From 53bd332bf3913cc1d210533f6a11b5ace908faad Mon Sep 17 00:00:00 2001 From: DTALEX66 <151195992+DTALEX66@users.noreply.github.com> Date: Sat, 15 Aug 2026 20:54:39 +0800 Subject: [PATCH] refactor(gate): single gate-selection authority, drop duplicate rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WL3-800 dedup (research subagent: 4-5 duplicate gate-selection rules). - impact_planner.py: drop the hardcoded critical prefixes (00-governance/**, .github/**, scripts/ci/**) — they are already covered by risk_zones.critical in the project profile; only unknown paths keep the fail-closed critical - emit_gate_plan.py: run_* outputs are generated from the profile `gates:` keys instead of a hardcoded 5-gate tuple — adding/renaming a gate no longer requires touching CI emit code - run_quality_gate.py: GATE_PATH_SCOPES is annotated as a local convenience mapping; the canonical authority is the profile `gates:` consumed by impact_planner + emit_gate_plan (CI never reads this table) Verification: 17 passed (impact planner / profile / gate vocabulary); 111 passed + 25 subtests (tests/ci, excluding env-dependent exact_tree_review); py_compile clean; CURRENT_STATE_FRESHNESS_PASS. --- 00-governance/generated/CURRENT_STATE.json | 6 +++--- 00-governance/generated/CURRENT_STATE.md | 6 +++--- .../scripts/workflow/impact_planner.py | 10 ++++------ .../scripts/workflow/run_quality_gate.py | 7 +++++-- scripts/ci/emit_gate_plan.py | 5 +++-- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/00-governance/generated/CURRENT_STATE.json b/00-governance/generated/CURRENT_STATE.json index cafd359..2da52df 100644 --- a/00-governance/generated/CURRENT_STATE.json +++ b/00-governance/generated/CURRENT_STATE.json @@ -1,7 +1,7 @@ { "schema_version": "work-lab-current-state/v1", - "generated_at": "2026-08-15T12:44:43.562105Z", - "source_digest": "cd6355e8621818b973d4277c6a4773f7c14e5aaf00f6fa548dc68415652b3608", + "generated_at": "2026-08-15T12:54:40.086382Z", + "source_digest": "62b331c21127d4b828ca6172e5d67f9756b2ef221cdff22e07247a060799e06f", "checkout_attestation": { "status": "RUNTIME_REQUIRED", "tracked_projection": "NO_HEAD_OR_BRANCH_CLAIM", @@ -219,5 +219,5 @@ "real_device_validation", "commercial_release" ], - "content_digest": "e3857b619b3cd604bbae67fb37f080a06cc3ba54d31ed122f74056db44370ac7" + "content_digest": "4f4ff1b61bd028872ac14c2852f6e2ef4a9357b26f5bf22a38317ceb511453f0" } diff --git a/00-governance/generated/CURRENT_STATE.md b/00-governance/generated/CURRENT_STATE.md index 503cbe7..ce8f899 100644 --- a/00-governance/generated/CURRENT_STATE.md +++ b/00-governance/generated/CURRENT_STATE.md @@ -1,8 +1,8 @@ # WORK-LAB current state -Generated at: `2026-08-15T12:44:43.562105Z` \ -Source digest: `cd6355e8621818b973d4277c6a4773f7c14e5aaf00f6fa548dc68415652b3608` \ -Content digest: `e3857b619b3cd604bbae67fb37f080a06cc3ba54d31ed122f74056db44370ac7` +Generated at: `2026-08-15T12:54:40.086382Z` \ +Source digest: `62b331c21127d4b828ca6172e5d67f9756b2ef221cdff22e07247a060799e06f` \ +Content digest: `4f4ff1b61bd028872ac14c2852f6e2ef4a9357b26f5bf22a38317ceb511453f0` ## Git and CI attestation diff --git a/10-workflow/workflow-assistance/scripts/workflow/impact_planner.py b/10-workflow/workflow-assistance/scripts/workflow/impact_planner.py index a7fe24f..6c92b87 100644 --- a/10-workflow/workflow-assistance/scripts/workflow/impact_planner.py +++ b/10-workflow/workflow-assistance/scripts/workflow/impact_planner.py @@ -96,12 +96,10 @@ def build_plan( affected.add(dependent) queue.append(dependent) - if unknown_paths or any( - path.startswith("00-governance/") - or path.startswith(".github/") - or path.startswith("scripts/ci/") - for path in changed_paths - ): + # critical prefixes (00-governance/**, .github/**, scripts/ci/**) are + # already covered by risk_zones.critical above; only unknown paths add a + # fail-closed critical here. + if unknown_paths: critical = True if critical: affected.update(gates) diff --git a/10-workflow/workflow-assistance/scripts/workflow/run_quality_gate.py b/10-workflow/workflow-assistance/scripts/workflow/run_quality_gate.py index 3097d89..02506ec 100644 --- a/10-workflow/workflow-assistance/scripts/workflow/run_quality_gate.py +++ b/10-workflow/workflow-assistance/scripts/workflow/run_quality_gate.py @@ -662,8 +662,11 @@ def run_gate_sequence(names: tuple[str, ...]) -> int: return 0 -# WLOSS-700: changed-files -> relevant gates. Small edits run only the gates -# whose path scope they touch; the full suite stays one command away. +# WLOSS-700: changed-files -> relevant gates (LOCAL convenience mapping only; +# the canonical gate-selection authority is 00-governance/work-lab.project-profile.yaml +# `gates:` consumed by impact_planner.py + scripts/ci/emit_gate_plan.py; CI never +# consumes this table). Small edits run only the gates whose path scope they +# touch; the full suite stays one command away. GATE_PATH_SCOPES: dict[str, tuple[str, ...]] = { "governance": ("tests/", "10-workflow/workflow-assistance/scripts/", "10-workflow/workflow-assistance/config/"), "compile": ("scripts/", "10-workflow/workflow-assistance/scripts/", "30-observer/work-lab-observer/src/"), diff --git a/scripts/ci/emit_gate_plan.py b/scripts/ci/emit_gate_plan.py index ec52c39..bf2be5d 100644 --- a/scripts/ci/emit_gate_plan.py +++ b/scripts/ci/emit_gate_plan.py @@ -53,8 +53,9 @@ def main() -> int: commit = args.commit or git(root, "rev-parse", "HEAD") tree = args.tree or git(root, "rev-parse", "HEAD^{tree}") generated_at = args.generated_at or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + profile = load_profile(args.profile.resolve()) plan = build_plan( - load_profile(args.profile.resolve()), + profile, repository=args.repository, commit=commit, tree=tree, @@ -74,7 +75,7 @@ def main() -> int: write_output(args.github_output, "plan_digest", plan["plan_digest"]["value"]) write_output(args.github_output, "risk", plan["risk"]) write_output(args.github_output, "plan_json", plan_json) - for gate in ("workflow", "observer", "token-monitor", "supply-chain-security", "integration"): + for gate in sorted(profile["gates"]): write_output(args.github_output, f"run_{gate.replace('-', '_')}", str(gate in plan["required_gates"]).lower()) return 0