Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@useorgx/cursor-plugin",
"description": "OrgX execution control plane for Cursor with bootstrap, resumable workstreams, proof, decisions, Work Graph hooks, and specialist agents.",
"version": "0.1.4",
"version": "0.1.5",
"author": {
"name": "OrgX Team",
"email": "team@useorgx.com"
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ capture. The Wizard owns the durable queue, acknowledgement, retry, and AWR
delivery path. The adapter never forwards prompts, tool inputs or outputs,
transcript paths, user email, or error text.

Set `ORGX_SESSION_SUMMARY_AUTO_FLUSH=off` for a deliberately offline run. The
adapter and Wizard retain the capture without starting a delivery worker;
`orgx-wizard hooks flush` can replay it later with server acknowledgement.

Cursor cloud agents support the prompt, tool, subagent, and `stop` subset but
do not run the local `sessionStart` or `sessionEnd` hooks. Cloud proof is
therefore capability-bounded: `RunEnd` can issue a run receipt when the shared
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@useorgx/cursor-plugin",
"version": "0.1.4",
"version": "0.1.5",
"description": "OrgX plugin for Cursor with MCP, rules, skills, passive Work Graph hooks, commands, and specialist agents.",
"type": "module",
"private": false,
Expand Down
5 changes: 5 additions & 0 deletions scripts/hooks/session-summary-bridge.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ function defaultHookPath(env) {
);
}

function autoFlushDisabled(value) {
return ['off', 'false', '0'].includes(String(value ?? '').trim().toLowerCase());
}

function triggerFlush({ env, spawnImpl, queueDir }) {
if (autoFlushDisabled(env.ORGX_SESSION_SUMMARY_AUTO_FLUSH)) return false;
try {
const args = ['hooks', 'flush', '--background', '--limit=25'];
if (queueDir) args.push(`--queue=${queueDir}`);
Expand Down
30 changes: 30 additions & 0 deletions scripts/hooks/session-summary-bridge.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,36 @@ test('delegates to the installed Wizard hook and starts fallback delivery', asyn
}
});

test('keeps an offline run queued without starting fallback delivery', async () => {
const dir = mkdtempSync(join(tmpdir(), 'orgx-cursor-bridge-'));
const hookPath = join(dir, 'orgx-session-summary.mjs');
writeFileSync(hookPath, 'export async function main() {}\n', 'utf8');
let spawns = 0;
try {
const result = await bridgeCursorSessionSummary({
event: 'run_end',
payload: { conversation_id: 'conversation-offline' },
hookPath,
env: {
PATH: process.env.PATH,
ORGX_SESSION_SUMMARY_AUTO_FLUSH: 'off',
},
moduleLoader: async () => ({
main: async () => ({ ok: true, queued: true, delivery_triggered: false }),
}),
spawnImpl: () => {
spawns += 1;
throw new Error('offline capture must not spawn');
},
});

assert.equal(result.fallback_delivery_triggered, false);
assert.equal(spawns, 0);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});

test('reports a missing shared hook without inventing capture', async () => {
const result = await bridgeCursorSessionSummary({
event: 'run_end',
Expand Down
Loading