mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 10:26:26 +01:00
fix(runner): kill stale semantic-catalog counts and drift-check the doc
The catalog doc claimed 36 tools / 22 optional while the catalog holds 37 / 23 (the 36-vs-37 drift the reconciliation plan flagged). Correct the prose and add src/catalog/catalog-docs.test.ts, which recomputes the total/always/optional counts and the operation-id membership from the catalog so a stale hand count can no longer pass. Refs PAP-17025. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
63d691aeb6
commit
3d6a45e4d7
2 files changed
+65
-2
No files matched your search
@@ -17,9 +17,12 @@ list, not a disposition — they are never exposed as tools. See
|
||||
[capability disposition](capability-disposition.md) and
|
||||
[authorization and exposure](capability-authorization-and-exposure.md).
|
||||
|
||||
The catalog holds **36 tools**: 14 always-agent tools and 22 optional tools
|
||||
The catalog holds **37 tools**: 14 always-agent tools and 23 optional tools
|
||||
across 10 groups.
|
||||
|
||||
<!-- These counts are drift-checked against src/tools/capability-semantic-tool-catalog.ts
|
||||
by src/catalog/catalog-docs.test.ts; update the catalog, not the numbers. -->
|
||||
|
||||
### Always-agent tools (14)
|
||||
|
||||
`get_task_context`, `get_task_history`, `list_documents`, `read_document`,
|
||||
@@ -27,7 +30,7 @@ across 10 groups.
|
||||
`finish_task`, `block_task`, `request_review`, `write_document`,
|
||||
`request_human_input`, `register_deliverable`, `inspect_operation_result`.
|
||||
|
||||
### Optional tools (22), by group
|
||||
### Optional tools (23), by group
|
||||
|
||||
| Group | Tools |
|
||||
| --- | --- |
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
CAPABILITY_SEMANTIC_TOOL_CATALOG as SCENARIO_CATALOG,
|
||||
capabilitySemanticTool,
|
||||
} from "../tools/capability-semantic-tool-catalog.js";
|
||||
|
||||
const docPath = resolve(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
"..",
|
||||
"..",
|
||||
"docs",
|
||||
"capability-semantic-tools.md",
|
||||
);
|
||||
const doc = readFileSync(docPath, "utf8");
|
||||
|
||||
/** The catalog counts region, between the disposition prose and descriptor shape. */
|
||||
function countsRegion(): string {
|
||||
const start = doc.indexOf("## Two dispositions");
|
||||
const end = doc.indexOf("## Descriptor shape");
|
||||
expect(start).toBeGreaterThanOrEqual(0);
|
||||
expect(end).toBeGreaterThan(start);
|
||||
return doc.slice(start, end);
|
||||
}
|
||||
|
||||
describe("capability-semantic-tools.md stays in sync with the catalog", () => {
|
||||
const always = SCENARIO_CATALOG.filter((tool) => tool.disposition === "always_agent_tool");
|
||||
const optional = SCENARIO_CATALOG.filter((tool) => tool.disposition === "optional_agent_tool");
|
||||
|
||||
it("states the current total, always, and optional counts", () => {
|
||||
const region = countsRegion();
|
||||
const total = /holds \*\*(\d+) tools\*\*/.exec(region)?.[1];
|
||||
const alwaysProse = /(\d+) always-agent tools and (\d+) optional tools/.exec(region);
|
||||
const alwaysHeader = /### Always-agent tools \((\d+)\)/.exec(region)?.[1];
|
||||
const optionalHeader = /### Optional tools \((\d+)\)/.exec(region)?.[1];
|
||||
|
||||
expect(Number(total)).toBe(SCENARIO_CATALOG.length);
|
||||
expect(Number(alwaysProse?.[1])).toBe(always.length);
|
||||
expect(Number(alwaysProse?.[2])).toBe(optional.length);
|
||||
expect(Number(alwaysHeader)).toBe(always.length);
|
||||
expect(Number(optionalHeader)).toBe(optional.length);
|
||||
// Guard against the historical 36-vs-37 drift the reconciliation plan flagged.
|
||||
expect(SCENARIO_CATALOG.length).toBe(37);
|
||||
});
|
||||
|
||||
it("lists exactly the catalog's operation ids in the counts region", () => {
|
||||
const region = countsRegion();
|
||||
const backticked = new Set(
|
||||
[...region.matchAll(/`([a-z_]+)`/g)]
|
||||
.map((match) => match[1])
|
||||
.filter((id) => capabilitySemanticTool(id) !== undefined),
|
||||
);
|
||||
expect([...backticked].sort()).toEqual(
|
||||
SCENARIO_CATALOG.map((tool) => tool.operationId).sort(),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user