From 37fbb110e3062a8dc2efeff44c99c3dc68735cb5 Mon Sep 17 00:00:00 2001 From: chichuan Date: Thu, 6 Aug 2026 11:13:55 +0800 Subject: [PATCH 1/2] ci: run release compatibility in PR admission --- .github/workflows/ci.yml | 7 +++++++ test/scripts/changelog_pr_gate_test.go | 28 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bada42c2..4938e65c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1386,6 +1386,13 @@ jobs: BASE_REF="$COMPATIBILITY_STABLE_REF" fi + - name: Check complete CLI command compatibility + if: ${{ needs.lint.outputs.changelog_only != 'true' && needs.lint.outputs.docs_only != 'true' && (needs.lint.outputs.full_suite == 'true' || needs.lint.outputs.interface_sensitive == 'true') }} + run: | + ./scripts/policy/check-command-compatibility.sh \ + --base-ref "$COMPATIBILITY_BASE_REF" \ + --stable-ref "$COMPATIBILITY_STABLE_REF" + - name: Check complete Schema compatibility if: ${{ needs.lint.outputs.changelog_only != 'true' && needs.lint.outputs.docs_only != 'true' && (needs.lint.outputs.full_suite == 'true' || needs.lint.outputs.interface_sensitive == 'true') }} run: make schema-compatibility BASE_REF="$COMPATIBILITY_BASE_REF" diff --git a/test/scripts/changelog_pr_gate_test.go b/test/scripts/changelog_pr_gate_test.go index 4f485999..1ee8e22e 100644 --- a/test/scripts/changelog_pr_gate_test.go +++ b/test/scripts/changelog_pr_gate_test.go @@ -384,6 +384,34 @@ func TestReleaseChangelogExtractionAllowsLowercaseTodoProductName(t *testing.T) } } +func TestInterfaceIntegrityWorkflowContract(t *testing.T) { + root, err := filepath.Abs(filepath.Join("..", "..")) + if err != nil { + t.Fatalf("Abs(repo root) error = %v", err) + } + data, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "ci.yml")) + if err != nil { + t.Fatalf("ReadFile(ci.yml) error = %v", err) + } + workflow := string(data) + interfaceStart := strings.Index(workflow, "\n interface-integrity:\n") + interfaceEnd := strings.Index(workflow, "\n cli-smoke:\n") + if interfaceStart < 0 || interfaceEnd <= interfaceStart { + t.Fatal("Code Admission workflow missing Interface Integrity job boundaries") + } + interfaceJob := workflow[interfaceStart:interfaceEnd] + for _, want := range []string{ + "name: Check complete CLI command compatibility", + "./scripts/policy/check-command-compatibility.sh", + `--base-ref "$COMPATIBILITY_BASE_REF"`, + `--stable-ref "$COMPATIBILITY_STABLE_REF"`, + } { + if !strings.Contains(interfaceJob, want) { + t.Errorf("Interface Integrity job missing release-equivalent compatibility contract %q", want) + } + } +} + func TestChangelogPRFastPathWorkflowContract(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil { From d75b744a3528827eb61918b72af0b9097a24ab25 Mon Sep 17 00:00:00 2001 From: chichuan Date: Thu, 6 Aug 2026 11:58:49 +0800 Subject: [PATCH 2/2] ci: classify core command changes as interface-sensitive --- .github/workflows/ci.yml | 1 + test/scripts/changelog_pr_gate_test.go | 27 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4938e65c..c71a8697 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,6 +111,7 @@ jobs: filename.startsWith('internal/app/') || filename.startsWith('internal/cli/') || filename.startsWith('internal/cobracmd/') || + filename.startsWith('internal/corecmd/') || filename.startsWith('internal/helpers/') || filename.startsWith('internal/i18n/') || filename.startsWith('internal/interfacesnapshot/') || diff --git a/test/scripts/changelog_pr_gate_test.go b/test/scripts/changelog_pr_gate_test.go index 1ee8e22e..ac5a4986 100644 --- a/test/scripts/changelog_pr_gate_test.go +++ b/test/scripts/changelog_pr_gate_test.go @@ -412,6 +412,33 @@ func TestInterfaceIntegrityWorkflowContract(t *testing.T) { } } +func TestInterfaceSensitiveClassificationCoversCoreCommandFramework(t *testing.T) { + root, err := filepath.Abs(filepath.Join("..", "..")) + if err != nil { + t.Fatalf("Abs(repo root) error = %v", err) + } + data, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "ci.yml")) + if err != nil { + t.Fatalf("ReadFile(ci.yml) error = %v", err) + } + workflow := string(data) + start := strings.Index(workflow, " const isInterfaceSensitive =") + end := strings.Index(workflow, " const isMCPSensitive =") + if start < 0 || end <= start { + t.Fatal("Code Admission workflow missing interface-sensitive classifier boundaries") + } + classifier := strings.TrimSpace(workflow[start:end]) + probe := classifier + ` +if (!isInterfaceSensitive("internal/corecmd/corecmd.go")) { + throw new Error("existing corecmd files must trigger Interface Integrity"); +} +` + cmd := exec.Command("node", "-e", probe) + if output, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("interface-sensitive classifier rejected corecmd change: %v\n%s", err, output) + } +} + func TestChangelogPRFastPathWorkflowContract(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil {