feat(overseer): emit AGENT_NOTIFY_SUMMARY from Cursor (Half B, piece 1) - #86
feat(overseer): emit AGENT_NOTIFY_SUMMARY from Cursor (Half B, piece 1)#86heavygee wants to merge 1 commit into
Conversation
…cursor rule Cursor sessions (~95% of the fleet) emitted no AGENT_NOTIFY_SUMMARY, so the overseer/inbox/session-log were blind. cursor-agent has no HAPI system-prompt channel; it only reads workspace .cursor/rules/*.mdc. Install a per-session, non-clobbering, transient rule (alwaysApply) at spawn and restore/remove it at teardown, mirroring config-overlay backup/restore discipline. - cursorNotifyRuleOverlay: install/backup/restore/cleanup with own-file sentinel and created-dir pruning; fail-open. - Wired into cursorAcpRemoteLauncher setup + cleanup. - No user-turn prepend (the tiann#1095/tiann#1096 anti-pattern); no global ~/.cursor edits. Fork-only overseer work. Design + stealth rationale in docs/plans. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ef0242603
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (preExistingContent !== null) { | ||
| // Restore the user's file exactly as it was. | ||
| writeFileSync(rulePath, preExistingContent, 'utf-8'); |
There was a problem hiding this comment.
Avoid clobbering edits to backed-up rule files
When a workspace already has .cursor/rules/hapi-session.mdc, cleanup always restores the in-memory preExistingContent without checking what is currently on disk. If the user or another tool edits/replaces that rule while the HAPI session is running, teardown silently rolls it back to stale contents, unlike the no-backup path which checks for the sentinel before deleting; please only restore when the current file is still the HAPI overlay or otherwise preserve the new user content.
Useful? React with 👍 / 👎.
| } | ||
| } | ||
|
|
||
| writeFileSync(rulePath, buildNotifyRuleContent(opts), 'utf-8'); |
There was a problem hiding this comment.
Refuse symlinked Cursor rule targets before writing
When a checked-out workspace contains .cursor/rules/hapi-session.mdc as a symlink, this write follows the link and temporarily overwrites the target with the HAPI rule. That lets an untrusted repo clobber arbitrary user-owned files for the lifetime of the session (and permanently if cleanup does not run), so the overlay should lstat/skip symlinked paths or use a no-follow create/replace path before writing.
Useful? React with 👍 / 👎.
| if (!existsSync(cursorDir)) { | ||
| mkdirSync(cursorDir, { recursive: true }); | ||
| createdDirs.push(cursorDir); |
There was a problem hiding this comment.
Do not create missing workspace roots
With a stale or deleted cwd, this recursive mkdir creates <cwd> just to place .cursor, but cleanup only tracks .cursor and rules, leaving the previously missing workspace root behind and potentially letting Cursor start in an empty project instead of failing on the bad path. Please first verify cwd is an existing directory and fail open without creating it.
Useful? React with 👍 / 👎.
| this.notifyRuleOverlay = installCursorNotifyRuleOverlay({ | ||
| cwd: session.path, | ||
| project: basename(session.path) || null | ||
| }); |
There was a problem hiding this comment.
Strip notify summaries from the terminal buffer
When this overlay makes Cursor append AGENT_NOTIFY_SUMMARY, terminal-driven sessions that switch to remote still render assistant text from handleAgentMessage via messageBuffer.addMessage(message.text, 'assistant'), and OpencodeDisplay formats msg.content without stripAgentContract. In that TTY path humans will see the supposedly hidden machine line every turn, so strip it before adding to the Ink buffer while still sending the raw text to the hub.
Useful? React with 👍 / 👎.
…nvisible Half-B overseer emission (fork-only, PR #86/#87, do NOT upstream), stacked: emit (CLI, 9ef0242) then fallback (hub-only, db755c7), inserted after feat/overseer-contract-invisible per peer request. Not yet activated — blocked behind the v0.23.4 upstream bump sweep (fork main 23 behind); layers will land on the fresh base during that rematerialize + hub restart. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Tracking: remaining flavor coverage (kimi / pi / generic ACP) is fork issue #89 — needed for next overseer phase full-fleet primary emission. Design doc: |
Summary
Half B of the overseer contract: make Cursor sessions actually emit
AGENT_NOTIFY_SUMMARY. PR #81 shipped the invisibility half (strip/parse), but the hub deliberately never injected the contract for Cursor and no compensating rule existed - so ~95% of the fleet emitted nothing and the overseer was blind.cursor-agent has no HAPI-controlled system-prompt channel; it only discovers rules from workspace
.cursor/rules/*.mdc. This PR installs a per-session, transient, non-clobbering rule at spawn and restores/removes it at teardown.cursorNotifyRuleOverlay.ts-installCursorNotifyRuleOverlay({ cwd, project })writes<cwd>/.cursor/rules/hapi-session.mdc(alwaysApply: true), backs up any pre-existing user file, uses an own-file sentinel so a concurrent/prior HAPI session's file is never mistaken for user content, prunes only dirs it created, and is fail-open.cursorAcpRemoteLaunchersetup (before the backend spawns cursor-agent) + cleanup.AGENT_NOTIFY_CONTRACT_INLINE_PREFIX.Explicitly not doing: no user-turn prepend (the tiann#1095/tiann#1096 prompt-injection anti-pattern), no global
~/.cursoredits.Fork-only overseer work - never upstream. Design + stealth rationale:
docs/plans/2026-07-24-overseer-summary-emission.md.A hub-side deterministic backstop (for turns where rule compliance still slips) stacks on top in
feat/overseer-summary-fallback.Test plan
bun typecheckclean (cli/web/hub)cursorNotifyRuleOverlay.test.ts- 11 tests (write/cleanup/backup+restore/sentinel/dir-prune/idempotent/no-user-delete/stealth-copy)cursorAcpRemoteLauncher.test.ts- 19 tests still greenhapi-restart-hubto activate the CLI change (agents must not restart)feat/overseer-contract-invisible)Made with Cursor