Files
msd-core/tests/cursor-dispatch-upgrade.test.cjs

72 lines
3.2 KiB
JavaScript

'use strict';
/**
* cursor dispatch UPGRADE — ADR-1239 / #2089 AC4b.
*
* Proves GSD's wave-based execution drives Cursor's native named/background
* nested subagent dispatch (background:true, backgroundDispatch:true,
* nested:true, maxDepth:2) instead of flattening to inline sequential calls.
*
* Cite:
* https://cursor.com/docs/subagents — named + background dispatch
* https://cursor.com/docs/sdk/typescript — nested subagent depth-2 constraint
*/
const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { shouldFlattenDispatch } = require('../gsd-core/bin/lib/host-integration.cjs');
const CUR_CAP = JSON.parse(
fs.readFileSync(path.join(__dirname, '..', 'capabilities', 'cursor', 'capability.json'), 'utf8'),
);
const CUR_DISPATCH = CUR_CAP.runtime.hostIntegration.dispatch;
// -- AC4b: cursor dispatch axes ----------------------------------------------
test('cursor dispatch declares namedDispatch + nested + background + backgroundDispatch', () => {
assert.equal(CUR_DISPATCH.namedDispatch, true,
'cite https://cursor.com/docs/subagents — named subagent invocation');
assert.equal(CUR_DISPATCH.nested, true,
'cite https://cursor.com/docs/sdk/typescript — nested subagents');
assert.equal(CUR_DISPATCH.background, true,
'cite https://cursor.com/docs/subagents — background dispatch');
assert.equal(CUR_DISPATCH.backgroundDispatch, true,
'cite https://cursor.com/docs/subagents FAQ — subagents can launch child subagents');
});
test('cursor dispatch respects maxDepth: 2 (the documented constraint)', () => {
assert.equal(CUR_DISPATCH.maxDepth, 2,
'cite https://cursor.com/docs/sdk/typescript — "a subagent launched by another subagent can\'t launch further"');
});
// -- AC4b: shouldFlattenDispatch returns false (NOT force-flattened) ----------
test('shouldFlattenDispatch(cursor) is false — GSD uses native background dispatch', () => {
assert.equal(shouldFlattenDispatch(CUR_DISPATCH), false,
'cursor has background:true + backgroundDispatch:true → GSD must NOT force-flatten');
});
test('pre-upgrade cursor axes (background:false) DID force-flatten', () => {
const preUpgrade = { ...CUR_DISPATCH, background: false, backgroundDispatch: 'undocumented' };
assert.equal(shouldFlattenDispatch(preUpgrade), true,
'pre-upgrade cursor (no background dispatch) was force-flattened — the behavioral change #2089 lands');
});
test('shouldFlattenDispatch is true when backgroundDispatch is false (depth-2 but no bg dispatch)', () => {
const noBgDispatch = { ...CUR_DISPATCH, backgroundDispatch: false };
assert.equal(shouldFlattenDispatch(noBgDispatch), true,
'background without backgroundDispatch still flattens (the #853 rule)');
});
// -- AC4b: boundary — maxDepth 2 is the discriminator vs unbounded -----------
test('maxDepth 2 is the documented constraint (not -1 unbounded)', () => {
assert.notEqual(CUR_DISPATCH.maxDepth, -1,
'cursor is NOT unbounded — depth-2 is the documented hard limit');
assert.ok(CUR_DISPATCH.maxDepth > 0 && CUR_DISPATCH.maxDepth <= 2,
'maxDepth must be a positive integer ≤ 2 per cursor docs');
});