Skip to content
Open
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
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ complete alternative. Require a current caller or explicit approval for adapter
parity. Review necessity separately from correctness; passing tests do not justify
scope growth. Split at real ownership boundaries, not by deleting safety coverage.

For non-trivial work, make that standard operational:

- Before coding, publish a short scope checkpoint: required behavior, non-goals,
existing owners/platform support to reuse, expected files, and a rough production
diff budget (separate from tests/docs). A small fix needs only a sentence, not a
design ceremony.
- Use one implementation owner per end-to-end change. Reviewers challenge necessity
as well as correctness; delegate bounded evidence/review, not competing rewrites.
Review the first working slice before expanding the design, without blocking
ordinary human UI feedback on a full validation cycle.
- Justify each new abstraction, lifecycle owner, timer, retry policy, or shared
contract expansion against a current requirement. If the implementation materially
exceeds the checkpoint, stop adding machinery and show the smallest alternative
and any behavior tradeoff before continuing. Do not silently weaken agreed behavior.
- Assess the combined feature diff, including stacked PRs. Passing tests, splitting
PRs, or already-invested work do not establish proportionality. Preserve required
regression coverage; do not game the budget by deleting tests or compressing code.
Keep speculative hardening and unrelated failures outside the task.
- Close with one verified end-to-end result and explicit remaining gaps, not a chain
of green intermediate repairs presented as completion.

Keep files cohesive and group modules and tests by owner. Treat size as a review
signal, not a quota. Extract stable boundaries only when they simplify the
requested change.
Expand Down
83 changes: 83 additions & 0 deletions dev/relay-broker-api.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,86 @@ test("both real sign and publish routes admit direct replies but reject arbitrar
await h.close();
}
});

test("held optional snapshot body leaves ordinary broker capacity free and start credit untouched", async () => {
let release;
const h = await harness((call) => {
if (call.body?.[0]?.kinds?.includes(20001))
return new Response(
new ReadableStream({
start(controller) {
release = () => {
controller.enqueue(new TextEncoder().encode("[]"));
controller.close();
};
},
}),
);
return Response.json([]);
});
const presence = [{ kinds: [20001], authors: [h.event.pubkey], limit: 1 }];
try {
const snapshot = h.post("presence-snapshot", presence);
await vi.waitFor(() => expect(release).toBeTypeOf("function"));
const duplicate = await h.post("presence-snapshot", presence);
expect(duplicate.status).toBe(204);
expect((await h.post("query", filters)).status).toBe(200);
expect(h.calls).toHaveLength(2);
expect(h.calls[1].at - h.calls[0].at).toBeLessThan(400);
release();
release = undefined;
expect(await (await snapshot).json()).toEqual([]);
expect(
(await h.post("presence-snapshot", [{ ...presence[0], authors: [] }]))
.status,
).toBe(400);
expect(
(
await h.post("presence-snapshot", [
{ ...presence[0], authors: Array(257).fill(h.event.pubkey) },
])
).status,
).toBe(400);
expect(h.calls).toHaveLength(2);
} finally {
release?.();
await h.close();
}
});

test("presence snapshot progresses while an ordinary response body is held", async () => {
let release;
const h = await harness((call) => {
if (call.body?.[0]?.kinds?.includes(20001)) return Response.json([]);
return new Response(
new ReadableStream({
start(controller) {
release = () => {
controller.enqueue(new TextEncoder().encode("[]"));
controller.close();
};
},
}),
);
});
let ordinary;
try {
ordinary = h.post("query", filters, undefined, "background");
await vi.waitFor(() => expect(release).toBeTypeOf("function"));
const snapshot = await h.post("presence-snapshot", [
{ kinds: [20001], authors: [h.event.pubkey], limit: 1 },
]);
expect(snapshot.status).toBe(200);
expect(await snapshot.json()).toEqual([]);
expect(h.calls).toHaveLength(2);
const missing = await h.post("stream-presence", {
streamId: "0".repeat(32),
status: "online",
});
expect(await missing.json()).toEqual({ accepted: null });
} finally {
release?.();
await ordinary;
await h.close();
}
});
Loading
Loading