From 2eaeaa2985e9a7a7cf022cd3cfe60744ed0e654c Mon Sep 17 00:00:00 2001 From: bouillipx Date: Wed, 4 Mar 2026 10:55:49 +0800 Subject: [PATCH 1/2] feat(governance): complete traceability gate depth checks Finish tasks 3.2-3.4 for enhance-doc-governance-traceability by extending the governance traceability gate beyond feature index integrity. Key changes: - enforce required frontmatter on the governance baseline standard/design docs and all concrete TODO ledger records under docs/todos - require active feature docs with todo_ids to map those ids through a tasks artifact TODO Coverage section - validate master TODO and slice-planning change targets resolve back to concrete feature docs and tasks artifacts, while skipping planned placeholder claims - add red/green regressions for frontmatter enforcement, task coverage, reverse TODO mapping, and archive-path edge cases - backfill the affected governance and TODO docs with canonical frontmatter and add TODO Coverage to the agentscope D2/D4 pilot tasks file - sync OpenSpec task status and feature evidence so the change now sits at 21/22 tasks complete Rationale: The previous slice left three governance gaps open: non-feature docs were not machine-checked for frontmatter, TODO-linked feature slices were not forced to declare their task coverage, and master TODO ledgers could drift away from actual change artifacts in the reverse direction. This commit closes those gaps with deterministic shell checks and fixture-backed regressions without widening scope to unrelated runtime behavior. Verification: - ../../.venv/bin/python -m pytest -q tests/unit/test_governance_traceability_gate.py tests/unit/test_governance_evidence_truth_gate.py - ./scripts/ci/check_governance_traceability.sh - ./scripts/ci/check_governance_evidence_truth.sh - openspec validate enhance-doc-governance-traceability --type change --strict --json --no-interactive - openspec list --- ..._Reconstructability_Traceability_Matrix.md | 9 + .../enhance-doc-governance-traceability.md | 22 +- .../Documentation_Management_Model.md | 9 + docs/guides/Development_Constraints.md | 9 + .../Documentation_First_Development_SOP.md | 9 + .../Evidence_Truth_Implementation_Strategy.md | 9 + ..._design_reconstructability_gap_analysis.md | 9 + ...2-27_design_reconstructability_gap_todo.md | 9 + ...6-02-27_full_design_review_gap_analysis.md | 9 + .../2026-02-27_full_design_review_gap_todo.md | 9 + .../agentscope_domain_execution_todos.md | 9 + .../2026-02-27_design_code_gap_analysis.md | 9 + .../2026-02-27_design_code_gap_todo.md | 9 + docs/todos/project_overall_todos.md | 9 + .../tasks.md | 5 + .../tasks.md | 9 +- scripts/ci/check_governance_traceability.sh | 201 +++++++++++++++++- .../unit/test_governance_traceability_gate.py | 192 +++++++++++++++-- 18 files changed, 518 insertions(+), 28 deletions(-) diff --git a/docs/design/Design_Reconstructability_Traceability_Matrix.md b/docs/design/Design_Reconstructability_Traceability_Matrix.md index fc6b33ce..8615f5af 100644 --- a/docs/design/Design_Reconstructability_Traceability_Matrix.md +++ b/docs/design/Design_Reconstructability_Traceability_Matrix.md @@ -1,3 +1,12 @@ +--- +change_ids: ["enhance-doc-governance-traceability"] +doc_kind: design +topics: ["design-reconstructability", "traceability", "governance"] +created: 2026-02-27 +updated: 2026-03-04 +status: active +--- + # 设计可重建性追踪矩阵(Doc -> Code -> Test) > 更新时间:2026-02-27 diff --git a/docs/features/enhance-doc-governance-traceability.md b/docs/features/enhance-doc-governance-traceability.md index bd661441..bcac1b76 100644 --- a/docs/features/enhance-doc-governance-traceability.md +++ b/docs/features/enhance-doc-governance-traceability.md @@ -36,8 +36,8 @@ Unify documentation management structure, lifecycle governance, and SOP-to-skill - `openspec validate enhance-doc-governance-traceability --type change --strict --json --no-interactive` ### Results -- `../../.venv/bin/python -m pytest -q tests/unit/test_governance_traceability_gate.py tests/unit/test_governance_evidence_truth_gate.py`: passed (`50 passed`) after extending the traceability gate regression suite to also cover stale active index entries, `Active Entries`-only membership checks, explicit checkpoint-to-skill pair rows, active/archive index path-family enforcement, README index-file exclusion for both active and archived entries, discrete `todo_ids` token matching, Claim Ledger-only TODO/change validation, same-record TODO/change validation, claim-scope range resolution, range-only claim-scope resolution without explicit todo tokens, full lifecycle checkpoint coverage, and date-prefixed archived change task discovery. -- `./scripts/ci/check_governance_traceability.sh`: passed against the real repository tree after tightening active/archive index membership to canonical sections, rejecting index entries outside the correct feature-doc path family, excluding `docs/features/README.md` and `docs/features/archive/README.md` from valid feature-entry targets, requiring explicit checkpoint-to-skill pair rows in Section 7, and resolving pilot `todo_ids` only through Claim Ledger records, including same-claim scope ranges where the TODO id is only implied by the claim range. +- `../../.venv/bin/python -m pytest -q tests/unit/test_governance_traceability_gate.py tests/unit/test_governance_evidence_truth_gate.py`: passed (`53 passed`) after extending the traceability gate regression suite to cover governance standard/design/TODO frontmatter enforcement, active-feature `## TODO Coverage` checks in tasks artifacts, master TODO reverse mapping to concrete feature/tasks targets, stale active index entries, `Active Entries`-only membership checks, explicit checkpoint-to-skill pair rows, active/archive index path-family enforcement, README index-file exclusion for both active and archived entries, discrete `todo_ids` token matching, Claim Ledger-only TODO/change validation, same-record TODO/change validation, claim-scope range resolution, range-only claim-scope resolution without explicit todo tokens, full lifecycle checkpoint coverage, and date-prefixed archived change task discovery. +- `./scripts/ci/check_governance_traceability.sh`: passed against the real repository tree after tightening active/archive index membership to canonical sections, rejecting index entries outside the correct feature-doc path family, excluding `docs/features/README.md` and `docs/features/archive/README.md` from valid feature-entry targets, enforcing baseline frontmatter on governance standard/design docs plus concrete TODO ledgers, requiring explicit checkpoint-to-skill pair rows in Section 7, requiring active features with `todo_ids` to declare `## TODO Coverage` in their tasks artifact, and resolving Claim Ledger / slice-plan change targets back to concrete feature docs and tasks artifacts while skipping `planned` placeholder claims. - `./scripts/ci/check_governance_evidence_truth.sh`: passed, confirming the new traceability assets do not break the existing evidence-first contract. - `openspec validate enhance-doc-governance-traceability --type change --strict --json --no-interactive`: passed (`1/1` change valid, `0` issues). @@ -50,6 +50,11 @@ Unify documentation management structure, lifecycle governance, and SOP-to-skill - `docs/features/templates/feature_aggregation_template.md` - `docs/features/README.md` - `docs/features/archive/README.md` +- `docs/governance/Documentation_Management_Model.md` +- `docs/guides/Documentation_First_Development_SOP.md` +- `docs/todos/project_overall_todos.md` +- `docs/todos/agentscope_domain_execution_todos.md` +- `openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md` - `scripts/ci/check_governance_traceability.sh` - `tests/unit/test_governance_traceability_gate.py` - `docs/features/agentscope-d2-d4-thinking-transport.md` @@ -69,17 +74,18 @@ Unify documentation management structure, lifecycle governance, and SOP-to-skill ### Structured Review Report - Changed Module Boundaries / Public API: governance scope only; no new runtime public API added. -- New State: adds one new repository gate script, one new gate test file, and canonical docs/index/template assets under `docs/features/`. +- New State: expands the repository traceability gate, adds frontmatter to the baseline governance standard/design/TODO docs, and adds `## TODO Coverage` mapping to the pilot tasks artifact under `openspec/changes/agentscope-d2-d4-thinking-transport/`. - Concurrency / Timeout / Retry: no concurrency change; gate runs are single-process document scans with deterministic rerun behavior after fixes. - Side Effects and Idempotency: side effects are limited to CI/log output; repeated runs are idempotent against unchanged docs. -- Coverage and Residual Risk: template/index/skill-mapping/TODO-linkage checks are covered; residual risk is that broader frontmatter enforcement across `docs/guides/**` and `docs/design/**` is still pending. +- Coverage and Residual Risk: template/index/skill-mapping/frontmatter/TODO-linkage/master-TODO-change-target checks are covered for the governance baseline docs and concrete TODO ledgers; residual risk is that broader standard/design families outside this baseline set are not yet auto-enforced. ### Behavior Verification -- Happy path: the repository now has a canonical feature aggregation template, explicit active/archive feature indexes, and a green traceability gate that resolves a pilot feature doc back to its TODO ledger and owning change-id through Claim Ledger records, including scope ranges such as `D2-1~D2-4, D4-1~D4-4`, even when the concrete TODO id does not appear elsewhere in the file. -- Error/fallback path: the new gate fails deterministically when a feature doc is missing from the `## Active Entries` section, when an active/archive index entry points at the wrong doc family, when Section 7 keeps checkpoint names but drops the actual `checkpoint -> skill` mapping rows, or when `todo_ids` and `change_ids` only co-occur in detail-board/prose lines without a matching Claim Ledger record. +- Happy path: the repository now has a canonical feature aggregation template, explicit active/archive feature indexes, governance baseline docs with structured frontmatter, and a green traceability gate that resolves a pilot feature doc back to its TODO ledger, owning change-id, and tasks coverage through Claim Ledger records plus `## TODO Coverage` ranges such as `D2-1~D2-4, D4-1~D4-4`. +- Error/fallback path: the gate now fails deterministically when a governance standard/TODO doc drops frontmatter, when an active feature declares `todo_ids` but its tasks artifact omits `## TODO Coverage`, when a master TODO slice table points to a non-existent change target, when a feature doc is missing from `## Active Entries`, when an active/archive index entry points at the wrong doc family, when Section 7 keeps checkpoint names but drops the actual `checkpoint -> skill` mapping rows, or when `todo_ids` and `change_ids` only co-occur in detail-board/prose lines without a matching Claim Ledger record. ### Risks and Rollback -- Risk: `3.2-3.4` are still open, so the new gate does not yet enforce full frontmatter coverage for every governance-tracked doc family or full master-TODO/task completeness. +- Risk: frontmatter auto-enforcement is still scoped to the governance baseline standard/design docs and concrete TODO ledgers, not every standard/design file in the repository. +- Risk: `planned` Claim Ledger rows are intentionally excluded from reverse mapping checks until a concrete feature/tasks artifact exists, so future placeholder drift still depends on later activation checks. - Risk: active/archive indexes are now explicit manual ledgers, so closeout changes that forget to update them will fail the new gate. - Rollback: remove `governance-traceability` from `.github/workflows/ci-gate.yml` and revert the template/index additions if the new gate produces unexpected false positives. @@ -103,4 +109,4 @@ Unify documentation management structure, lifecycle governance, and SOP-to-skill - `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/175#discussion_r2881421738` ## Next Milestone -Implement the remaining CI depth tasks: widen frontmatter enforcement beyond feature docs and add machine-checkable TODO/task and master-TODO/change-slice consistency checks before closeout. +Complete `5.3` closeout: update TODO/archive records, archive `enhance-doc-governance-traceability`, and move the feature evidence into `docs/features/archive/`. diff --git a/docs/governance/Documentation_Management_Model.md b/docs/governance/Documentation_Management_Model.md index afe10ef8..489e2143 100644 --- a/docs/governance/Documentation_Management_Model.md +++ b/docs/governance/Documentation_Management_Model.md @@ -1,3 +1,12 @@ +--- +change_ids: ["enhance-doc-governance-traceability"] +doc_kind: standard +topics: ["documentation-governance", "traceability", "skills"] +created: 2026-02-28 +updated: 2026-03-04 +status: active +--- + # Documentation Management Model > Scope: Repository-wide documentation governance for design, analysis, feature lifecycle, standards, temporary notes, and archive. diff --git a/docs/guides/Development_Constraints.md b/docs/guides/Development_Constraints.md index eefcdc69..678b1d27 100644 --- a/docs/guides/Development_Constraints.md +++ b/docs/guides/Development_Constraints.md @@ -1,3 +1,12 @@ +--- +change_ids: ["enhance-doc-governance-traceability"] +doc_kind: standard +topics: ["development-constraints", "governance", "workflow"] +created: 2026-02-28 +updated: 2026-03-04 +status: active +--- + # DARE 开发约束(面向 AI/Human 开发者) 适用对象:在本仓库编写代码的所有开发者(含 Codex、Claude 等 AI Agent)。目标:在不破坏架构的前提下,产出简洁、可验证、可维护的代码。 diff --git a/docs/guides/Documentation_First_Development_SOP.md b/docs/guides/Documentation_First_Development_SOP.md index ea839139..d1d8b44a 100644 --- a/docs/guides/Documentation_First_Development_SOP.md +++ b/docs/guides/Documentation_First_Development_SOP.md @@ -1,3 +1,12 @@ +--- +change_ids: ["enhance-doc-governance-traceability"] +doc_kind: standard +topics: ["documentation-governance", "sop", "workflow"] +created: 2026-02-28 +updated: 2026-03-04 +status: active +--- + # 文档先行开发 SOP(强制执行) > 适用范围:本仓库所有开发活动(AI Agent + Human),包含 Bug 修复、新增 Feature、重构。 diff --git a/docs/guides/Evidence_Truth_Implementation_Strategy.md b/docs/guides/Evidence_Truth_Implementation_Strategy.md index 7fc27022..e81511b4 100644 --- a/docs/guides/Evidence_Truth_Implementation_Strategy.md +++ b/docs/guides/Evidence_Truth_Implementation_Strategy.md @@ -1,3 +1,12 @@ +--- +change_ids: ["enhance-doc-governance-traceability"] +doc_kind: standard +topics: ["evidence-truth", "governance", "review"] +created: 2026-02-28 +updated: 2026-03-04 +status: active +--- + # Evidence Truth Implementation Strategy > Scope: Governance changes that use `docs/features/*.md` as aggregation entry documents. diff --git a/docs/todos/2026-02-27_design_reconstructability_gap_analysis.md b/docs/todos/2026-02-27_design_reconstructability_gap_analysis.md index de764cb7..43c18b21 100644 --- a/docs/todos/2026-02-27_design_reconstructability_gap_analysis.md +++ b/docs/todos/2026-02-27_design_reconstructability_gap_analysis.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: analysis +topics: ["design-reconstructability", "gap-analysis", "governance"] +created: 2026-02-27 +updated: 2026-03-04 +status: active +--- + # 2026-02-27 设计文档可重建性 Gap 分析(P0/P1,闭环回写版) > 目标:评估“仅保留 docs 资产,能否重建当前实现主能力”。 diff --git a/docs/todos/2026-02-27_design_reconstructability_gap_todo.md b/docs/todos/2026-02-27_design_reconstructability_gap_todo.md index 8ec71d98..86aa4b8c 100644 --- a/docs/todos/2026-02-27_design_reconstructability_gap_todo.md +++ b/docs/todos/2026-02-27_design_reconstructability_gap_todo.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: todo +topics: ["design-reconstructability", "todo", "governance"] +created: 2026-02-27 +updated: 2026-03-04 +status: active +--- + # 2026-02-27 可重建性 Gap TODO(P0/P1) > 来源:`docs/todos/2026-02-27_design_reconstructability_gap_analysis.md` diff --git a/docs/todos/2026-02-27_full_design_review_gap_analysis.md b/docs/todos/2026-02-27_full_design_review_gap_analysis.md index 91d291f0..31682150 100644 --- a/docs/todos/2026-02-27_full_design_review_gap_analysis.md +++ b/docs/todos/2026-02-27_full_design_review_gap_analysis.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: analysis +topics: ["design-review", "gap-analysis", "architecture"] +created: 2026-02-27 +updated: 2026-03-04 +status: active +--- + # 2026-02-27 全量设计文档 Review:Design/Code Gap Analysis(第二轮刷新) > 类型:完整评审(非最小补充) diff --git a/docs/todos/2026-02-27_full_design_review_gap_todo.md b/docs/todos/2026-02-27_full_design_review_gap_todo.md index 147e22b0..af4fc35d 100644 --- a/docs/todos/2026-02-27_full_design_review_gap_todo.md +++ b/docs/todos/2026-02-27_full_design_review_gap_todo.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: todo +topics: ["design-review", "todo", "architecture"] +created: 2026-02-27 +updated: 2026-03-04 +status: active +--- + # 2026-02-27 全量设计文档 Review:TODO 清单(第二轮刷新) > 来源:`docs/todos/2026-02-27_full_design_review_gap_analysis.md` diff --git a/docs/todos/agentscope_domain_execution_todos.md b/docs/todos/agentscope_domain_execution_todos.md index 85b75a33..8051e175 100644 --- a/docs/todos/agentscope_domain_execution_todos.md +++ b/docs/todos/agentscope_domain_execution_todos.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: todo +topics: ["agentscope", "domain-execution", "todo"] +created: 2026-03-02 +updated: 2026-03-04 +status: active +--- + # AgentScope 迁移 Domain 执行清单(详细设计输入版,4人协同) > 更新日期:2026-03-02 diff --git a/docs/todos/archive/2026-02-27_design_code_gap_analysis.md b/docs/todos/archive/2026-02-27_design_code_gap_analysis.md index fd422159..85c9fbe5 100644 --- a/docs/todos/archive/2026-02-27_design_code_gap_analysis.md +++ b/docs/todos/archive/2026-02-27_design_code_gap_analysis.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: analysis +topics: ["design-code-gap", "analysis", "governance"] +created: 2026-02-27 +updated: 2026-03-04 +status: archived +--- + # 设计文档与代码实现 Gap 分析(基线) > 日期:2026-02-27 diff --git a/docs/todos/archive/2026-02-27_design_code_gap_todo.md b/docs/todos/archive/2026-02-27_design_code_gap_todo.md index 06d0f5fa..3a2053ec 100644 --- a/docs/todos/archive/2026-02-27_design_code_gap_todo.md +++ b/docs/todos/archive/2026-02-27_design_code_gap_todo.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: todo +topics: ["design-code-gap", "todo", "governance"] +created: 2026-02-27 +updated: 2026-03-04 +status: archived +--- + # 设计-实现 Gap 修复 TODO(由 2026-02-27 分析生成) > 来源分析:`docs/todos/archive/2026-02-27_design_code_gap_analysis.md` diff --git a/docs/todos/project_overall_todos.md b/docs/todos/project_overall_todos.md index 46307e1d..1c9597fb 100644 --- a/docs/todos/project_overall_todos.md +++ b/docs/todos/project_overall_todos.md @@ -1,3 +1,12 @@ +--- +change_ids: [] +doc_kind: todo +topics: ["project-roadmap", "governance", "todo"] +created: 2026-02-25 +updated: 2026-03-04 +status: active +--- + # DARE Framework 项目总体 TODO > 更新时间:2026-03-02 diff --git a/openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md b/openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md index cc31c3d1..847754e3 100644 --- a/openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md +++ b/openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md @@ -1,3 +1,8 @@ +## TODO Coverage + +- D2-1~D2-4 +- D4-1~D4-4 + ## 1. Transport contract and schema alignment (D2) - [x] 1.1 Extend transport canonical event taxonomy to cover `message/tool_call/tool_result/thinking/error/status` with compatibility normalization for legacy aliases. diff --git a/openspec/changes/enhance-doc-governance-traceability/tasks.md b/openspec/changes/enhance-doc-governance-traceability/tasks.md index 85dd3b6f..c79bb444 100644 --- a/openspec/changes/enhance-doc-governance-traceability/tasks.md +++ b/openspec/changes/enhance-doc-governance-traceability/tasks.md @@ -28,9 +28,12 @@ - [x] 3.1 Implement or extend CI checks to validate aggregation entry existence when governance-scoped files change. Evidence: `scripts/ci/check_governance_traceability.sh`, `tests/unit/test_governance_traceability_gate.py`, and `.github/workflows/ci-gate.yml`. -- [ ] 3.2 Implement or extend CI checks to validate required frontmatter fields for governance-tracked docs. -- [ ] 3.3 Implement or extend CI checks to validate gap/TODO -> OpenSpec task mapping completeness. -- [ ] 3.4 Implement or extend CI checks to validate master TODO -> OpenSpec change-slice mapping consistency. +- [x] 3.2 Implement or extend CI checks to validate required frontmatter fields for governance-tracked docs. + Evidence: `scripts/ci/check_governance_traceability.sh` now validates required frontmatter on the governance baseline standard/design docs plus all concrete `docs/todos/**/*.md` records, and the corresponding docs now declare canonical frontmatter blocks. +- [x] 3.3 Implement or extend CI checks to validate gap/TODO -> OpenSpec task mapping completeness. + Evidence: `scripts/ci/check_governance_traceability.sh` now requires active feature docs with `todo_ids` to be covered by a `## TODO Coverage` section in their tasks artifact; `openspec/changes/agentscope-d2-d4-thinking-transport/tasks.md` provides the pilot coverage mapping and `tests/unit/test_governance_traceability_gate.py` locks the contract. +- [x] 3.4 Implement or extend CI checks to validate master TODO -> OpenSpec change-slice mapping consistency. + Evidence: `scripts/ci/check_governance_traceability.sh` now resolves Claim Ledger / slice-plan change targets back to concrete feature docs and tasks artifacts, while skipping `planned` placeholder claims; `tests/unit/test_governance_traceability_gate.py` covers stale slice target failures. - [x] 3.5 Implement evidence truth structural gate (`scripts/ci/check_governance_evidence_truth.sh`) and wire it into `ci-gate`. Evidence: `scripts/ci/check_governance_evidence_truth.sh`, `tests/unit/test_governance_evidence_truth_gate.py`, and `.github/workflows/ci-gate.yml`. diff --git a/scripts/ci/check_governance_traceability.sh b/scripts/ci/check_governance_traceability.sh index 6da5b8c6..aa8a2d4a 100755 --- a/scripts/ci/check_governance_traceability.sh +++ b/scripts/ci/check_governance_traceability.sh @@ -166,6 +166,17 @@ extract_markdown_section_matching() { ' "$file" } +extract_first_markdown_table_from_section_matching() { + local file="$1" + local pattern="$2" + awk -v pattern="$pattern" ' + $0 ~ /^##[[:space:]]+/ && $0 ~ pattern {in_section=1; next} + in_section && /^##[[:space:]]+/ {exit} + in_section && $0 ~ /^\|/ {in_table=1; print; next} + in_table {exit} + ' "$file" +} + escape_extended_regex() { printf '%s' "$1" | sed -E 's/[][(){}.^$*+?|\\/]/\\&/g' } @@ -275,7 +286,7 @@ claim_ledger_has_tokens_in_same_record() { if [[ -n "$scope_field" ]] && scope_contains_todo_id "$scope_field" "$first_token"; then return 0 fi - done < <(extract_markdown_section_matching "$file" "Claim Ledger") + done < <(extract_first_markdown_table_from_section_matching "$file" "Claim Ledger") return 1 } @@ -380,10 +391,173 @@ check_checkpoint_skill_mapping() { fi } +check_governance_doc_frontmatter() { + local file="$1" + local expected_doc_kind="$2" + local frontmatter key actual_doc_kind mode + + frontmatter="$(extract_frontmatter "$file")" + if [[ -z "$frontmatter" ]]; then + log "missing frontmatter in $file" + failures=$((failures + 1)) + return + fi + + for key in change_ids doc_kind topics created updated status; do + if [[ -z "$(frontmatter_scalar "$frontmatter" "$key")" ]]; then + log "missing required frontmatter field '$key' in $file" + failures=$((failures + 1)) + fi + done + + actual_doc_kind="$(trim_quotes "$(frontmatter_scalar "$frontmatter" "doc_kind")")" + if [[ -n "$expected_doc_kind" && "$actual_doc_kind" != "$expected_doc_kind" ]]; then + log "unexpected doc_kind in $file: expected $expected_doc_kind" + failures=$((failures + 1)) + fi + + mode="$(trim_quotes "$(frontmatter_scalar "$frontmatter" "mode")")" + if [[ "$mode" == "todo_fallback" && -z "$(frontmatter_scalar "$frontmatter" "topic_slug")" ]]; then + log "missing required frontmatter field 'topic_slug' in $file" + failures=$((failures + 1)) + fi +} + +check_governance_tracked_frontmatter() { + local file expected_doc_kind + + for file in \ + docs/governance/Documentation_Management_Model.md \ + docs/guides/Documentation_First_Development_SOP.md \ + docs/guides/Development_Constraints.md \ + docs/guides/Evidence_Truth_Implementation_Strategy.md; do + [[ -f "$file" ]] && check_governance_doc_frontmatter "$file" "standard" + done + + if [[ -f "docs/design/Design_Reconstructability_Traceability_Matrix.md" ]]; then + check_governance_doc_frontmatter "docs/design/Design_Reconstructability_Traceability_Matrix.md" "design" + fi + + while IFS= read -r file; do + expected_doc_kind="todo" + [[ "$file" == *"_gap_analysis.md" ]] && expected_doc_kind="analysis" + check_governance_doc_frontmatter "$file" "$expected_doc_kind" + done < <(find docs/todos -type f -name '*.md' ! -name 'README.md' ! -path 'docs/todos/templates/*' | sort) +} + +normalize_table_cell() { + local value="$1" + value="${value//\`/}" + trim_whitespace "$value" +} + +is_placeholder_change_id() { + local compact="${1//[[:space:]]/}" + case "$compact" in + ""|"N/A"|"n/a"|"pending"|"---"|"OpenSpecChange"|"PlannedOpenSpecChange"|"建议OpenSpecChange") + return 0 + ;; + esac + return 1 +} + +resolve_change_tasks_file() { + local change_id="$1" + if [[ -f "openspec/changes/$change_id/tasks.md" ]]; then + echo "openspec/changes/$change_id/tasks.md" + return 0 + fi + + if [[ ! -d "openspec/changes/archive" ]]; then + return 1 + fi + + find openspec/changes/archive -type f \ + \( -path "*/$change_id/tasks.md" -o -path "*/????-??-??-$change_id/tasks.md" \) \ + | head -n 1 +} + +resolve_feature_doc_file() { + local change_id="$1" + if [[ -f "docs/features/$change_id.md" ]]; then + echo "docs/features/$change_id.md" + return 0 + fi + if [[ -f "docs/features/archive/$change_id.md" ]]; then + echo "docs/features/archive/$change_id.md" + return 0 + fi + return 1 +} + +tasks_file_has_todo_coverage() { + local file="$1" + local todo_id="$2" + local line candidate + + while IFS= read -r line; do + candidate="$(sed -E 's/^[[:space:]]*[-|][[:space:]]*//; s/`//g' <<<"$line")" + candidate="$(trim_whitespace "$candidate")" + [[ -z "$candidate" ]] && continue + if text_has_discrete_token "$candidate" "$todo_id"; then + return 0 + fi + if scope_contains_todo_id "$candidate" "$todo_id"; then + return 0 + fi + done < <(extract_markdown_section_matching "$file" "TODO Coverage") + + return 1 +} + +check_todo_change_mapping_target() { + local source_file="$1" + local change_id="$2" + + if is_placeholder_change_id "$change_id"; then + return + fi + + if [[ -z "$(resolve_feature_doc_file "$change_id" || true)" ]]; then + log "missing feature aggregation doc for TODO change mapping in $source_file: $change_id" + failures=$((failures + 1)) + fi + + if [[ -z "$(resolve_change_tasks_file "$change_id" || true)" ]]; then + log "missing OpenSpec tasks artifact for TODO change mapping in $source_file: $change_id" + failures=$((failures + 1)) + fi +} + +check_master_todo_change_slice_mappings() { + local file line change_id status_value + + while IFS= read -r file; do + while IFS= read -r line; do + [[ "$line" == \|* ]] || continue + status_value="$(awk -F'|' 'NF >= 6 {field=$5; gsub(/^[[:space:]]+|[[:space:]]+$/, "", field); print field}' <<<"$line")" + status_value="$(normalize_table_cell "$status_value")" + if [[ "$status_value" == "planned" ]]; then + continue + fi + change_id="$(awk -F'|' 'NF >= 9 {field=$8; gsub(/^[[:space:]]+|[[:space:]]+$/, "", field); print field}' <<<"$line")" + change_id="$(normalize_table_cell "$change_id")" + check_todo_change_mapping_target "$file" "$change_id" + done < <(extract_first_markdown_table_from_section_matching "$file" "Claim Ledger") + + while IFS= read -r line; do + [[ "$line" == \|* ]] || continue + change_id="$(awk -F'|' 'NF >= 5 {field=$4; gsub(/^[[:space:]]+|[[:space:]]+$/, "", field); print field}' <<<"$line")" + change_id="$(normalize_table_cell "$change_id")" + check_todo_change_mapping_target "$file" "$change_id" + done < <(extract_first_markdown_table_from_section_matching "$file" "切片规划|Slice Plan") + done < <(find docs/todos -type f -name '*.md' ! -name 'README.md' ! -path 'docs/todos/templates/*' | sort) +} + check_feature_doc() { local file="$1" local frontmatter mode doc_kind key change_id todo_id matched candidate - local change_ids_raw todo_ids_raw + local change_ids_raw todo_ids_raw tasks_file task_checked task_covered frontmatter="$(extract_frontmatter "$file")" if [[ -z "$frontmatter" ]]; then @@ -423,8 +597,7 @@ check_feature_doc() { while IFS= read -r change_id; do [[ -z "$change_id" ]] && continue - if [[ ! -f "openspec/changes/$change_id/tasks.md" ]] && \ - ! find openspec/changes/archive -type f \( -path "*/$change_id/tasks.md" -o -path "*/????-??-??-$change_id/tasks.md" \) | grep -q .; then + if [[ -z "$(resolve_change_tasks_file "$change_id" || true)" ]]; then log "missing OpenSpec tasks artifact for change_id '$change_id' declared in $file" failures=$((failures + 1)) fi @@ -456,11 +629,31 @@ check_feature_doc() { log "missing TODO mapping for feature doc $file: $todo_id" failures=$((failures + 1)) fi + + task_checked=0 + task_covered=0 + while IFS= read -r change_id; do + [[ -z "$change_id" ]] && continue + tasks_file="$(resolve_change_tasks_file "$change_id" || true)" + [[ -z "$tasks_file" ]] && continue + task_checked=1 + if tasks_file_has_todo_coverage "$tasks_file" "$todo_id"; then + task_covered=1 + break + fi + done <<<"$change_ids_raw" + + if [[ "$task_checked" -eq 1 && "$task_covered" -eq 0 ]]; then + log "missing TODO coverage in tasks artifact for feature doc $file: $todo_id" + failures=$((failures + 1)) + fi done <<<"$todo_ids_raw" } check_feature_indexes check_checkpoint_skill_mapping +check_governance_tracked_frontmatter +check_master_todo_change_slice_mappings while IFS= read -r file; do check_feature_doc "$file" diff --git a/tests/unit/test_governance_traceability_gate.py b/tests/unit/test_governance_traceability_gate.py index 410abff9..9b0586c9 100644 --- a/tests/unit/test_governance_traceability_gate.py +++ b/tests/unit/test_governance_traceability_gate.py @@ -51,6 +51,26 @@ - Review thread: https://github.com/example/repo/pull/2#discussion_r1 """ +TODO_DOC_FRONTMATTER = """--- +change_ids: [] +doc_kind: todo +topics: ["governance", "todo"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- +""" + +STANDARD_DOC_FRONTMATTER = """--- +change_ids: ["demo-change"] +doc_kind: standard +topics: ["governance", "traceability"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- +""" + def _write(path: Path, content: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) @@ -107,20 +127,50 @@ def _base_tree(root: Path) -> None: _write(root / "docs" / "features" / "demo-change.md", FEATURE_DOC) _write( root / "docs" / "todos" / "demo_master_todo.md", - """# Demo TODO + """--- +change_ids: [] +doc_kind: todo +topics: ["governance", "todo"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | |---|---|---|---|---|---|---|---| | CLM-DEMO | D2-1~D2-2 | demo | active | 2026-03-03 | 2026-03-10 | `demo-change` | demo | + +## 切片规划 +| Slice | 目标 | 建议 OpenSpec Change | 主要覆盖 TODO | +|---|---|---|---| +| Slice A | demo | `demo-change` | D2-1, D2-2 | """, ) _write(root / "openspec" / "changes" / "demo-change" / "proposal.md", "# proposal\n") _write(root / "openspec" / "changes" / "demo-change" / "design.md", "# design\n") - _write(root / "openspec" / "changes" / "demo-change" / "tasks.md", "- [ ] demo\n") + _write( + root / "openspec" / "changes" / "demo-change" / "tasks.md", + """## TODO Coverage +- D2-1~D2-2 + +- [ ] demo +""", + ) _write( root / "docs" / "governance" / "Documentation_Management_Model.md", - """# Documentation Management Model + """--- +change_ids: ["demo-change"] +doc_kind: standard +topics: ["governance", "traceability"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Documentation Management Model ## 7. Checkpoint-to-Skill Mapping - kickoff -> `development-workflow` + `documentation-management` @@ -128,6 +178,62 @@ def _base_tree(root: Path) -> None: - verification -> `development-workflow` - review-merge-gate -> `development-workflow` + `documentation-management` - completion-archive -> `development-workflow` + `documentation-management` +""", + ) + _write( + root / "docs" / "guides" / "Documentation_First_Development_SOP.md", + """--- +change_ids: ["demo-change"] +doc_kind: standard +topics: ["governance", "sop"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Demo SOP +""", + ) + _write( + root / "docs" / "guides" / "Development_Constraints.md", + """--- +change_ids: ["demo-change"] +doc_kind: standard +topics: ["governance", "constraints"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Demo Constraints +""", + ) + _write( + root / "docs" / "guides" / "Evidence_Truth_Implementation_Strategy.md", + """--- +change_ids: ["demo-change"] +doc_kind: standard +topics: ["governance", "evidence"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Demo Evidence Truth +""", + ) + _write( + root / "docs" / "design" / "Design_Reconstructability_Traceability_Matrix.md", + """--- +change_ids: ["demo-change"] +doc_kind: design +topics: ["governance", "traceability"] +created: 2026-03-03 +updated: 2026-03-03 +status: active +--- + +# Demo Matrix """, ) _write(root / ".codex" / "skills" / "documentation-management" / "SKILL.md", "# doc skill\n") @@ -261,10 +367,23 @@ def mutate(root: Path) -> None: self.assertNotEqual(result.returncode, 0) self.assertIn("invalid archived feature index entry path", result.stdout) + def test_gate_requires_frontmatter_for_governance_standard_and_todo_docs(self) -> None: + def mutate(root: Path) -> None: + todo_doc = root / "docs" / "todos" / "demo_master_todo.md" + todo_doc.write_text(todo_doc.read_text(encoding="utf-8").split("---\n", 2)[2], encoding="utf-8") + sop_doc = root / "docs" / "guides" / "Documentation_First_Development_SOP.md" + sop_doc.write_text(sop_doc.read_text(encoding="utf-8").split("---\n", 2)[2], encoding="utf-8") + + result = self._run_gate(mutate) + + self.assertNotEqual(result.returncode, 0) + self.assertIn("missing frontmatter in docs/todos/demo_master_todo.md", result.stdout) + self.assertIn("missing frontmatter in docs/guides/Documentation_First_Development_SOP.md", result.stdout) + def test_gate_fails_when_checkpoint_skill_mapping_is_missing(self) -> None: def mutate(root: Path) -> None: model = root / "docs" / "governance" / "Documentation_Management_Model.md" - model.write_text("# Documentation Management Model\n", encoding="utf-8") + model.write_text(f"{STANDARD_DOC_FRONTMATTER}\n# Documentation Management Model\n", encoding="utf-8") result = self._run_gate(mutate) @@ -275,7 +394,8 @@ def test_gate_requires_all_declared_lifecycle_checkpoints(self) -> None: def mutate(root: Path) -> None: model = root / "docs" / "governance" / "Documentation_Management_Model.md" model.write_text( - """# Documentation Management Model + f"""{STANDARD_DOC_FRONTMATTER} +# Documentation Management Model ## 7. Checkpoint-to-Skill Mapping - kickoff -> `development-workflow` + `documentation-management` @@ -295,7 +415,8 @@ def test_gate_requires_explicit_checkpoint_to_skill_pairs(self) -> None: def mutate(root: Path) -> None: model = root / "docs" / "governance" / "Documentation_Management_Model.md" model.write_text( - """# Documentation Management Model + f"""{STANDARD_DOC_FRONTMATTER} +# Documentation Management Model ## 7. Checkpoint-to-Skill Mapping @@ -320,7 +441,10 @@ def mutate(root: Path) -> None: def test_gate_fails_when_declared_todo_id_has_no_matching_todo_ledger(self) -> None: def mutate(root: Path) -> None: - (root / "docs" / "todos" / "demo_master_todo.md").write_text("# empty\n", encoding="utf-8") + (root / "docs" / "todos" / "demo_master_todo.md").write_text( + f"{TODO_DOC_FRONTMATTER}\n# empty\n", + encoding="utf-8", + ) result = self._run_gate(mutate) @@ -336,7 +460,8 @@ def mutate(root: Path) -> None: ) todo_doc = root / "docs" / "todos" / "demo_master_todo.md" todo_doc.write_text( - """# Demo TODO + f"""{TODO_DOC_FRONTMATTER} +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | @@ -360,7 +485,8 @@ def mutate(root: Path) -> None: ) todo_doc = root / "docs" / "todos" / "demo_master_todo.md" todo_doc.write_text( - """# Demo TODO + f"""{TODO_DOC_FRONTMATTER} +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | @@ -385,7 +511,8 @@ def mutate(root: Path) -> None: ) todo_doc = root / "docs" / "todos" / "demo_master_todo.md" todo_doc.write_text( - """# Demo TODO + f"""{TODO_DOC_FRONTMATTER} +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | @@ -423,7 +550,7 @@ def mutate(root: Path) -> None: active_change_dir.rmdir() _write( root / "openspec" / "changes" / "archive" / "2026-03-03-archived-change" / "tasks.md", - "- [x] archived\n", + "## TODO Coverage\n- D2-1~D2-2\n\n- [x] archived\n", ) result = self._run_gate(mutate) @@ -435,7 +562,8 @@ def test_gate_accepts_todo_ids_covered_by_claim_scope_for_same_change(self) -> N def mutate(root: Path) -> None: todo_doc = root / "docs" / "todos" / "demo_master_todo.md" todo_doc.write_text( - """# Demo TODO + f"""{TODO_DOC_FRONTMATTER} +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | @@ -451,6 +579,11 @@ def mutate(root: Path) -> None: """, encoding="utf-8", ) + tasks_doc = root / "openspec" / "changes" / "demo-change" / "tasks.md" + tasks_doc.write_text( + "## TODO Coverage\n- D2-1~D2-4\n- D4-1~D4-4\n\n- [ ] demo\n", + encoding="utf-8", + ) feature_doc = root / "docs" / "features" / "demo-change.md" feature_doc.write_text( feature_doc.read_text(encoding="utf-8").replace( @@ -469,7 +602,8 @@ def test_gate_accepts_claim_scope_range_without_explicit_todo_token(self) -> Non def mutate(root: Path) -> None: todo_doc = root / "docs" / "todos" / "demo_master_todo.md" todo_doc.write_text( - """# Demo TODO + f"""{TODO_DOC_FRONTMATTER} +# Demo TODO ## Claim Ledger | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | @@ -484,6 +618,11 @@ def mutate(root: Path) -> None: """, encoding="utf-8", ) + tasks_doc = root / "openspec" / "changes" / "demo-change" / "tasks.md" + tasks_doc.write_text( + "## TODO Coverage\n- D2-1~D2-4\n- D4-1~D4-4\n\n- [ ] demo\n", + encoding="utf-8", + ) feature_doc = root / "docs" / "features" / "demo-change.md" feature_doc.write_text( feature_doc.read_text(encoding="utf-8").replace( @@ -498,6 +637,33 @@ def mutate(root: Path) -> None: self.assertEqual(result.returncode, 0) self.assertIn("passed", result.stdout) + def test_gate_requires_tasks_todo_coverage_for_active_feature_todo_ids(self) -> None: + def mutate(root: Path) -> None: + tasks_doc = root / "openspec" / "changes" / "demo-change" / "tasks.md" + tasks_doc.write_text("- [ ] demo\n", encoding="utf-8") + + result = self._run_gate(mutate) + + self.assertNotEqual(result.returncode, 0) + self.assertIn("missing TODO coverage in tasks artifact", result.stdout) + + def test_gate_requires_master_todo_slice_mapping_targets_to_exist(self) -> None: + def mutate(root: Path) -> None: + todo_doc = root / "docs" / "todos" / "demo_master_todo.md" + todo_doc.write_text( + todo_doc.read_text(encoding="utf-8").replace( + "| Slice A | demo | `demo-change` | D2-1, D2-2 |\n", + "| Slice A | demo | `demo-change` | D2-1, D2-2 |\n" + "| Slice B | drift | `missing-change` | D9-9 |\n", + ), + encoding="utf-8", + ) + + result = self._run_gate(mutate) + + self.assertNotEqual(result.returncode, 0) + self.assertIn("missing feature aggregation doc for TODO change mapping", result.stdout) + if __name__ == "__main__": unittest.main() From 086eb87fb359f26145e6c7ad2aa006507d221bcb Mon Sep 17 00:00:00 2001 From: bouillipx Date: Wed, 4 Mar 2026 11:49:14 +0800 Subject: [PATCH 2/2] docs(feature): record PR evidence for governance traceability depth checks Record the new implementation PR for the post-#175 traceability gate depth work in the active feature aggregation document. Key changes: - relabel earlier governance PRs as baseline/previous implementation references - point the current implementation PR link at #178 - preserve the active feature doc as the review and merge-gate source of truth Rationale: The branch was rebased onto the latest main before opening the new implementation PR. The feature aggregation document must reflect the current review surface so governance evidence and merge-gate history remain accurate and machine-checkable. Verification: - ./scripts/ci/check_governance_traceability.sh - ./scripts/ci/check_governance_evidence_truth.sh - openspec validate enhance-doc-governance-traceability --type change --strict --json --no-interactive --- docs/features/enhance-doc-governance-traceability.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/features/enhance-doc-governance-traceability.md b/docs/features/enhance-doc-governance-traceability.md index bcac1b76..c540eb86 100644 --- a/docs/features/enhance-doc-governance-traceability.md +++ b/docs/features/enhance-doc-governance-traceability.md @@ -91,8 +91,9 @@ Unify documentation management structure, lifecycle governance, and SOP-to-skill ### Review and Merge Gate Links - Intent PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/126` -- Implementation PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/137` -- Current implementation PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/175` +- Baseline implementation PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/137` +- Previous implementation PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/175` +- Current implementation PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/178` - Review request: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/126#issuecomment-3976690386` - Key owner feedback: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/126#issuecomment-3976707233` - Active fix threads: