diff --git a/.github/workflows/smoke-call-workflow.lock.yml b/.github/workflows/smoke-call-workflow.lock.yml index b7fb052fab3..fbe4cdd2d92 100644 --- a/.github/workflows/smoke-call-workflow.lock.yml +++ b/.github/workflows/smoke-call-workflow.lock.yml @@ -1112,7 +1112,7 @@ jobs: # Imported from called workflow "smoke-workflow-call" because GitHub requires the caller job to grant permissions requested by reusable workflow jobs. # Review the called workflow's job-level permissions in ./.github/workflows/smoke-workflow-call.lock.yml. permissions: - actions: write + actions: read contents: read issues: write pull-requests: write diff --git a/pkg/workflow/agentic_engine.go b/pkg/workflow/agentic_engine.go index 43f09cf5f21..8b4716af100 100644 --- a/pkg/workflow/agentic_engine.go +++ b/pkg/workflow/agentic_engine.go @@ -327,6 +327,11 @@ type BaseEngine struct { ghSkillAgentName string capabilities EngineCapabilities dedicatedLLMGatewayPort int + // undocumented marks an engine that is registered and functional but intentionally + // excluded from public reference documentation (engines.md) and the workflow schema. + // Drift-detection tools should skip engines with undocumented == true to avoid + // filing spurious "undocumented engine" issues. + undocumented bool } func (e *BaseEngine) GetID() string { @@ -349,6 +354,14 @@ func (e *BaseEngine) GetGHSkillAgentName() string { return e.ghSkillAgentName } +// IsUndocumented reports whether this engine is intentionally excluded from +// public reference documentation (engines.md) and the workflow schema. +// When true, drift-detection tools should skip this engine to avoid filing +// spurious "undocumented engine" alerts. Default is false. +func (e *BaseEngine) IsUndocumented() bool { + return e.undocumented +} + func (e *BaseEngine) GetCapabilities() EngineCapabilities { return e.capabilities } @@ -565,6 +578,30 @@ func (r *EngineRegistry) GetSupportedEngines() []string { return engines } +// GetDocumentedEngines returns a sorted list of engine IDs that are intended +// to appear in the public reference documentation (engines.md) and the workflow +// schema. Engines that have IsUndocumented() == true are excluded. +// +// Use this method (rather than GetSupportedEngines) when comparing the registered +// engine set against docs/engines.md or main_workflow_schema.json so that +// intentionally hidden engines do not trigger spurious drift-detection alerts. +func (r *EngineRegistry) GetDocumentedEngines() []string { + agenticEngineLog.Print("Getting list of documented engines") + type undocumentedChecker interface { + IsUndocumented() bool + } + var ids []string + for id, engine := range r.engines { + if checker, ok := engine.(undocumentedChecker); ok && checker.IsUndocumented() { + agenticEngineLog.Printf("Skipping undocumented engine: %s", id) + continue + } + ids = append(ids, id) + } + sort.Strings(ids) + return ids +} + // IsValidEngine checks if an engine ID is valid func (r *EngineRegistry) IsValidEngine(id string) bool { _, exists := r.engines[id] diff --git a/pkg/workflow/agentic_engine_test.go b/pkg/workflow/agentic_engine_test.go index a8bd3d218ab..0264644bcf5 100644 --- a/pkg/workflow/agentic_engine_test.go +++ b/pkg/workflow/agentic_engine_test.go @@ -150,6 +150,45 @@ func TestGetGlobalEngineRegistry(t *testing.T) { }) } +func TestEngineRegistry_GetDocumentedEngines(t *testing.T) { + t.Run("excludes undocumented engines", func(t *testing.T) { + registry := NewEngineRegistry() + documented := registry.GetDocumentedEngines() + assert.NotContains(t, documented, "antigravity", + "antigravity is intentionally undocumented and must not appear in the documented engines list") + }) + + t.Run("includes standard documented engines", func(t *testing.T) { + registry := NewEngineRegistry() + documented := registry.GetDocumentedEngines() + for _, id := range []string{"claude", "codex", "copilot", "gemini", "opencode"} { + assert.Contains(t, documented, id, + "documented engine %q must appear in GetDocumentedEngines()", id) + } + }) + + t.Run("result is a subset of GetSupportedEngines", func(t *testing.T) { + registry := NewEngineRegistry() + supported := registry.GetSupportedEngines() + documented := registry.GetDocumentedEngines() + for _, id := range documented { + assert.Contains(t, supported, id, + "documented engine %q must also be in GetSupportedEngines()", id) + } + assert.LessOrEqual(t, len(documented), len(supported), + "GetDocumentedEngines must return no more engines than GetSupportedEngines") + }) + + t.Run("result is sorted", func(t *testing.T) { + registry := NewEngineRegistry() + documented := registry.GetDocumentedEngines() + for i := 1; i < len(documented); i++ { + assert.LessOrEqual(t, documented[i-1], documented[i], + "GetDocumentedEngines result must be sorted alphabetically") + } + }) +} + func TestEngineRegistry_GetAllAgentManifestFolders(t *testing.T) { t.Run("always includes .agents platform directory", func(t *testing.T) { registry := NewEngineRegistry() diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 5d7584bf9d5..3ad9643d2be 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -34,6 +34,11 @@ func NewAntigravityEngine() *AntigravityEngine { NativeAgentFile: false, // Antigravity does not support agent file natively; the compiler prepends the agent file content to prompt.txt }, dedicatedLLMGatewayPort: constants.AntigravityLLMGatewayPort, + // undocumented: intentionally excluded from engines.md and the workflow schema. + // The engine is registered and functional but kept out of public reference docs + // to avoid confusing users. Drift-detection tools check IsUndocumented() to + // skip this engine and prevent recurring false-positive issue filings. + undocumented: true, }, } } diff --git a/pkg/workflow/antigravity_engine_test.go b/pkg/workflow/antigravity_engine_test.go index 0b9f9de6163..7ac5365f74a 100644 --- a/pkg/workflow/antigravity_engine_test.go +++ b/pkg/workflow/antigravity_engine_test.go @@ -20,6 +20,11 @@ func TestAntigravityEngine(t *testing.T) { assert.True(t, engine.IsExperimental(), "Antigravity engine should be experimental") }) + t.Run("undocumented flag", func(t *testing.T) { + assert.True(t, engine.IsUndocumented(), + "Antigravity engine must be marked undocumented to prevent drift-detection tools from filing spurious issues about its absence in engines.md and the workflow schema") + }) + t.Run("capabilities", func(t *testing.T) { capabilities := engine.GetCapabilities() assert.True(t, capabilities.ToolsAllowlist, "Should support tools allowlist")