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
5 changes: 5 additions & 0 deletions .changeset/notice-delivery-advertisement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agent-bundle": patch
---

Advertise #99 notice-delivery routes per pinned host in a new `noticeDelivery` capability-table section consumed by the runtime's delivery-route selector: `mcp-inbox` and `mcp-resource-updated` are supported on every target, `next-event` and `current-response` on the three hook-bearing hosts (honestly unavailable on hookless portable), and `directed-push`/`host-toast` carry dated unavailable rows because no pinned host documents a plugin-initiated directed message or toast API (2026-09-02 survey on #99). A pin test enforces the route set, dated reasons, and the per-host truths.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,28 @@
"stdio": true,
"streamableHttp": true
},
"noticeDelivery": {
Comment thread
ScriptedAlchemy marked this conversation as resolved.
"current-response": {
"state": "supported"
},
"directed-push": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-initiated directed cross-actor message API at this pin; the Claude Notification hook observes host-emitted notifications and does not send them.",
"state": "unavailable"
},
"host-toast": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-facing toast/notification send API at this pin.",
"state": "unavailable"
},
"mcp-inbox": {
"state": "supported"
},
"mcp-resource-updated": {
"state": "supported"
},
"next-event": {
"state": "supported"
}
},
"observedCliVersion": "2.1.250",
"plugin": {
"agents": {
Expand Down
22 changes: 22 additions & 0 deletions packages/agent-bundle/src/adapters/capabilities/codex-0.147.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,28 @@
"stdio": true,
"streamableHttp": true
},
"noticeDelivery": {
"current-response": {
"state": "supported"
},
"directed-push": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-initiated directed cross-actor message API at this pin; the Claude Notification hook observes host-emitted notifications and does not send them.",
"state": "unavailable"
},
"host-toast": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-facing toast/notification send API at this pin.",
"state": "unavailable"
},
"mcp-inbox": {
"state": "supported"
},
"mcp-resource-updated": {
"state": "supported"
},
"next-event": {
"state": "supported"
}
},
"observedCliVersion": "0.147.0",
"plugin": {
"apps": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,28 @@
"stdio": true,
"streamableHttp": true
},
"noticeDelivery": {
"current-response": {
"state": "supported"
},
"directed-push": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-initiated directed cross-actor message API at this pin; the Claude Notification hook observes host-emitted notifications and does not send them.",
"state": "unavailable"
},
"host-toast": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-facing toast/notification send API at this pin.",
"state": "unavailable"
},
"mcp-inbox": {
"state": "supported"
},
"mcp-resource-updated": {
"state": "supported"
},
"next-event": {
"state": "supported"
}
},
"observedCliVersion": "2026-08-28",
"plugin": {
"commands": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,30 @@
"stdio": true,
"streamableHttp": true
},
"noticeDelivery": {
"current-response": {
"reason": "2026-09-02: Agent Plugins 1.0.0 defines no hooks, so there is no synchronous hook response surface (https://agent-plugins.org/).",
"state": "unavailable"
},
"directed-push": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-initiated directed cross-actor message API at this pin; the Claude Notification hook observes host-emitted notifications and does not send them.",
"state": "unavailable"
},
"host-toast": {
"reason": "retrieved 2026-09-02 (#99 survey): no documented plugin-facing toast/notification send API at this pin.",
"state": "unavailable"
},
"mcp-inbox": {
"state": "supported"
},
"mcp-resource-updated": {
"state": "supported"
},
"next-event": {
"reason": "2026-09-02: Agent Plugins 1.0.0 defines no hooks, so no event admission surface exists (https://agent-plugins.org/).",
"state": "unavailable"
}
},
"observedSpecificationVersion": "1.0.0",
"plugin": {
"manifest": "plugin.json",
Expand Down
33 changes: 33 additions & 0 deletions packages/agent-bundle/tests/adapter-capability-states.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1052,3 +1052,36 @@ it('pins dated deferral rows for every explicitly deferred native callback from
}
}
});

it('advertises notice delivery routes per host with dated unavailability (#99 stage 4)', async () => {
const { readFile } = await import('node:fs/promises');
const routes = ['current-response', 'directed-push', 'host-toast', 'mcp-inbox', 'mcp-resource-updated', 'next-event'];
const files = {
claude: 'claude-2.1.250.json',
codex: 'codex-0.147.0.json',
cursor: 'cursor-2026-08-28.json',
portable: 'portable-1.0.0.json',
};
for (const [host, file] of Object.entries(files)) {
const table = JSON.parse(await readFile(new URL(`../src/adapters/capabilities/${file}`, import.meta.url), 'utf8')) as Record<string, unknown>;
const advertisement = table.noticeDelivery as Record<string, { reason?: string; state: string }>;
expect(Object.keys(advertisement).sort()).toEqual(routes);
for (const route of routes) {
const entry = advertisement[route]!;
expect(['supported', 'unavailable']).toContain(entry.state);
if (entry.state === 'unavailable') expect(entry.reason).toMatch(/2026-09-02/u);
}
// No pinned host has a directed cross-actor push or toast surface (#99 survey).
expect(advertisement['directed-push']!.state).toBe('unavailable');
expect(advertisement['host-toast']!.state).toBe('unavailable');
// The generated MCP inbox surface exists on every target.
expect(advertisement['mcp-inbox']!.state).toBe('supported');
// Hookless portable honestly loses the hook-borne routes.
if (host === 'portable') {
expect(advertisement['next-event']!.state).toBe('unavailable');
expect(advertisement['current-response']!.state).toBe('unavailable');
} else {
expect(advertisement['next-event']!.state).toBe('supported');
}
}
});
4 changes: 2 additions & 2 deletions packages/agent-bundle/tests/adapter-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ it('records observed capability versions and rehashes schema snapshots against p
}

if (target === 'claude') {
expect(sha256Hex(capability)).toBe('98938d9685411227acee422f90d2e5bb51f33da96ba499aa2ad7b5d3422b37f1');
expect(sha256Hex(capability)).toBe('ad8913270725c3f4abbfbf12bac888092e271cecc9c64adaa114093c9e2e70de');
}
if (target === 'cursor') {
expect(sha256Hex(capability)).toBe('e36e84f829f1c69562647a4bc26ecfbaea2dbd0559f194ed7f52bbf133688fe5');
expect(sha256Hex(capability)).toBe('d056a5575fb98408e12e9236af356227911aec657f226eb720ff9b6a120c5819');
const pluginSchema = JSON.parse(await readFile(
new URL('../src/adapters/schemas/cursor/plugin.schema.json', import.meta.url),
'utf8',
Expand Down
Loading