Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions docs/sdd-search-strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# SDD Search Strategy Design Boundary

This change makes code search configurable for SDD code-reading phases while keeping `grep` as the safe default. RAG/MCP search is an optional acceleration path, not a hard dependency.

## Detection contract

`sdd-init` resolves `search_strategy` in this order:

1. Explicit agent/system config wins.
2. `openspec/config.yaml` wins when present.
3. MCP auto-detection MAY enable `hybrid` only when a tool name or description explicitly indicates semantic, vector, or embedding-based code search.
4. If nothing qualifies, the mode is `grep`.

Generic tools named like `code_search` are not enough by themselves; their description must indicate embedding-backed semantic search to avoid false positives.

## Fallback behavior

| Situation | Behavior |
|-----------|----------|
| No `search_strategy` config | Use `grep` mode. |
| `mode: grep` | Use the existing Grep + targeted Read flow. |
| `mode: hybrid` with valid RAG tool | Query RAG first, then fall back to grep if results are insufficient. |
| RAG tool missing, down, or timing out | Log the issue, use grep for the rest of the phase, and report the risk. |
| Optional reindex fails after `sdd-apply` | Continue; reindex is non-blocking. |

## Why `grep` remains the safe default

`grep` is deterministic, local, and already supported by every SDD phase. Keeping it as the default preserves backwards compatibility and avoids making SDD depend on optional MCP infrastructure.

`hybrid` mode is useful when available because semantic search can reduce exploration work on large codebases, but correctness still comes from the fallback cascade: RAG → grep → targeted read.

## Baseline measurement on this repository

Measured locally on `gentle-ai` using a grep-style scan over tracked UTF-8 files.

| Scenario | Scope | Files scanned | Lines scanned | Matches | Time |
|----------|-------|---------------|---------------|---------|------|
| Find orchestrator forwarding contract (`Search Strategy Forwarding`) | `internal/assets/*/sdd-orchestrator.md` | 11 | 2,944 | 11 | 1.768 ms |
| Find search strategy contract (`search_strategy`) | `internal/assets/skills/**` | 33 | 4,532 | 23 | 3.102 ms |
| Find fallback wording (`fall back to grep`) | `internal/assets/skills/**` | 33 | 4,532 | 1 | 1.850 ms |

These numbers are intentionally a baseline, not a promise of RAG performance. They show the current grep path is cheap for this repository slice, while documenting the exact metrics future `hybrid` runs should compare against: files scanned, lines read, matching confidence, fallback activation, and elapsed time.

## Review checklist

- [ ] `search_strategy` detection is explicit and conservative.
- [ ] Missing or broken RAG never blocks SDD execution.
- [ ] `grep` remains the default when config is absent.
- [ ] Orchestrators forward search config to `sdd-explore`, `sdd-apply`, and `sdd-verify`.
- [ ] Tests cover the contract so future asset edits cannot silently remove it.
11 changes: 11 additions & 0 deletions internal/assets/antigravity/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,17 @@ When executing `sdd-apply` or `sdd-verify` phases, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When executing `sdd-apply` for a continuation batch (not the first batch):
Expand Down
72 changes: 72 additions & 0 deletions internal/assets/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,78 @@ func TestSDDPhaseCommonEnforcesExecutorBoundary(t *testing.T) {
}
}

func TestSDDSearchStrategyContract(t *testing.T) {
orchestrators := []string{
"generic/sdd-orchestrator.md",
"claude/sdd-orchestrator.md",
"opencode/sdd-orchestrator.md",
"gemini/sdd-orchestrator.md",
"codex/sdd-orchestrator.md",
"cursor/sdd-orchestrator.md",
"windsurf/sdd-orchestrator.md",
"antigravity/sdd-orchestrator.md",
"kiro/sdd-orchestrator.md",
"kimi/sdd-orchestrator.md",
"qwen/sdd-orchestrator.md",
}

for _, assetPath := range orchestrators {
t.Run(assetPath, func(t *testing.T) {
content := MustRead(assetPath)
for _, want := range []string{
"Search Strategy Forwarding (MANDATORY)",
"sdd-explore", "sdd-apply", "sdd-verify",
`mem_search(query: "sdd-init/{project}"`,
"SEARCH STRATEGY CONFIG DETECTED",
"Section F",
"grep",
} {
if !strings.Contains(content, want) {
t.Fatalf("%q missing search strategy contract %q", assetPath, want)
}
}
})
}

phaseCommon := MustRead("skills/_shared/sdd-phase-common.md")
for _, want := range []string{
"## F. Code Search Protocol",
"`grep` | Current behavior",
"`hybrid` | RAG-first cascade with grep fallback",
"If `mode` is `hybrid` but `rag.mcp_tool` is missing or empty, fall back to `grep`",
"If `mode` is `hybrid` but the MCP tool call fails",
"grep fallback guarantees correctness",
} {
if !strings.Contains(phaseCommon, want) {
t.Fatalf("sdd-phase-common missing search strategy boundary %q", want)
}
}

initSkill := MustRead("skills/sdd-init/SKILL.md")
for _, want := range []string{
"Resolve `search_strategy` from agent marker",
"semantic/vector/embedding",
"no qualifying RAG MCP tool",
"Search Strategy status",
} {
if !strings.Contains(initSkill, want) {
t.Fatalf("sdd-init missing search strategy detection contract %q", want)
}
}

applySkill := MustRead("skills/sdd-apply/SKILL.md")
for _, want := range []string{
"3a. Read `search_strategy`",
"3b. Read existing code",
"#### Step 6b: Reindex Hook (Section F)",
"cached in Step 3a",
} {
if !strings.Contains(applySkill, want) {
t.Fatalf("sdd-apply missing search strategy apply contract %q", want)
}
}
}

func TestOpenCodeSDDOverlaySubagentsAreExplicitExecutors(t *testing.T) {
for _, assetPath := range []string{"opencode/sdd-overlay-single.json", "opencode/sdd-overlay-multi.json"} {
t.Run(assetPath, func(t *testing.T) {
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/claude/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/codex/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/cursor/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/gemini/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/generic/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
8 changes: 8 additions & 0 deletions internal/assets/kimi/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ Sub-agents get a fresh context with NO memory. The orchestrator controls context
| `sdd-verify` | spec + tasks | `verify-report` |
| `sdd-archive` | all artifacts | `archive-report` |

### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify`, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block, add: `"SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."`
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F)

### Engram Topic Key Format

| Artifact | Topic Key |
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/kiro/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,17 @@ When executing `sdd-apply` or `sdd-verify` phases:

Resolve TDD status ONCE per session (at first apply/verify phase) and cache it.

### Search Strategy Forwarding (MANDATORY)

When executing `sdd-explore`, `sdd-apply`, or `sdd-verify` phases:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to your working context: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, proceed with grep per Section F.

Resolve this ONCE per session (at first explore/apply/verify phase) and cache it.

### Apply-Progress Continuity (MANDATORY)

When starting a continuation `sdd-apply` batch (not the first batch for a change):
Expand Down
8 changes: 8 additions & 0 deletions internal/assets/opencode/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ When launching `sdd-apply` or `sdd-verify`, the orchestrator MUST:
2. If the result contains `strict_tdd: true`, add: `"STRICT TDD MODE IS ACTIVE. Test runner: {test_command}. You MUST follow strict-tdd.md. Do NOT fall back to Standard Mode."`
3. If the search fails or `strict_tdd` is not found, do NOT add the TDD instruction

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify`, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block, add: `"SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."`
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F)

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch:
Expand Down
11 changes: 11 additions & 0 deletions internal/assets/qwen/sdd-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ When launching `sdd-apply` or `sdd-verify` sub-agents, the orchestrator MUST:

The orchestrator resolves TDD status ONCE per session (at first apply/verify launch) and caches it.

#### Search Strategy Forwarding (MANDATORY)

When launching `sdd-explore`, `sdd-apply`, or `sdd-verify` sub-agents, the orchestrator MUST:

1. Search for project context: `mem_search(query: "sdd-init/{project}", project: "{project}")` → `mem_get_observation(id)`
2. If the result contains a `search_strategy` block:
- Add to the sub-agent prompt: "SEARCH STRATEGY CONFIG DETECTED. Mode: {search_strategy.mode}. RAG MCP tool: {search_strategy.rag.mcp_tool} (optional reindex: {search_strategy.rag.reindex_tool}). Follow Section F in sdd-phase-common.md for code search."
3. If `search_strategy` is missing, do NOT add any extra instruction (sub-agents default to grep per Section F).

Resolve this ONCE per session (at first explore/apply/verify launch) and cache it.

#### Apply-Progress Continuity (MANDATORY)

When launching `sdd-apply` for a continuation batch (not the first batch):
Expand Down
14 changes: 14 additions & 0 deletions internal/assets/skills/_shared/persistence-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ Why this split:
- Sub-agents read for SDD: SDD artifacts are large; inlining them in the orchestrator prompt would consume the entire context window
- Sub-agents always write: they have the complete detail on what happened; nuance is lost by the time results flow back to the orchestrator

## Search Strategy Context

The orchestrator MAY pass `search_strategy` config to sub-agents that read code. This is optional — phases MUST default to `grep` behavior when absent.

```yaml
search_strategy:
mode: grep | hybrid # default: grep (current behavior)
rag: # present only when mode: hybrid
mcp_tool: "tool_name" # MCP tool name for semantic search (REQUIRED for hybrid)
reindex_tool: "tool_name" # optional — fire-and-forget after sdd-apply batch
```

Sub-agents that receive this config follow **Section F** from `sdd-phase-common.md` for code search. Sub-agents that do NOT read code (sdd-propose, sdd-spec, sdd-design, sdd-tasks, sdd-archive) ignore this config entirely.

## Orchestrator Prompt Instructions for Sub-Agents

Non-SDD:
Expand Down
Loading