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
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ scripts/ Setup and deployment scripts

See `docs/knowledge/core-memory.md` for durable maintenance notes. Do not create dated AI review reports; fold recurring findings into core memory and keep `docs/INDEX.md` updated.

For automation runs, read `$CODEX_HOME/automations/code-smell-detector/memory.md` before scanning commits. In sandboxed checkouts, use the writable Bun/Wrangler paths recorded in `docs/knowledge/core-memory.md` if verification commands hit tempdir or Wrangler log permission errors.

**Architecture**: Single Cloudflare Worker serves both the REST API (`/api/v1/*`) and dashboard static assets.

## Dev Commands
Expand Down Expand Up @@ -123,7 +125,7 @@ Run all quality checks in parallel. If any regress, fix before proceeding.
bunx biome check packages/api/src/
bunx tsc --noEmit -p packages/api/tsconfig.json
cd packages/api && bunx vitest run
cd packages/dashboard && bunx tsc --noEmit
cd packages/dashboard && bun run build
git status --short
```

Expand Down
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ scripts/ Setup and deployment scripts

See `docs/knowledge/core-memory.md` for durable maintenance notes. Do not create dated AI review reports; fold recurring findings into core memory and keep `docs/INDEX.md` updated.

For automation runs, read `$CODEX_HOME/automations/code-smell-detector/memory.md` before scanning commits. In sandboxed checkouts, use the writable Bun/Wrangler paths recorded in `docs/knowledge/core-memory.md` if verification commands hit tempdir or Wrangler log permission errors.

**Architecture**: Single Cloudflare Worker serves both the REST API (`/api/v1/*`) and dashboard static assets.

## Dev Commands
Expand Down Expand Up @@ -123,7 +125,7 @@ Run all quality checks in parallel. If any regress, fix before proceeding.
bunx biome check packages/api/src/
bunx tsc --noEmit -p packages/api/tsconfig.json
cd packages/api && bunx vitest run
cd packages/dashboard && bunx tsc --noEmit
cd packages/dashboard && bun run build
git status --short
```

Expand Down
4 changes: 4 additions & 0 deletions docs/knowledge/core-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ Durable notes for recurring maintenance. Keep this file small and update it inst
- `CLAUDE.md` is the main repo guide; root `AGENTS.md` carries the same guidance for Codex and other agents.
- Use `PLAN.md` as the autonomous maintenance playbook, but store recurring lessons here.
- Do not create new snapshot files like `docs/API_DOCS_REVIEW.md`, `docs/test-coverage-analysis.md`, or `docs/reviews/code-smell-dead-code-*.md`.
- For code-smell automation, read `$CODEX_HOME/automations/code-smell-detector/memory.md` first, scan commits since that timestamp, then fall back to the last 24 hours or 7 days only when needed.
- When refreshing `/agents.md`, edit `packages/api/src/content/agents.md` and regenerate `packages/api/src/content/static.ts`.
- In sandboxed maintenance runs, set Bun and Wrangler writable paths when needed: `BUN_TMPDIR=/private/tmp/codex-bun-tmp`, `BUN_INSTALL_CACHE_DIR=/private/tmp/codex-bun-cache`, and `XDG_CONFIG_HOME=/private/tmp/codex-wrangler-config`.
- Validate dashboard changes with `cd packages/dashboard && bun run build`; raw `bunx tsc --noEmit` can fail in fresh checkouts before Next generates route type files.

## Review Memory

- Historical API-doc review notes from March 2026 were folded into the live docs. Keep API endpoint coverage current in `docs/api-reference.md`, `docs/sdk.md`, and `docs/integration.md`.
- Historical test-coverage notes were stale after the test suite expanded. Use current `packages/api/test/` coverage and CI output as the source of truth before adding tests.
- Recent state-platform maintenance should cover sparse `/api/v2/states/query` filters. Tag and JSON-path queries must keep scanning past nonmatching rows instead of stopping at the first capped candidate page.
- Sparse state-query cap tests seed enough D1 rows to run close to Vitest's default timeout under full-suite load; keep an explicit per-test timeout on that coverage instead of changing production scan behavior.
- The TypeScript LangGraph adapter should extend `BaseCheckpointSaver` from `@langchain/langgraph-checkpoint`; keep the optional peer and dev dependency aligned so SDK type/build checks verify that contract.
86 changes: 46 additions & 40 deletions packages/api/test/state-platform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,51 +147,57 @@ describe("State platform", () => {
expect(body.data.map((row: any) => row.state_key)).toEqual(["sparse-match"]);
});

it("returns a cursor when sparse query scanning reaches the per-request cap", async () => {
await putState("sparse-capped-match", {
agent_id: "query-agent-sparse-capped",
data: { status: "done", nested: { priority: "high" } },
tags: ["sparse-capped-match"],
});

for (let index = 0; index < 55; index++) {
await putState(`sparse-capped-miss-${index}`, {
agent_id: "query-agent-sparse-capped",
data: { status: "pending", nested: { priority: "low" } },
tags: ["sparse-capped-miss"],
});
}

const first = await SELF.fetch("http://localhost/api/v2/states/query", {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
it(
"returns a cursor when sparse query scanning reaches the per-request cap",
async () => {
await putState("sparse-capped-match", {
agent_id: "query-agent-sparse-capped",
data: { status: "done", nested: { priority: "high" } },
tags: ["sparse-capped-match"],
limit: 1,
}),
});
});

expect(first.status).toBe(200);
const firstBody = await first.json<any>();
expect(firstBody.data).toEqual([]);
expect(firstBody.pagination.next_cursor).toEqual(expect.any(String));
await Promise.all(
Array.from({ length: 55 }, (_, index) =>
putState(`sparse-capped-miss-${index}`, {
agent_id: "query-agent-sparse-capped",
data: { status: "pending", nested: { priority: "low" } },
tags: ["sparse-capped-miss"],
}),
),
);

const first = await SELF.fetch("http://localhost/api/v2/states/query", {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
agent_id: "query-agent-sparse-capped",
tags: ["sparse-capped-match"],
limit: 1,
}),
});

const second = await SELF.fetch("http://localhost/api/v2/states/query", {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
agent_id: "query-agent-sparse-capped",
tags: ["sparse-capped-match"],
limit: 1,
cursor: firstBody.pagination.next_cursor,
}),
});
expect(first.status).toBe(200);
const firstBody = await first.json<any>();
expect(firstBody.data).toEqual([]);
expect(firstBody.pagination.next_cursor).toEqual(expect.any(String));

const second = await SELF.fetch("http://localhost/api/v2/states/query", {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
agent_id: "query-agent-sparse-capped",
tags: ["sparse-capped-match"],
limit: 1,
cursor: firstBody.pagination.next_cursor,
}),
});

expect(second.status).toBe(200);
const secondBody = await second.json<any>();
expect(secondBody.data.map((row: any) => row.state_key)).toEqual(["sparse-capped-match"]);
});
expect(second.status).toBe(200);
const secondBody = await second.json<any>();
expect(secondBody.data.map((row: any) => row.state_key)).toEqual(["sparse-capped-match"]);
},
15_000,
);

it("enforces leases for protected writes", async () => {
await putState("leased-run", { agent_id: "lease-agent", data: { value: 1 } });
Expand Down
Loading