@armoriq/policy-ir 0.1.0

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.
@@ -0,0 +1,497 @@
1
+ {
2
+ "_comment": [
3
+ "Golden vectors for the tool-inventory canonicalizer (Tool Inventory PRD T4, armoriq/conmap-auto#968).",
4
+ "Three implementations must agree byte-for-byte: conmap src/tool-inventory/canonical.ts,",
5
+ "armoriq-sdk-customer (python) and armoriq-sdk-customer-ts. conmap is the source of truth;",
6
+ "each SDK keeps a byte-identical copy of this file plus its sha256 in a sibling .sha256, and a",
7
+ "test in each repo asserts the file still hashes to it -- so changing a vector forces all three",
8
+ "copies to move together.",
9
+ "canonicalJson = sorted keys, compact separators, ensure_ascii escaping. This is NOT RFC 8785;",
10
+ "see the header of canonical.ts for why, and vector 5 for the number forms left outside the",
11
+ "agreed set."
12
+ ],
13
+ "algorithm": {
14
+ "canonicalJson": "sorted keys, no whitespace, ASCII-escaped (json.dumps sort_keys=True separators=(',',':') ensure_ascii=True)",
15
+ "schemaHash": "'sha256:' + sha256_hex(canonicalJson(strip description/title only where they are annotation keywords (never as names under properties/patternProperties/$defs/definitions/dependentSchemas or strings in required, never inside enum/const/default/examples values), resolve local #/ $ref)); null when inputSchema is null",
16
+ "manifestHash": "'sha256:' + sha256_hex(canonicalJson({name, description|null, annotations|{}, inputSchema|null}))"
17
+ },
18
+ "vectors": [
19
+ {
20
+ "id": 1,
21
+ "name": "key-order-irrelevant",
22
+ "note": "Object keys are sorted, so two spellings that differ only in key order produce identical bytes.",
23
+ "inputSchema": {
24
+ "type": "object",
25
+ "required": [
26
+ "b"
27
+ ],
28
+ "properties": {
29
+ "b": {
30
+ "type": "string"
31
+ },
32
+ "a": {
33
+ "type": "number"
34
+ }
35
+ }
36
+ },
37
+ "schemaHash": "sha256:597b8b01f9b5b640dd6856455c6156c631bb3e36768be54f79f21c89392c064d",
38
+ "equivalentSpellings": [
39
+ {
40
+ "properties": {
41
+ "a": {
42
+ "type": "number"
43
+ },
44
+ "b": {
45
+ "type": "string"
46
+ }
47
+ },
48
+ "required": [
49
+ "b"
50
+ ],
51
+ "type": "object"
52
+ }
53
+ ]
54
+ },
55
+ {
56
+ "id": 2,
57
+ "name": "nested-description-and-title-stripped",
58
+ "note": "description and title are removed wherever they are schema annotation keywords, so prose-only edits never move schemaHash. Equals vector 1.",
59
+ "inputSchema": {
60
+ "title": "Thing",
61
+ "description": "top level prose",
62
+ "type": "object",
63
+ "required": [
64
+ "b"
65
+ ],
66
+ "properties": {
67
+ "a": {
68
+ "type": "number",
69
+ "description": "the a"
70
+ },
71
+ "b": {
72
+ "title": "B",
73
+ "type": "string",
74
+ "description": "the b"
75
+ }
76
+ }
77
+ },
78
+ "schemaHash": "sha256:597b8b01f9b5b640dd6856455c6156c631bb3e36768be54f79f21c89392c064d",
79
+ "equalsVector": 1
80
+ },
81
+ {
82
+ "id": 3,
83
+ "name": "local-ref-resolved",
84
+ "note": "A local #/$defs pointer is inlined before hashing, so spelling a shape out and pointing at it hash the same.",
85
+ "inputSchema": {
86
+ "type": "object",
87
+ "$defs": {
88
+ "Id": {
89
+ "type": "string",
90
+ "pattern": "^[a-z]+$"
91
+ }
92
+ },
93
+ "properties": {
94
+ "id": {
95
+ "$ref": "#/$defs/Id"
96
+ }
97
+ }
98
+ },
99
+ "schemaHash": "sha256:ed8f92e2b3119b897b4c3fb2322e4a94aefb4e345b2520c95ef96459ff532073"
100
+ },
101
+ {
102
+ "id": 4,
103
+ "name": "unicode-including-astral-plane",
104
+ "note": "Non-ASCII escapes as \\uXXXX; an astral-plane character (U+1F600, U+1F680) escapes as its UTF-16 surrogate pair, matching Python ensure_ascii and JS charCodeAt iteration. All keys here are ASCII on purpose: JS sorts keys by UTF-16 code unit and Python by code point, which differ for astral-plane KEYS, so those are outside the agreed set.",
105
+ "inputSchema": {
106
+ "type": "string",
107
+ "enum": [
108
+ "caf\u00e9",
109
+ "\u65e5\u672c\u8a9e",
110
+ "\ud83d\ude00"
111
+ ],
112
+ "const": "na\u00efve \ud83d\ude80"
113
+ },
114
+ "schemaHash": "sha256:bd1abce15a0b8bcd6e5c0571a22858e1e14d889ed9ffc68fc2c06f4c5c68be40"
115
+ },
116
+ {
117
+ "id": 5,
118
+ "name": "number-forms",
119
+ "note": "Numbers are emitted by the host JSON writer, not RFC 8785. Integers and decimals are distinct canonical bytes.",
120
+ "knownDivergence": "A float-valued integer diverges across languages (Python json.dumps(1.0) -> \"1.0\", JSON.stringify(1.0) -> \"1\"), as does -0.0 (Python \"-0.0\", JS \"0\"). Neither appears in a real JSON Schema, and neither is in this vector: agreeing on them requires a shared number formatter, which is the RFC 8785 migration, not a patch here.",
121
+ "inputSchema": {
122
+ "type": "number",
123
+ "multipleOf": 1,
124
+ "minimum": 0,
125
+ "maximum": 10,
126
+ "default": 2.5,
127
+ "exclusiveMinimum": -1
128
+ },
129
+ "schemaHash": "sha256:bcafbb074da1b4c0217c2438646e132ab73398dc1570efd186017abdf21f5029"
130
+ },
131
+ {
132
+ "id": 6,
133
+ "name": "empty-object-schema",
134
+ "note": "An empty schema {} is a real, hashable schema. It is NOT the same fact as 'no schema' (vector 7).",
135
+ "inputSchema": {},
136
+ "schemaHash": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
137
+ },
138
+ {
139
+ "id": 7,
140
+ "name": "null-schema-has-no-hash",
141
+ "note": "No schema at all: schemaHash is null, never the hash of {} and never the hash of the string 'null'. FR-7 warns on exactly this row.",
142
+ "inputSchema": null,
143
+ "schemaHash": null,
144
+ "manifestDoc": {
145
+ "name": "unschemad_tool",
146
+ "description": "declared with a name only"
147
+ },
148
+ "manifestHash": "sha256:61f5054dde7e535542c2e04a739dc78d1341504f798c7642ab9ad29f1b456bee"
149
+ },
150
+ {
151
+ "id": 8,
152
+ "name": "array-order-is-significant",
153
+ "note": "Canonicalization sorts object keys and never sequences: reordering prefixItems is a different schema.",
154
+ "inputSchema": {
155
+ "type": "array",
156
+ "prefixItems": [
157
+ {
158
+ "type": "string"
159
+ },
160
+ {
161
+ "type": "number"
162
+ },
163
+ {
164
+ "type": "boolean"
165
+ }
166
+ ],
167
+ "items": {
168
+ "anyOf": [
169
+ {
170
+ "type": "null"
171
+ },
172
+ {
173
+ "type": "string"
174
+ }
175
+ ]
176
+ }
177
+ },
178
+ "schemaHash": "sha256:9dd8bbfb2bc524842d1203e4f914a5743cceaa228fcf328182f4bc9260fb747e"
179
+ },
180
+ {
181
+ "id": 9,
182
+ "name": "nested-required-arrays",
183
+ "note": "required lists nested inside properties survive verbatim, order included, at every depth.",
184
+ "inputSchema": {
185
+ "type": "object",
186
+ "required": [
187
+ "outer"
188
+ ],
189
+ "properties": {
190
+ "outer": {
191
+ "type": "object",
192
+ "required": [
193
+ "z",
194
+ "a"
195
+ ],
196
+ "properties": {
197
+ "z": {
198
+ "type": "string"
199
+ },
200
+ "a": {
201
+ "type": "object",
202
+ "required": [
203
+ "q"
204
+ ],
205
+ "properties": {
206
+ "q": {
207
+ "type": "integer"
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ },
215
+ "schemaHash": "sha256:864f94090821218ef480510c415eaac315715d2f8ee3be1cbc7517594b51ab13"
216
+ },
217
+ {
218
+ "id": 10,
219
+ "name": "booleans-nulls-and-escaped-strings",
220
+ "note": "true/false/null literals, and a string carrying a quote, a backslash, a tab, a newline and a control character.",
221
+ "inputSchema": {
222
+ "type": "object",
223
+ "additionalProperties": false,
224
+ "deprecated": true,
225
+ "properties": {
226
+ "q": {
227
+ "type": "string",
228
+ "default": "he said \"hi\"\tone\\two\nthree\u0001",
229
+ "const": null
230
+ }
231
+ }
232
+ },
233
+ "schemaHash": "sha256:f5cdf2e3025ce09cb931b6cc918484a14de97a057e9667874593f0a3bc50877c"
234
+ },
235
+ {
236
+ "id": 11,
237
+ "name": "argument-named-description-is-kept",
238
+ "note": "`description` and `title` are stripped only as schema annotation keywords, never as argument names under `properties`, `required`, `patternProperties`, `$defs`, `definitions` or `dependentSchemas`. create_ticket(title, description, priority) must NOT hash like create_ticket(priority). The annotation on `priority` is stripped; the two argument names are kept. `equivalentSpellings` differs only in annotation prose and must hash identically; `distinctSpelling` drops the two arguments and must NOT.",
239
+ "inputSchema": {
240
+ "type": "object",
241
+ "properties": {
242
+ "title": {
243
+ "type": "string",
244
+ "title": "Title",
245
+ "description": "Short summary"
246
+ },
247
+ "description": {
248
+ "type": "string",
249
+ "description": "Long form body"
250
+ },
251
+ "priority": {
252
+ "type": "integer",
253
+ "description": "P0-P3"
254
+ }
255
+ },
256
+ "required": [
257
+ "title",
258
+ "description"
259
+ ]
260
+ },
261
+ "schemaHash": "sha256:996c1f968a21b24a3f171a432a3de33257901beb2d172e3dfa3d345b7e3e6a3c",
262
+ "equivalentSpellings": [
263
+ {
264
+ "type": "object",
265
+ "properties": {
266
+ "title": {
267
+ "type": "string"
268
+ },
269
+ "description": {
270
+ "type": "string",
271
+ "title": "Body"
272
+ },
273
+ "priority": {
274
+ "type": "integer"
275
+ }
276
+ },
277
+ "required": [
278
+ "title",
279
+ "description"
280
+ ]
281
+ }
282
+ ],
283
+ "distinctSpelling": {
284
+ "type": "object",
285
+ "properties": {
286
+ "priority": {
287
+ "type": "integer"
288
+ }
289
+ }
290
+ }
291
+ },
292
+ {
293
+ "id": 12,
294
+ "name": "real-mcp-input-schema",
295
+ "note": "A verbatim MCP tools/list inputSchema (GitHub MCP create_issue), prose included, with the manifestHash of the full tool entry.",
296
+ "inputSchema": {
297
+ "type": "object",
298
+ "properties": {
299
+ "owner": {
300
+ "type": "string",
301
+ "description": "Repository owner"
302
+ },
303
+ "repo": {
304
+ "type": "string",
305
+ "description": "Repository name"
306
+ },
307
+ "title": {
308
+ "type": "string",
309
+ "description": "Issue title"
310
+ },
311
+ "body": {
312
+ "type": "string",
313
+ "description": "Issue body content"
314
+ },
315
+ "assignees": {
316
+ "type": "array",
317
+ "items": {
318
+ "type": "string"
319
+ },
320
+ "description": "Usernames to assign"
321
+ },
322
+ "labels": {
323
+ "type": "array",
324
+ "items": {
325
+ "type": "string"
326
+ },
327
+ "description": "Labels to apply"
328
+ },
329
+ "milestone": {
330
+ "type": "number",
331
+ "description": "Milestone number"
332
+ }
333
+ },
334
+ "required": [
335
+ "owner",
336
+ "repo",
337
+ "title"
338
+ ],
339
+ "additionalProperties": false,
340
+ "$schema": "http://json-schema.org/draft-07/schema#"
341
+ },
342
+ "schemaHash": "sha256:b06130f66f945f4ca2bc4474340c7f934c5e7b10168978fb8f507ecc146c091b",
343
+ "manifestDoc": {
344
+ "name": "create_issue",
345
+ "description": "Create a new issue in a GitHub repository",
346
+ "annotations": {
347
+ "readOnlyHint": false,
348
+ "destructiveHint": false,
349
+ "idempotentHint": false
350
+ },
351
+ "inputSchema": {
352
+ "type": "object",
353
+ "properties": {
354
+ "owner": {
355
+ "type": "string",
356
+ "description": "Repository owner"
357
+ },
358
+ "repo": {
359
+ "type": "string",
360
+ "description": "Repository name"
361
+ },
362
+ "title": {
363
+ "type": "string",
364
+ "description": "Issue title"
365
+ },
366
+ "body": {
367
+ "type": "string",
368
+ "description": "Issue body content"
369
+ },
370
+ "assignees": {
371
+ "type": "array",
372
+ "items": {
373
+ "type": "string"
374
+ },
375
+ "description": "Usernames to assign"
376
+ },
377
+ "labels": {
378
+ "type": "array",
379
+ "items": {
380
+ "type": "string"
381
+ },
382
+ "description": "Labels to apply"
383
+ },
384
+ "milestone": {
385
+ "type": "number",
386
+ "description": "Milestone number"
387
+ }
388
+ },
389
+ "required": [
390
+ "owner",
391
+ "repo",
392
+ "title"
393
+ ],
394
+ "additionalProperties": false,
395
+ "$schema": "http://json-schema.org/draft-07/schema#"
396
+ }
397
+ },
398
+ "manifestHash": "sha256:a0bc53dbf453b8c5860924781ddc912d1b118a64adb3ee4b5089bf599b936113"
399
+ },
400
+ {
401
+ "id": 13,
402
+ "name": "data-literals-are-not-schemas",
403
+ "note": "The values of `enum`, `const`, `default` and `examples` are data, not schema nodes: a `title` or `description` key inside them is part of the value and is kept verbatim. `equivalentSpellings` reorders keys inside the literals only; `distinctSpelling` removes those keys from the literals and must NOT hash equal.",
404
+ "inputSchema": {
405
+ "type": "object",
406
+ "properties": {
407
+ "payload": {
408
+ "type": "object",
409
+ "default": {
410
+ "title": "Untitled",
411
+ "description": "",
412
+ "priority": 2
413
+ },
414
+ "examples": [
415
+ {
416
+ "title": "First",
417
+ "description": "Body"
418
+ }
419
+ ]
420
+ },
421
+ "kind": {
422
+ "type": "object",
423
+ "enum": [
424
+ {
425
+ "title": "bug"
426
+ },
427
+ {
428
+ "title": "task"
429
+ }
430
+ ],
431
+ "const": {
432
+ "description": "fixed"
433
+ }
434
+ }
435
+ }
436
+ },
437
+ "schemaHash": "sha256:cae41d7dfcc5d51cf9ce1756903979b1fc5754fa8e95a69d9e5bec5df0266dc8",
438
+ "equivalentSpellings": [
439
+ {
440
+ "properties": {
441
+ "kind": {
442
+ "const": {
443
+ "description": "fixed"
444
+ },
445
+ "enum": [
446
+ {
447
+ "title": "bug"
448
+ },
449
+ {
450
+ "title": "task"
451
+ }
452
+ ],
453
+ "type": "object"
454
+ },
455
+ "payload": {
456
+ "examples": [
457
+ {
458
+ "description": "Body",
459
+ "title": "First"
460
+ }
461
+ ],
462
+ "default": {
463
+ "priority": 2,
464
+ "description": "",
465
+ "title": "Untitled"
466
+ },
467
+ "type": "object"
468
+ }
469
+ },
470
+ "type": "object"
471
+ }
472
+ ],
473
+ "distinctSpelling": {
474
+ "type": "object",
475
+ "properties": {
476
+ "payload": {
477
+ "type": "object",
478
+ "default": {
479
+ "priority": 2
480
+ },
481
+ "examples": [
482
+ {}
483
+ ]
484
+ },
485
+ "kind": {
486
+ "type": "object",
487
+ "enum": [
488
+ {},
489
+ {}
490
+ ],
491
+ "const": {}
492
+ }
493
+ }
494
+ }
495
+ }
496
+ ]
497
+ }