Skip to content

feat(overseer): emit AGENT_NOTIFY_SUMMARY from Cursor (Half B, piece 1) - #86

Open
heavygee wants to merge 1 commit into
feat/overseer-contract-invisiblefrom
feat/overseer-summary-emit
Open

feat(overseer): emit AGENT_NOTIFY_SUMMARY from Cursor (Half B, piece 1)#86
heavygee wants to merge 1 commit into
feat/overseer-contract-invisiblefrom
feat/overseer-summary-emit

Conversation

@heavygee

Copy link
Copy Markdown
Owner

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.
  • Wired into cursorAcpRemoteLauncher setup (before the backend spawns cursor-agent) + cleanup.
  • Line shape mirrors AGENT_NOTIFY_CONTRACT_INLINE_PREFIX.

Explicitly not doing: no user-turn prepend (the tiann#1095/tiann#1096 prompt-injection anti-pattern), no global ~/.cursor edits.

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 typecheck clean (cli/web/hub)
  • cursorNotifyRuleOverlay.test.ts - 11 tests (write/cleanup/backup+restore/sentinel/dir-prune/idempotent/no-user-delete/stealth-copy)
  • existing cursorAcpRemoteLauncher.test.ts - 19 tests still green
  • operator hapi-restart-hub to activate the CLI change (agents must not restart)
  • soup layer placement coordinated with meta bot (after feat/overseer-contract-invisible)

Made with Cursor

…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>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment on lines +132 to +134
if (preExistingContent !== null) {
// Restore the user's file exactly as it was.
writeFileSync(rulePath, preExistingContent, 'utf-8');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +105 to +107
if (!existsSync(cursorDir)) {
mkdirSync(cursorDir, { recursive: true });
createdDirs.push(cursorDir);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +84 to +87
this.notifyRuleOverlay = installCursorNotifyRuleOverlay({
cwd: session.path,
project: basename(session.path) || null
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

heavygee added a commit that referenced this pull request Jul 24, 2026
…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>
@heavygee

Copy link
Copy Markdown
Owner Author

Tracking: remaining flavor coverage (kimi / pi / generic ACP) is fork issue #89 — needed for next overseer phase full-fleet primary emission.

Design doc: docs/plans/2026-07-24-overseer-summary-emission.md (better-fallback corrected: rarity gate first, full-turn content when LLM path runs — no quality-degrading char caps).

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