Skip to content

Exclude Guardian reviewer sub-sessions from Agent Status - #51

Merged
twidtwid merged 1 commit into
mainfrom
cursor/exclude-guardian-subsessions-0114
Oct 8, 2026
Merged

twidtwid merged 1 commit into
mainfrom
cursor/exclude-guardian-subsessions-0114

Conversation

@twidtwid

@twidtwid twidtwid commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Summary

With Codex Approve for me enabled, Agent Status keys were filling with internal Guardian / Guardian2 reviewer sub-sessions. Pressing one failed with cannot resume a live Guardian reviewer.

Credit: Paweł Lipkowski reported the bug and diagnosed that CodexStore.recentThreads() selected recent state_5.sqlite rows without excluding internal sub-sessions, so they consumed the 12-row limit.

This change excludes those sub-sessions in SQL, before LIMIT 12, using structured metadata only (never titles). A genuine user chat titled "Guardian" stays visible. The same predicate is applied to focusedThread() and to the native helper’s thread-ID/cwd lookups so New Chat targeting cannot treat a Guardian reviewer as a valid task.

Metadata signals (each used only when the column/table exists):

Signal How it is used
threads.thread_source exclude 'subagent'
threads.source if JSON, exclude when json_extract(source, '$.subagent') is present (covers Guardian and Guardian2)
threads.agent_path exclude nested paths; /root and unset remain user-facing
thread_spawn_edges a row whose child_thread_id is this thread is a sub-session (NOT EXISTS, so duplicate child edges cannot multiply rows before the limit)
threads.archived exclude archived rows when the column exists

The previous LEFT JOIN thread_spawn_edges e ON e.child_thread_id = t.id could attach child status and duplicate rows before LIMIT 12. Listing now uses SELECT DISTINCT plus NOT EXISTS on spawn children, and aggregates spawn status with MAX(status) in a subquery.

Schema detection is via PRAGMA table_info / sqlite_master in TypeScript and the same probes in Swift, so older Codex databases missing these columns still work.

This PR is based on main only. It does not include Claude provider / draft PR #33 work, and it does not create a release or tag.

Validation

  • Linux check-gate subset (see below)
  • Full npm run check on macOS CI (includes native helper + visual QA)
  • Relevant connected-device checks, or an explanation of why they do not apply — no device needed; this is a SQLite read-model filter
  • No private data, credentials, proprietary Codex assets, or copied third-party source

CI check is npm run public:check && generated:check && format:check && typecheck && npm test && qa:design && build:bundle && validate.

Ran on Linux, skipping macOS-only native steps:

Step Result
public:check pass
generated:check pass (no generated artifacts needed regenerating)
format:check pass
typecheck pass
Store / unit tests including new sqlite fixtures pass (test/subsession-filter.test.ts, test/local-store.integration.test.ts, and the rest of the unit project except native-helper fixtures)
build:bundle pass
streamdeck validate pass
npm run native:build / compiled-native fixtures / qa:design skipped — no swiftc/Xcode; no rsvg-convert/ImageMagick

Fixtures cover: Guardian excluded via each metadata signal; a user thread titled "Guardian" still shown; 12-row limit filled by real threads despite newer sub-sessions; older schema without the extra columns; focusedThread() skipping sub-sessions; a Guardian child plus its parent (including duplicate spawn edges); native archived-ID exclusion.

User impact

Agent Status keys show recent user chats instead of Approve-for-me Guardian reviewer sessions. Pressing a slot resumes that user chat. New Chat still proves a fresh user-facing thread, not a reviewer sub-session. No migration or settings change.

Open in Web Open in Cursor 

recentThreads() and focusedThread() now drop internal sub-sessions in SQL
before the 12-row limit, using schema-tolerant metadata (thread_source,
source.subagent, agent_path, spawn-edge children) rather than titles.
The native helper applies the same user-facing predicate so New Chat
cannot treat a Guardian reviewer as a valid task.

Reported and diagnosed by Paweł Lipkowski.

Co-authored-by: Todd Dailey <twidtwid@users.noreply.github.com>
@twidtwid
twidtwid marked this pull request as ready for review October 8, 2026 13:23
@twidtwid
twidtwid merged commit f0ed9f4 into main Oct 8, 2026
1 check passed
@twidtwid
twidtwid deleted the cursor/exclude-guardian-subsessions-0114 branch October 8, 2026 13:23
cursor Bot pushed a commit that referenced this pull request Oct 8, 2026
Keep Guardian sub-session SQL filtering from #51 together with the
read-only open/query fail-safe and state_*.sqlite fallback.

Co-authored-by: Todd Dailey <twidtwid@users.noreply.github.com>
twidtwid added a commit that referenced this pull request Oct 8, 2026
…52)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Maintenance work on `main` only (not the Claude/v0.3.0-beta provider
work). No version bump, tag, or deploy.

1. **Audit release blocker.** Bump the `brace-expansion` override to
`>=5.0.12` (resolves 5.0.12) and pin `fast-uri` to 3.1.8. Leave
`opentype.js` at 1.3.4.
2. **SQLite fail-safe.** `#open()` and queries now map missing DB,
WAL/open failures, and schema mismatches to `unsupported-schema`
(`UNSUPPORTED`) instead of throwing. Health and doctor surface a `store`
component. Path discovery still prefers `state_5.sqlite`
(`CODEX_SQLITE_HOME` / `config.toml sqlite_home` unchanged) and falls
back to the highest-numbered `state_*.sqlite` when `state_5` is absent.
3. **Model dial families.** Families are derived from
`models_cache.json` with the existing slug/reasoning allow-list
(including stripping cache-only `max`), falling back to
Luna/Terra/Sol/Astra when the cache is missing.
4. **Cleanup.** Move `test/astra-picker.fixture.test.ts` into
`integrationTests` so `test:fast` is native-free. Update MARKETPLACE.md
(`@elgato/streamdeck` 3.0.1) and add a CHANGELOG Unreleased section (no
version bump).

Merged `origin/main` at `f0ed9f4` (#51 Guardian/subagent SQL filter).
Conflict resolution keeps both: #51's schema-aware
`recentThreads`/`focusedThread` SQL (`thread_source`, `source.subagent`,
`agent_path`, spawn-edge exclusion, archived, DISTINCT/`MAX(status)`,
column detection) and this PR's fail-safe `#open()` wrapper plus
`state_*.sqlite` fallback. Does not edit
`native/ComposerControls.swift`. Native Targeting/Fixtures changes come
from #51.

## Validation

- [ ] `npm run check` (macOS-14 CI on this PR, after merge)
- [x] `npm audit --omit=dev --audit-level=high` and `npm run audit:full`
(0 vulnerabilities; `brace-expansion@5.0.12`, `fast-uri@3.1.8`,
`opentype.js@1.3.4`)
- [x] Relevant connected-device checks, or an explanation of why they do
not apply
- [x] No private data, credentials, proprietary Codex assets, or copied
third-party source

Linux after the merge: `public:check`, `generated:check`,
`format:check`, `typecheck`, `docs:check`, `test:fast` (323 passed, 1
skipped, including #51 `subsession-filter` and this PR's store/model
tests), non-native integration (17 passed), `build:bundle`, `validate`.
Connected-device checks do not apply.

## User impact

- Unreadable Codex state no longer blanks keys; Health and doctor
surface `UNSUPPORTED`.
- Model dial can pick up new cache families without a plugin code
change.
- Guardian reviewer sub-sessions stay excluded from Agent Status (#51).
- No plugin version or Marketplace submission in this PR.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-b6d10954-2a96-5e58-9567-ce559d1d887f?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-b6d10954-2a96-5e58-9567-ce559d1d887f&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Todd Dailey <twidtwid@users.noreply.github.com>
@twidtwid twidtwid mentioned this pull request Oct 8, 2026
4 of 5 tasks
twidtwid added a commit that referenced this pull request Oct 8, 2026
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Prepare the v0.2.5 release from current `main` (`42f8ffe`), following
the v0.2.4 version-bump pattern. No feature work in this PR.

- Bump `0.2.4` → `0.2.5` in `package.json` and both top-level
`package-lock.json` version fields
- Bump plugin `manifest.json` `"Version"` to `"0.2.5.0"` (`SDKVersion`
3, Node.js 24, `MinimumVersion` 7.1 unchanged)
- Fold the Unreleased notes from #51 (Guardian/subagent session filter)
and #52 (SQLite fail-safe, model families, audit overrides) plus
Dependabot bumps including `@elgato/streamdeck` 3.0.1 into `## 0.2.5 —
2026-10-08`

This PR does not include Claude provider / draft PR #33 work. Do not
merge from that beta line. Do not tag or create a GitHub Release here;
tag after merge so `.github/workflows/release.yml` can pack and publish.

## Validation

- [x] Linux-allowed `release:verify` subset: `audit:full`,
`audit:production`, and `docs:check` (macOS-only native/`qa:design`
steps skipped on Linux)
- [x] `test:fast`, `build:bundle`, `streamdeck validate`,
`generated:check`
- [ ] Full `npm run check` on macOS CI
- [x] Relevant connected-device checks, or an explanation of why they do
not apply — version bump and changelog only; no device interaction
- [x] No private data, credentials, proprietary Codex assets, or copied
third-party source

## User impact

- Agent Status and the native helper no longer show or try to resume
Codex Guardian reviewer / subagent sub-sessions (reported by Paweł
Lipkowski; fixes "cannot resume a live Guardian reviewer"). A user chat
titled Guardian still shows.
- Unreadable Codex SQLite state fails closed; Health and doctor report
the store.
- Model dial families come from the Codex models cache.
- Stream Deck SDK 3.0.1 and security overrides (`brace-expansion`,
`fast-uri`) ship with this release.
- Install from the GitHub Release created when v0.2.5 is tagged after
merge.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-c9c04dac-37cf-56af-9592-63ee0b0b2bbf?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-c9c04dac-37cf-56af-9592-63ee0b0b2bbf&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Todd Dailey <twidtwid@users.noreply.github.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.

2 participants