Skip to content

fix(ai): make query_workspace the single source of truth (local-driver union) - #1278

Merged
ocervell merged 1 commit into
ai-resiliencyfrom
fix/ai-query-single-source
Jul 5, 2026
Merged

fix(ai): make query_workspace the single source of truth (local-driver union)#1278
ocervell merged 1 commit into
ai-resiliencyfrom
fix/ai-query-single-source

Conversation

@ocervell

@ocervell ocervell commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Why (diagnosed from a live run)

Asked "What's in my workspace", the model correctly ran query_workspace — then cd'd into ~/.secator/reports/.../tasks/18/.outputs/ and cat | jq'd local JSON to count finding types. Two causes:

  1. Local-driver gap: the JSON exporter writes findings to disk only at end-of-run, so mid-run query_workspace (local backend) sees nothing — the prompt compensated by telling the model where the report files live.
  2. Prompt framing: "the runner folder … is where we store all inputs/outputs" invited the model to read those files to find data — a different, possibly stale store than the workspace it queried (outright wrong under --driver mongodb/cloud).

Fix — Query is the single source of truth

  • Local driver only: _handle_query unions the backend results with this run's in-memory findings (ctx.results), filtered by the same query and deduped by _uuid. mongodb/api are unchanged (hooks persist live → no union needed). The local driver is also exempted from the workspace_id guard (it can answer from in-memory results).
  • Prompt (common.txt): keep "write generated outputs to $workspace_path/.outputs/"; drop the "we store all inputs/outputs here" framing; add "ALWAYS use query_workspace — the single source of truth; do NOT read local report files to find findings."

Tests

_union_live_results (filter+merge+dedup), local-driver unions live results, mongodb does NOT union, local exempt from the workspace guard, and the updated no_workspace guard test (now scoped to non-local backends). Full AI suite: no new failures.

Targets ai-resiliency (#1241).

🤖 Generated with Claude Code

…r union)

Under the local driver the JSON exporter writes findings to disk only at
end-of-run, so mid-run the query backend sees nothing — which is why the prompt
told the model where the report files live, and why it then shelled into
.outputs/ to *find* findings (fragile, and it reads a different store than the
one it queried).

- _handle_query: for the local (json) backend only, union the backend results
  with this run's in-memory findings (ctx.results), filtered by the same query
  and deduped by _uuid. mongodb/api persist live via hooks, so they are queried
  normally (no union). The local driver is also exempted from the workspace_id
  guard (it can answer from in-memory results).
- prompt (common.txt): keep "write your generated outputs to $workspace_path/
  .outputs/", drop the "we store all inputs/outputs here" framing that invited
  reading local report files, and add "ALWAYS use query_workspace — the single
  source of truth; do NOT read local report files to find findings".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NNjPggRSVZ2xnLb7ZxWP5H
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: da75e04d-5618-462b-83c5-1c542d74e554

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ai-query-single-source

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ocervell
ocervell merged commit 3a5c2ae into ai-resiliency Jul 5, 2026
1 check passed
@ocervell
ocervell deleted the fix/ai-query-single-source branch July 5, 2026 16:33
ocervell added a commit that referenced this pull request Jul 5, 2026
…eritance (PR1 1.b/1.c) (#1279)

## What (PR 1, parts 1.b + 1.c + a subagent-runnability fix)

**1.b/1.c — structured, evidence-backed subagent prompt.** When the ai
task spawns a subagent, its prompt becomes a **structured** template
whose "already known" section is **auto-assembled** from workspace
findings for the subagent's target(s), so it doesn't redo work.
- `build_subagent_prompt(objective, targets, evidence)` — wraps the
LLM-supplied objective (**verbatim**) in `## Objective / ## Scope / ##
Already known (do not re-run) / ## Expected output`.
- `_gather_subagent_evidence(ctx, targets, limit=40)` — queries the
workspace (single source of truth incl. this run's live findings, per
#1278) for findings matching the targets; token-bounded; **best-effort**
(failure → `""`, never breaks the spawn).
- Wired into `_run_runner`'s `name=="ai"` branch. **1.a (permissions)
untouched** — out of scope.

**Subagent LLM inheritance (fold-in).** E2E testing surfaced that a
spawned subagent fell back to `CONFIG.addons.ai.default_model` — a
different provider than the parent (anthropic-direct vs openrouter) with
no key → `AuthenticationError` before it ran, so **subagents never
actually ran**. Fixed: carry the parent's resolved
`model`/`api_key`/`api_base` on `ActionContext` and `setdefault` them
onto the child opts at spawn (explicit LLM-supplied model still wins).

## Verification
- Unit: `TestBuildSubagentPrompt`, `TestGatherSubagentEvidence`, and
`TestRunRunner` tests for the structured prompt + LLM inheritance (+
explicit-model-wins). `test_ai_actions.py` **97 passed**; no new
failures vs baseline.
- **E2E** (live subagent run): subagent runs to **SUCCESS** (no
AuthError), receives the structured prompt with **all four sections**,
and its spawned nmap **nests** under the conversation via `session_id`.

## Known limitation (accepted, v1)
The `$or` host/ip/url evidence match is exact — `matched_at`-only
findings on URL-only targets aren't gathered yet (deliberate follow-up).

Part of the AI-task series → `ai-resiliency` (#1241).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant