From 2375d3c20ee5b6f068f686dda97b415add6238ad Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer B (MiniMax)" Date: Sun, 14 Jun 2026 10:48:36 +0000 Subject: [PATCH 1/2] test(provisioner): SEO-patch grep-gate (RFC #2843 #23, makes #2844 substantive) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per PM dispatch 07a13c0a — add a regression test that makes the SEO-patch deletion (PR #2844) structural vs the 0-diff no-op. The test guards the 'core carries zero template-specific skill knowledge' invariant (RFC #2843 §4.4): any future refactor that re-introduces the per-template SEO patch will fail CI here BEFORE the symbols leak into core, rather than after the next incident. Two layers of defense: 1. Symbol grep on every .go file in workspace-server/ (catches re-adds to ANY package, not just provisioner). Skips the test file itself (architecture_test.go lists the symbols as documentation) to avoid a self-match. Skips /vendor/. The 4 forbidden symbols are the union of (a) the field the patch added to WorkspaceConfig (EnableSEOSkillPackage) and (b) the symbols the patch's seo_skill_package.go defined (SEOSkillPackageFiles, SEOSkillConfigBlock, mergeSkillsBlockIntoConfigYAML). 2. File-path existence check (catches the embedded seo_skill_package/ directory reappearing with the .md/.yaml files the grep would miss). Two forbidden paths: the directory + the file. Test resolves the repo root from the test's CWD (internal/provisioner → ../../..) so the grep walks the right tree from any runner. go test ./internal/provisioner/ -> 0.081s clean (the new TestNoSEOPatchSymbolsInCore + the existing TestProvisionerDoesNotImportUpstreamLayers both pass). Refs RFC #2843 §4.4, PR #2844. This is the substantive test the 0-diff audit PR #2844 was missing. --- .../internal/provisioner/architecture_test.go | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/workspace-server/internal/provisioner/architecture_test.go b/workspace-server/internal/provisioner/architecture_test.go index 12e1420a0..bee4f9d2a 100644 --- a/workspace-server/internal/provisioner/architecture_test.go +++ b/workspace-server/internal/provisioner/architecture_test.go @@ -78,3 +78,113 @@ func listImports(t *testing.T, dir string) map[string]string { } return out } + +// SEO-patch grep-gate (RFC #2843 §4.4, PR #2844). The SEO +// patch (EnableSEOSkillPackage / SEOSkillPackageFiles / +// SEOSkillConfigBlock / seo_skill_package.go) was a +// per-template patch deleted by PR #2844. The generic asset +// channel (RFC #2843 #24) replaces it with template-agnostic +// template-repo fetches, so any reintroduction here is a +// layering violation (template content in core). This test +// makes the deletion STRUCTURAL — a future refactor that +// re-adds the patch (e.g. "let's just bring back +// EnableSEOSkillPackage for the new template") fails CI here +// before the SEO symbols leak into core, rather than after the +// next incident. +// +// Two layers of defense: +// 1. Symbol grep on every .go file in workspace-server/ +// (catches a re-add to any package, not just provisioner). +// 2. File-path existence check (catches the embedded +// seo_skill_package/ directory reappearing). +// +// If this test fails: you re-introduced the per-template SEO +// patch that RFC #2843 §4.4 explicitly deletes. Use the generic +// template-repo asset channel (RFC #2843 #24) instead. + +var seoPatchForbiddenSymbols = []string{ + "EnableSEOSkillPackage", + "SEOSkillPackageFiles", + "SEOSkillConfigBlock", + "mergeSkillsBlockIntoConfigYAML", +} + +var seoPatchForbiddenPathPrefixes = []string{ + "workspace-server/internal/provisioner/seo_skill_package", + "workspace-server/internal/provisioner/seo_skill_package.go", +} + +func TestNoSEOPatchSymbolsInCore(t *testing.T) { + t.Parallel() + + // The test runs from internal/provisioner/ — the repo root + // is 4 levels up (workspace-server/internal/provisioner → root). + repoRoot, _ := filepath.Abs("../../..") + root := filepath.Join(repoRoot, "workspace-server") + + // Layer 1: grep every .go file in workspace-server/ for the + // forbidden SEO-patch symbols. Catches re-adds to ANY package + // (provisioner, handlers, etc.) — the patch was per-template + // content in core, no package is a valid home. + var hits []string + err := filepath.Walk(root, func(path string, info os.FileInfo, walkErr error) error { + if walkErr != nil { + return walkErr + } + if info.IsDir() { + return nil + } + if !strings.HasSuffix(path, ".go") { + return nil + } + // Skip generated files and vendored code. + if strings.Contains(path, "/vendor/") { + return nil + } + // Skip THIS test file itself — it lists the forbidden + // symbols as documentation. Excluding self from the grep + // is necessary to avoid a self-match (the grep-gate would + // fail on the very file that defines it). + if strings.HasSuffix(path, "architecture_test.go") { + return nil + } + b, readErr := os.ReadFile(path) + if readErr != nil { + return readErr + } + for _, sym := range seoPatchForbiddenSymbols { + if strings.Contains(string(b), sym) { + hits = append(hits, path+":"+sym) + } + } + return nil + }) + if err != nil { + t.Fatalf("walk %s: %v", root, err) + } + if len(hits) > 0 { + t.Errorf( + "RFC #2843 §4.4 grep-gate: the SEO-specific patch symbols "+ + "are forbidden in core (per-template content has no home "+ + "here). Use the generic template-repo asset channel "+ + "(RFC #2843 #24) instead. Hits: %v", + hits, + ) + } + + // Layer 2: forbidden file-path existence check. Catches + // the seo_skill_package/ directory reappearing with the + // embedded skill files (which the grep above would miss + // since the .md/.yaml files don't reference the symbols). + for _, forbidden := range seoPatchForbiddenPathPrefixes { + abs := filepath.Join(repoRoot, forbidden) + if _, statErr := os.Stat(abs); statErr == nil { + t.Errorf( + "RFC #2843 §4.4 grep-gate: forbidden file/dir re-appeared: %s "+ + "(this is the per-template SEO patch that the generic "+ + "asset channel replaces).", + abs, + ) + } + } +} -- 2.52.0 From 69bd35e054345b29aad666bf0f739e42ed8d97ba Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer B (MiniMax)" Date: Sun, 14 Jun 2026 10:55:38 +0000 Subject: [PATCH 2/2] test(provisioner): narrow grep-gate self-exclude to exact path (RC #11684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Researcher RC #11684 on #2844 — the prior self-exclude strings.HasSuffix(path, 'architecture_test.go') matched EVERY workspace-server architecture_test.go file (4 siblings under internal/{models,db,provisioner,wsauth}/), creating a blind spot where forbidden SEO symbols in a sibling architecture test would pass silently. Fix: compute selfPath via filepath.Abs at the top of the test (the CWD is the package directory, so Abs gives the exact test file's path), then match by EXACT path equality ('if path == selfPath') rather than by basename suffix. The sibling architecture_test.go files (internal/models/, internal/db/, internal/wsauth/) are now grep'd normally — they could legitimately contain the forbidden SEO symbols and the gate must catch them. go test -run TestNoSEOPatchSymbolsInCore -v ./internal/provisioner/ -> PASS (0.03s) go test ./internal/provisioner/ -> clean (0.039s, all existing tests still pass). Closes RC #11684. Re-requesting 2-genuine re-review on the new head. --- .../internal/provisioner/architecture_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/workspace-server/internal/provisioner/architecture_test.go b/workspace-server/internal/provisioner/architecture_test.go index bee4f9d2a..e6e374ade 100644 --- a/workspace-server/internal/provisioner/architecture_test.go +++ b/workspace-server/internal/provisioner/architecture_test.go @@ -127,6 +127,15 @@ func TestNoSEOPatchSymbolsInCore(t *testing.T) { // (provisioner, handlers, etc.) — the patch was per-template // content in core, no package is a valid home. var hits []string + // Resolve the current test file's absolute path so the + // self-exclude can match by exact path, not by basename + // (a basename match would skip EVERY architecture_test.go + // in the tree — workspace-server has them under + // internal/{models,db,provisioner,wsauth}/ — and create + // a blind spot where forbidden SEO symbols in a sibling + // architecture test would pass silently). Researcher + // RC #11684. + selfPath, _ := filepath.Abs("architecture_test.go") err := filepath.Walk(root, func(path string, info os.FileInfo, walkErr error) error { if walkErr != nil { return walkErr @@ -144,8 +153,12 @@ func TestNoSEOPatchSymbolsInCore(t *testing.T) { // Skip THIS test file itself — it lists the forbidden // symbols as documentation. Excluding self from the grep // is necessary to avoid a self-match (the grep-gate would - // fail on the very file that defines it). - if strings.HasSuffix(path, "architecture_test.go") { + // fail on the very file that defines it). Match by EXACT + // absolute path so sibling architecture_test.go files + // (workspace-server/internal/{models,db,wsauth}/) are + // still grep'd — they could legitimately contain the + // forbidden SEO symbols and must be caught. + if path == selfPath || strings.HasSuffix(path, "/"+filepath.Base(selfPath)) && path == selfPath { return nil } b, readErr := os.ReadFile(path) -- 2.52.0