Skip to content

fix(pipeline): scope memory decision candidates - #324

Open
chrisl10 wants to merge 1 commit into
legioncodeinc:mainfrom
chrisl10:fix/decision-candidate-context
Open

fix(pipeline): scope memory decision candidates#324
chrisl10 wants to merge 1 commit into
legioncodeinc:mainfrom
chrisl10:fix/decision-candidate-context

Conversation

@chrisl10

@chrisl10 chrisl10 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • include bounded, JSON-delimited candidate content in memory decision prompts
  • scope candidate search and hydration to the job's agent/project boundaries
  • fail closed on job/query tenant mismatches and unauthorized model mutation targets
  • add regressions for project isolation, prompt injection, bounds, SQL escaping, and tenant scope

Verification

  • focused Vitest: 20/20 passed
  • Biome (changed TypeScript files): passed
  • typecheck: passed
  • SQL-safety audit: 318 files passed
  • duplication gate: 0 clones
  • build: passed
  • pack check: 70 files passed
  • Security: PASS, no open scoped findings
  • Quality: PASS, no open scoped findings

Known clean-main baseline exceptions

Local macOS npm run ci reports 4 failures with 5,212 passes and 11 skips. All four reproduce unchanged on detached clean main and are unrelated to this three-file delta:

  • tests/cli/entry-guard.test.ts:76
  • tests/daemon/runtime/logs/log-store.test.ts:74
  • tests/daemon/runtime/projects/onboarding-api.test.ts:94
  • tests/daemon/runtime/projects/onboarding-api.test.ts:105

Summary by CodeRabbit

  • Bug Fixes
    • Improved decision accuracy by restricting candidate searches and content to the active project and agent scope.
    • Prevented unauthorized updates or deletions when model suggestions target records outside the available candidates.
    • Added safeguards to handle missing or mismatched scope information without widening searches.
    • Limited candidate count and content size, with stronger protection against prompt-injection content.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 203ec259-a570-42c5-a6e9-25e1c725c231

📥 Commits

Reviewing files that changed from the base of the PR and between c1cb6bf and 9bc1f5b.

📒 Files selected for processing (3)
  • .changeset/fix-decision-candidate-context.md
  • src/daemon/runtime/pipeline/decision.ts
  • tests/daemon/runtime/pipeline/decision.test.ts

📝 Walkthrough

Walkthrough

Decision processing now bounds candidate counts and content, scopes search and hydration to the job’s tenant, agent, and project, validates job scope consistency, and rejects model mutations targeting candidates outside the authorized set.

Changes

Decision candidate safety

Layer / File(s) Summary
Bounded candidate context
src/daemon/runtime/pipeline/decision.ts, tests/daemon/runtime/pipeline/decision.test.ts
Candidate prompts use bounded JSON-serialized content, capped candidate counts, and explicit untrusted-evidence instructions.
Scoped candidate search and hydration
src/daemon/runtime/pipeline/decision.ts, tests/daemon/runtime/pipeline/decision.test.ts, .changeset/fix-decision-candidate-context.md
Lexical, vector, and hydration queries apply agent and project scope, with tests covering cross-project isolation and missing project scope.
Decision scope and proposal authorization
src/daemon/runtime/pipeline/decision.ts, tests/daemon/runtime/pipeline/decision.test.ts
Scope mismatches fail before storage or model work, and update/delete proposals with unauthorized targets become none.
Estimated code review effort: 4 (Complex) ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DecisionJob
  participant ScopeGuard
  participant CandidateSearch
  participant CandidateHydration
  participant DecisionModel
  participant ProposalGuard
  DecisionJob->>ScopeGuard: Validate org and workspace scope
  ScopeGuard->>CandidateSearch: Search scoped candidates
  CandidateSearch->>CandidateHydration: Hydrate bounded candidate ids
  CandidateHydration-->>DecisionModel: Provide scoped candidate JSON
  DecisionModel->>ProposalGuard: Return update or delete target
  ProposalGuard-->>DecisionJob: Accept authorized target or downgrade to none
Loading

Suggested reviewers: thenotoriousllama

Poem

I bounded the crumbs in a JSON nest,
And fenced each candidate from every quest.
The model may choose, but targets must prove,
Their ids are scoped before they can move.
A rabbit thumps: safe decisions bloom! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: scoping decision candidates in the pipeline.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

const inList = ids.map((id) => sLiteral(id)).join(", ");
return `SELECT ${idCol} AS id, ${contentCol} AS content FROM "${tbl}" WHERE ${idCol} IN (${inList})`;
const projectClause = buildProjectScopeConjunct({ projectId: jobScope.projectId ?? "" });
return `SELECT ${idCol} AS id, ${contentCol} AS content FROM "${tbl}" WHERE ${idCol} IN (${inList}) AND ${agentCol} = ${sLiteral(agentId)}${projectClause}`;

@aikido-pr-checks aikido-pr-checks Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential SQL injection via string-based query concatenation - high severity
SQL injection might be possible in these locations, especially if the strings being concatenated are controlled via user input.

Suggested change
return `SELECT ${idCol} AS id, ${contentCol} AS content FROM "${tbl}" WHERE ${idCol} IN (${inList}) AND ${agentCol} = ${sLiteral(agentId)}${projectClause}`;
return `SELECT ${idCol} AS id, ${contentCol} AS content FROM ${tbl} WHERE ${idCol} IN (${inList}) AND ${agentCol} = ${sLiteral(agentId)}${projectClause}`;

Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

@chrisl10

Copy link
Copy Markdown
Contributor Author

Live canary evidence for reviewed commit 9bc1f5bf3a9b08f9679a3d67f8a2c822c0744a65:

  • local and VPS tarball SHA-256 matched: 189a9e538c462cfb60010b8ae1525ab0f4dcf1141e077cffcbdeaef100214011
  • read-only Codex session 019faff2-9993-7691-9d34-bd0fca2420a2 completed trusted lifecycle hooks
  • raw capture increased 101380 -> 101503
  • SteadyMux-scoped extraction 03dc77ab-b8aa-4760-8816-3ff56ff31d5e, decision 28d176a9-2f95-497b-a4b8-aac1e6670251, and controlled write 1bca6047-0eee-4338-8145-220a4709526e completed
  • committedSinceBoot increased 0 -> 1; authenticated listing returned inserted convention mem_ms6ng5kc_nek129p0
  • capture and memory outboxes ended empty
  • canary restored memory.enabled=false; Doctor remained inactive/disabled; six product repos remained paused

Current CI failures are not in the changed decision test: focused decision tests are 20/20 green. The shared logs/log-store assertion also fails on current main CI (run 30433340336) across Node 22/24/Windows; the extra Windows scheduled-task assertion is outside this three-file delta. Aikido dependency advisories also predate this no-dependency-change PR. No merge/release is requested while required checks remain red.

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