agent-control-plane-core 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/conformance.mjs +33 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-control-plane-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Vendor-neutral control-plane contract for coding agents: a normalized ToolCallEvent/Verdict schema with per-agent adapters (Claude Code, Codex, Amp, Gemini CLI) and a conformance suite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/conformance.mjs
CHANGED
|
@@ -124,23 +124,34 @@ export function assertToolAliasesCovered(
|
|
|
124
124
|
* @param {any} assert node:assert/strict (injected)
|
|
125
125
|
*/
|
|
126
126
|
export function assertAliasedInputsCanonical(fixturesList, assert) {
|
|
127
|
-
for (const fixtures of fixturesList)
|
|
128
|
-
for (const testCase of fixtures.cases)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
127
|
+
for (const fixtures of fixturesList)
|
|
128
|
+
for (const testCase of fixtures.cases)
|
|
129
|
+
assertAliasedInput(fixtures.agent, testCase.name, testCase.event, assert);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The per-event half of {@link assertAliasedInputsCanonical}, shared with
|
|
134
|
+
* {@link runAdapterConformance} so the rule holds against a LIVE parse and not
|
|
135
|
+
* only against the fixture file.
|
|
136
|
+
* @param {string} agent
|
|
137
|
+
* @param {string} caseName
|
|
138
|
+
* @param {any} event a normalized ToolCallEvent
|
|
139
|
+
* @param {any} assert node:assert/strict (injected)
|
|
140
|
+
*/
|
|
141
|
+
function assertAliasedInput(agent, caseName, event, assert) {
|
|
142
|
+
const nativeTool = event?.meta?.native_tool;
|
|
143
|
+
const canon = event?.tool;
|
|
144
|
+
// Only a RENAME makes the promise; a native-named tool advertises nothing.
|
|
145
|
+
if (typeof nativeTool !== "string" || nativeTool === canon) return;
|
|
146
|
+
const key = lookup(
|
|
147
|
+
/** @type {Record<string, string>} */ (MODELED_TOOL_INPUT_KEYS),
|
|
148
|
+
canon,
|
|
149
|
+
);
|
|
150
|
+
if (key === undefined) return;
|
|
151
|
+
assert.ok(
|
|
152
|
+
event.input !== undefined && Object.hasOwn(event.input, key),
|
|
153
|
+
`'${caseName}' (${agent}): ${JSON.stringify(nativeTool)} was canonicalized to ${JSON.stringify(canon)}, which advertises input.${key}, but the input carries ${JSON.stringify(Object.keys(event.input ?? {}))} — rename the input keys or drop the alias`,
|
|
154
|
+
);
|
|
144
155
|
}
|
|
145
156
|
|
|
146
157
|
/**
|
|
@@ -217,6 +228,11 @@ export function runAdapterConformance({ adapter, fixtures, assert }) {
|
|
|
217
228
|
testCase.event,
|
|
218
229
|
`parse mismatch: ${testCase.name}`,
|
|
219
230
|
);
|
|
231
|
+
// Against what parse ACTUALLY produced, not the fixture's copy of it. The
|
|
232
|
+
// deepEqual above ties the two today, but it is the fixture that gets
|
|
233
|
+
// updated when an adapter changes — so checking the fixture alone would let
|
|
234
|
+
// a rename-without-its-input land by editing the expectation.
|
|
235
|
+
assertAliasedInput(adapter.AGENT, testCase.name, parsed, assert);
|
|
220
236
|
|
|
221
237
|
if (testCase.call_class !== undefined) {
|
|
222
238
|
assert.ok(
|