iterate-kernel 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -90,6 +90,21 @@ as `unplanned` — a reporter that quietly dropped it would be the failure this
90
90
  consumer depends on, so a change to either is a minor-version change at minimum, and the
91
91
  fixtures in `fixtures/` are the executable statement of what the contract means.
92
92
 
93
+ ## The fixtures are the portable half of the contract
94
+
95
+ `schemas/` and `fixtures/` ship in the tarball — `test/packaging.test.mjs` packs locally and
96
+ refuses a corpus that did not make it into the artifact. Each fixture states its own rules in
97
+ its `comment`, written so a second implementation can be coded from the file without reading the
98
+ TypeScript. That is the only way this contract reaches the consumers that cannot import it:
99
+ `iterate-harness` is Python and `glasspaned` is Swift.
100
+
101
+ Those consumers do not read this package at runtime. They vendor a copy of the corpus pinned by
102
+ sha256 — `iterate-harness/tests/kernel_fixtures/`, checked by its `scripts/check_kernel_fixtures.py`
103
+ (`--source kernel/fixtures` inside the monorepo, registry mode in the split repo). Moving a fixture
104
+ therefore means re-recording that pin in the same change, and the check fails in whichever
105
+ direction the bytes disagree. A cross-implementation comparison that can be skipped silently is
106
+ not a contract; it is a note nobody reads.
107
+
93
108
  ## Consumers
94
109
 
95
110
  Vendored or installed, a consumer's kernel is one of two things, and the difference is a
@@ -0,0 +1,13 @@
1
+ {
2
+ "comment": "Cross-implementation anchor for the decision log chain (kernel/src/decision-log.ts). A line's bytes ARE canonicalJson(entry) — keys sorted by UTF-16 code unit, no insignificant whitespace — so prevEntryHash of line i+1 equals sha256_hex of line i, and genesis carries an empty prevEntryHash. Any language that can sort keys and sha256 can verify this file; the kernel test recomputes the hashes with an external tool (shasum/openssl), so a TypeScript-only chain cannot pass silently.",
3
+ "lines": [
4
+ "{\"createdAt\":\"2026-09-25T04:00:00.000Z\",\"entryId\":\"dl_01K2ABCDEFGHJKMNPQRSTVWXZ0\",\"outcome\":\"pass\",\"prevEntryHash\":\"\",\"sequence\":0,\"summary\":\"attach Finder; window matched the attached pid\"}",
5
+ "{\"createdAt\":\"2026-09-25T04:00:01.000Z\",\"entryId\":\"dl_01K2ABCDEFGHJKMNPQRSTVWXZ1\",\"operationId\":\"op_01K2ABCDEFGHJKMNPQRSTVWXZ9\",\"outcome\":\"fail\",\"prevEntryHash\":\"f7c3b4198c27ad0e5947efd2d50dedced3e02f0171411fbf6c67f07e22d13d4d\",\"sequence\":1,\"summary\":\"act set-value refused: element not focusable\"}",
6
+ "{\"createdAt\":\"2026-09-25T04:00:02.000Z\",\"entryId\":\"dl_01K2ABCDEFGHJKMNPQRSTVWXZ2\",\"outcome\":\"inconclusive\",\"prevEntryHash\":\"db250a8182952a7ceb4240bcfcc48f639d452514e6ee9e8401111a57127f69c3\",\"sequence\":2,\"summary\":\"observe timed out while the app was modal\"}"
7
+ ],
8
+ "hashes": [
9
+ "f7c3b4198c27ad0e5947efd2d50dedced3e02f0171411fbf6c67f07e22d13d4d",
10
+ "db250a8182952a7ceb4240bcfcc48f639d452514e6ee9e8401111a57127f69c3",
11
+ "7b89c488c39f680343eec27cee805092140a43ef50e15f25a81133c1f154076b"
12
+ ]
13
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "entryId": "dl_0123456789ABCDEFGHJKMNPQRS",
3
+ "sequence": 0,
4
+ "prevEntryHash": "",
5
+ "operationId": "op_0123456789ABCDEFGHJKMNPQRS",
6
+ "summary": "act press on button 'Submit' (op_0123456789ABCDEFGHJKMNPQRS): actConfirmed=true, axChanged=true, assertion enabled=true passed",
7
+ "outcome": "pass",
8
+ "createdAt": "2026-09-14T12:34:56.789Z"
9
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "comment": "Cross-implementation anchor for dimensionContext (kernel/src/dimension-context.ts). The rules a second implementation must reproduce, written so it can be coded from this file without reading the TypeScript: (1) planned entries keep the caller's order; status is `verified` iff recorded[id].decisions >= 1, else `unverified`, and an absent id is the same as a recorded zero — `{decisions: 0}`. (2) A recorded id absent from the plan becomes one `unplanned` entry, sorted by id ascending in UTF-16 code unit order. (3) totals.decisions sums planned and unplanned alike, each decision counted once; verified + unverified === planned always. (4) A duplicate planned id throws KERNEL_E_DIMENSION_DUPLICATE rather than collapsing. The ids here are the nine the iterate config owns (config/config.schema.json $defs.dimension.enum); the kernel validates their *shape* and never enumerates them, which is why this fixture may name them without the kernel knowing they exist.",
3
+ "input": {
4
+ "planned": [
5
+ { "id": "correctness", "label": "正确性", "focus": "Crash risks, logic errors, concurrency." },
6
+ { "id": "security" },
7
+ { "id": "performance" },
8
+ { "id": "architecture" },
9
+ { "id": "style-tests" },
10
+ { "id": "tech-debt" },
11
+ { "id": "spec-compliance" },
12
+ { "id": "frontend-backend" },
13
+ { "id": "ui-ux", "label": "UI/UX" }
14
+ ],
15
+ "recorded": {
16
+ "correctness": { "decisions": 6, "operationIds": ["op_01K2ABCDEFGHJKMNPQRSTVWXZ9"] },
17
+ "security": { "decisions": 3 },
18
+ "performance": { "decisions": 0 },
19
+ "architecture": { "decisions": 2 },
20
+ "style-tests": { "decisions": 1 },
21
+ "tech-debt": { "decisions": 1 },
22
+ "spec-compliance": { "decisions": 0 },
23
+ "frontend-backend": { "decisions": 4 },
24
+ "ui-ux": { "decisions": 1 },
25
+ "concurrency": { "decisions": 2 }
26
+ }
27
+ },
28
+ "expected": {
29
+ "planned": [
30
+ {
31
+ "id": "correctness",
32
+ "status": "verified",
33
+ "label": "正确性",
34
+ "focus": "Crash risks, logic errors, concurrency.",
35
+ "evidence": { "decisions": 6, "operationIds": ["op_01K2ABCDEFGHJKMNPQRSTVWXZ9"] }
36
+ },
37
+ { "id": "security", "status": "verified", "evidence": { "decisions": 3 } },
38
+ { "id": "performance", "status": "unverified", "evidence": { "decisions": 0 } },
39
+ { "id": "architecture", "status": "verified", "evidence": { "decisions": 2 } },
40
+ { "id": "style-tests", "status": "verified", "evidence": { "decisions": 1 } },
41
+ { "id": "tech-debt", "status": "verified", "evidence": { "decisions": 1 } },
42
+ { "id": "spec-compliance", "status": "unverified", "evidence": { "decisions": 0 } },
43
+ { "id": "frontend-backend", "status": "verified", "evidence": { "decisions": 4 } },
44
+ { "id": "ui-ux", "status": "verified", "label": "UI/UX", "evidence": { "decisions": 1 } }
45
+ ],
46
+ "unplanned": [{ "id": "concurrency", "status": "unplanned", "evidence": { "decisions": 2 } }],
47
+ "totals": { "planned": 9, "verified": 7, "unverified": 2, "unplanned": 1, "decisions": 20 }
48
+ },
49
+ "expectedLine": "7/9 dimensions verified, 2 unverified (performance, spec-compliance), 1 unplanned (concurrency), 20 decisions"
50
+ }
@@ -0,0 +1,541 @@
1
+ {
2
+ "comment": "Cross-implementation anchor for decisionOutcomeFromEvidence and decisionSummaryFromEvidence (kernel/src/evidence-decision.ts). The rules a second implementation must reproduce, written so it can be coded from this file without reading the TypeScript: (1) circuitBreaker.level >= 3 is `blocked`, checked FIRST — the loop was stopped by harness policy and calling that a `fail` would blame the app. (2) Otherwise an assertion present (key present and not null) decides `pass` when its `passed` is true, `fail` when false. (3) Otherwise a diagnosis present decides `NO_ANOMALY` -> pass, `INCONCLUSIVE` -> inconclusive, any T-class -> fail. (4) Otherwise `inconclusive`: nothing was asserted and nothing diagnosed is not a pass. (5) A pass is then downgraded — never upgraded — to `inconclusive` when attribution.contaminated is true or attribution.level is `weak`, because the engine itself refuses to attribute that result to this operation. Absent vs explicit-null for assertion/diagnosis are two shapes the engine really emits and must be treated the same way. The summary is a rendering of the same fields in this order, joined by '; ': 'assertion <property> passed|failed: expected <JSON>, actual <JSON>' when an assertion is present; 'diagnosis <class>: <report.anomaly>' when a diagnosis is present; 'circuitBreaker level <n> (<reason>)' when level > 0 (the parenthetical only when a reason is present); 'attribution <level>' plus ', contaminated' when contaminated. JSON values are rendered as JavaScript's JSON.stringify would (no insignificant whitespace, key order as the pack carries them). Longer than 2048 characters, keep the first 2045 and append '...'. Provenance: four cases are real packs read out of ~/.glasspane/evidence on 2026-10-08 (operationId recorded per case); four are derived by editing exactly one field of a recorded pack, stated in each case's `origin`, because the archived corpus never contains a failed assertion, a weak-or-contaminated pass, or a breaker at the policy limit — those rules can only be pinned by derivation, and a fixture that silently invented them would be unsourced. The `input` bytes are the archived files exactly as the engine wrote them, including a `schemaVersion` of `glasspane.evidence/0.1-draft` and a `pixelDiff` with no `bounds`. A consumer that reads evidence off disk therefore parses them through the read-side contract (`parseEvidencePackRead`), which is what folds the legacy version and tolerates the missing signal — the same path the GlassPane Harness ledger uses. The transcription itself reads only `attribution`, `assertion`, `diagnosis` and `circuitBreaker`, which are identical under both contracts; nothing here depends on version folding.",
3
+ "cases": [
4
+ {
5
+ "name": "no-assertion-no-diagnosis-soft-breaker0",
6
+ "origin": "real",
7
+ "sourceOperationId": "op_01M2QS5A2AMWPNKCMTH0KFARC2",
8
+ "input": {
9
+ "assertion": null,
10
+ "attribution": {
11
+ "contaminated": false,
12
+ "level": "soft"
13
+ },
14
+ "circuitBreaker": {
15
+ "level": 0
16
+ },
17
+ "createdAt": "2026-09-17T13:33:39.275Z",
18
+ "diagnosis": null,
19
+ "operationId": "op_01M2QS5A2AMWPNKCMTH0KFARC2",
20
+ "schemaVersion": "glasspane.evidence/0.1-draft",
21
+ "signals": {
22
+ "act": {
23
+ "actConfirmed": true,
24
+ "action": "press",
25
+ "selector": {
26
+ "role": "AXButton",
27
+ "title": "Submit"
28
+ }
29
+ },
30
+ "axEvent": {
31
+ "axChanged": false,
32
+ "latencyMs": 0.0050067901611328125,
33
+ "nodeCount": 4,
34
+ "treeDigestAfter": "f84988c2d9a2edf3972aa9a247279fce",
35
+ "treeDigestBefore": "f84988c2d9a2edf3972aa9a247279fce"
36
+ },
37
+ "crash": {
38
+ "processAliveAfter": true,
39
+ "processAliveBefore": true
40
+ },
41
+ "handlerProbe": null,
42
+ "pixelDiff": {
43
+ "changedPixelRatio": 0,
44
+ "windowId": 12
45
+ },
46
+ "responsiveness": {
47
+ "pingMs": 3,
48
+ "responsive": true
49
+ },
50
+ "stateDiff": null
51
+ }
52
+ },
53
+ "expectedOutcome": "inconclusive",
54
+ "expectedSummary": "attribution soft"
55
+ },
56
+ {
57
+ "name": "diagnosis-T5-strong-breaker1",
58
+ "origin": "real",
59
+ "sourceOperationId": "op_01M2WNQN9TTG0MCR0ZRNZ5V5G1",
60
+ "input": {
61
+ "assertion": null,
62
+ "attribution": {
63
+ "contaminated": false,
64
+ "level": "strong"
65
+ },
66
+ "circuitBreaker": {
67
+ "level": 1,
68
+ "reason": "screen-recording-denied"
69
+ },
70
+ "createdAt": "2026-09-19T11:09:58.741Z",
71
+ "diagnosis": {
72
+ "class": "T5",
73
+ "report": {
74
+ "anomaly": "SwiftUI dependency loss: handler hit and state changed (source=z3-kvc, changed=true, keys=[demo.hidden]) but AX tree and pixels stayed silent",
75
+ "evidence": "op_01M2WNQN9TTG0MCR0ZRNZ5V5G1 strong attribution; actConfirmed=true; axChanged=false (digest 37521cc12c2829f47cca0287517a6d9c -> 37521cc12c2829f47cca0287517a6d9c, 171 nodes, 281.99493885040283ms); pixelDiff=unavailable; responsive=true pingMs=0.028967857360839844; alive true -> true; handlerProbe hitCount=1 late=0 [probe_demo/ProbeDemoApp.swift:68]; source=z3-kvc, changed=true, keys=[demo.hidden]; circuitBreaker=1",
76
+ "next": "check the view's observation of the changed key (Z1b-style direct @State writes and missing @Observable registration are the usual roots); re-bind or route through the observed model",
77
+ "path": "act.press -> probe-window -> handler/state -> ax-digest -> pixel-diff"
78
+ }
79
+ },
80
+ "operationId": "op_01M2WNQN9TTG0MCR0ZRNZ5V5G1",
81
+ "schemaVersion": "glasspane.evidence/0.1-draft",
82
+ "signals": {
83
+ "act": {
84
+ "actConfirmed": true,
85
+ "action": "press",
86
+ "selector": {
87
+ "identifier": "hidden-write",
88
+ "role": "AXButton"
89
+ }
90
+ },
91
+ "axEvent": {
92
+ "axChanged": false,
93
+ "latencyMs": 281.99493885040283,
94
+ "nodeCount": 171,
95
+ "treeDigestAfter": "37521cc12c2829f47cca0287517a6d9c",
96
+ "treeDigestBefore": "37521cc12c2829f47cca0287517a6d9c"
97
+ },
98
+ "crash": {
99
+ "processAliveAfter": true,
100
+ "processAliveBefore": true
101
+ },
102
+ "handlerProbe": {
103
+ "handlers": [
104
+ {
105
+ "file": "probe_demo/ProbeDemoApp.swift",
106
+ "line": 68
107
+ }
108
+ ],
109
+ "hitCount": 1,
110
+ "lateCount": 0,
111
+ "probeVersion": "gp-probe/0.1.0"
112
+ },
113
+ "responsiveness": {
114
+ "pingMs": 0.028967857360839844,
115
+ "responsive": true
116
+ },
117
+ "stateDiff": {
118
+ "changed": true,
119
+ "entries": [
120
+ {
121
+ "after": "1",
122
+ "before": "0",
123
+ "key": "demo.hidden"
124
+ }
125
+ ],
126
+ "source": "z3-kvc"
127
+ }
128
+ }
129
+ },
130
+ "expectedOutcome": "fail",
131
+ "expectedSummary": "diagnosis T5: SwiftUI dependency loss: handler hit and state changed (source=z3-kvc, changed=true, keys=[demo.hidden]) but AX tree and pixels stayed silent; circuitBreaker level 1 (screen-recording-denied); attribution strong"
132
+ },
133
+ {
134
+ "name": "diagnosis-INCONCLUSIVE-strong-breaker1",
135
+ "origin": "real",
136
+ "sourceOperationId": "op_01M2WNQMK2NEEZDNMK58NP2JYQ",
137
+ "input": {
138
+ "assertion": null,
139
+ "attribution": {
140
+ "contaminated": false,
141
+ "level": "strong"
142
+ },
143
+ "circuitBreaker": {
144
+ "level": 1,
145
+ "reason": "screen-recording-denied"
146
+ },
147
+ "createdAt": "2026-09-19T11:09:58.103Z",
148
+ "diagnosis": {
149
+ "class": "INCONCLUSIVE",
150
+ "report": {
151
+ "anomaly": "AX tree changed but the pixel signal is unavailable (circuitBreaker level 1); T6 is undecidable without screen capture",
152
+ "evidence": "op_01M2WNQMK2NEEZDNMK58NP2JYQ strong attribution; actConfirmed=true; axChanged=true (digest c624dee7d3644a4b64f8f8b6739917de -> 37521cc12c2829f47cca0287517a6d9c, 171 nodes, 372.1029758453369ms); pixelDiff=unavailable; responsive=true pingMs=0.054955482482910156; alive true -> true; handlerProbe hitCount=1 late=0 [probe_demo/ProbeDemoApp.swift:60]; source=z3-kvc, changed=true, keys=[count-domain.count, demo.count]; circuitBreaker=1",
153
+ "next": "grant screen recording permission to the daemon and replay the act for a decidable T6/NO_ANOMALY verdict",
154
+ "path": "act.press -> probe-window -> handler/state -> ax-digest -> pixel-diff"
155
+ }
156
+ },
157
+ "operationId": "op_01M2WNQMK2NEEZDNMK58NP2JYQ",
158
+ "schemaVersion": "glasspane.evidence/0.1-draft",
159
+ "signals": {
160
+ "act": {
161
+ "actConfirmed": true,
162
+ "action": "press",
163
+ "selector": {
164
+ "identifier": "ok-press",
165
+ "role": "AXButton"
166
+ }
167
+ },
168
+ "axEvent": {
169
+ "axChanged": true,
170
+ "latencyMs": 372.1029758453369,
171
+ "nodeCount": 171,
172
+ "treeDigestAfter": "37521cc12c2829f47cca0287517a6d9c",
173
+ "treeDigestBefore": "c624dee7d3644a4b64f8f8b6739917de"
174
+ },
175
+ "crash": {
176
+ "processAliveAfter": true,
177
+ "processAliveBefore": true
178
+ },
179
+ "handlerProbe": {
180
+ "handlers": [
181
+ {
182
+ "file": "probe_demo/ProbeDemoApp.swift",
183
+ "line": 60
184
+ }
185
+ ],
186
+ "hitCount": 1,
187
+ "lateCount": 0,
188
+ "probeVersion": "gp-probe/0.1.0"
189
+ },
190
+ "responsiveness": {
191
+ "pingMs": 0.054955482482910156,
192
+ "responsive": true
193
+ },
194
+ "stateDiff": {
195
+ "changed": true,
196
+ "entries": [
197
+ {
198
+ "after": "1",
199
+ "before": "0",
200
+ "key": "count-domain.count"
201
+ },
202
+ {
203
+ "after": "1",
204
+ "before": "0",
205
+ "key": "demo.count"
206
+ }
207
+ ],
208
+ "source": "z3-kvc"
209
+ }
210
+ }
211
+ },
212
+ "expectedOutcome": "inconclusive",
213
+ "expectedSummary": "diagnosis INCONCLUSIVE: AX tree changed but the pixel signal is unavailable (circuitBreaker level 1); T6 is undecidable without screen capture; circuitBreaker level 1 (screen-recording-denied); attribution strong"
214
+ },
215
+ {
216
+ "name": "assertion-pass-with-diagnosis-T3-soft",
217
+ "origin": "real",
218
+ "sourceOperationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
219
+ "input": {
220
+ "assertion": {
221
+ "actual": true,
222
+ "expected": true,
223
+ "kind": "element_property",
224
+ "passed": true,
225
+ "property": "enabled",
226
+ "selector": {
227
+ "role": "AXButton"
228
+ }
229
+ },
230
+ "attribution": {
231
+ "contaminated": false,
232
+ "level": "soft"
233
+ },
234
+ "circuitBreaker": {
235
+ "level": 1,
236
+ "reason": "screen-recording-denied"
237
+ },
238
+ "createdAt": "2026-09-18T08:39:37.667Z",
239
+ "diagnosis": {
240
+ "class": "T3",
241
+ "report": {
242
+ "anomaly": "operation confirmed but neither the AX tree nor pixels changed; binding lost",
243
+ "evidence": "op_01M2STQMY23REZG9CPD6Z3CYGT soft attribution; actConfirmed=true; axChanged=false (digest bd76f2aba5c08ea202103eeca782292b -> bd76f2aba5c08ea202103eeca782292b, 820 nodes, 811.6888999938965ms); pixelDiff=unavailable; responsive=true pingMs=0.1289844512939453; alive true -> true; circuitBreaker=1",
244
+ "next": "verify the selector matches an enabled control; observe the tree; check the action binding and isEnabled state",
245
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff"
246
+ }
247
+ },
248
+ "operationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
249
+ "schemaVersion": "glasspane.evidence/0.1-draft",
250
+ "signals": {
251
+ "act": {
252
+ "actConfirmed": true,
253
+ "action": "press",
254
+ "selector": {
255
+ "role": "AXButton"
256
+ }
257
+ },
258
+ "axEvent": {
259
+ "axChanged": false,
260
+ "latencyMs": 811.6888999938965,
261
+ "nodeCount": 820,
262
+ "treeDigestAfter": "bd76f2aba5c08ea202103eeca782292b",
263
+ "treeDigestBefore": "bd76f2aba5c08ea202103eeca782292b"
264
+ },
265
+ "crash": {
266
+ "processAliveAfter": true,
267
+ "processAliveBefore": true
268
+ },
269
+ "handlerProbe": null,
270
+ "responsiveness": {
271
+ "pingMs": 0.1289844512939453,
272
+ "responsive": true
273
+ },
274
+ "stateDiff": null
275
+ }
276
+ },
277
+ "expectedOutcome": "pass",
278
+ "expectedSummary": "assertion enabled passed: expected true, actual true; diagnosis T3: operation confirmed but neither the AX tree nor pixels changed; binding lost; circuitBreaker level 1 (screen-recording-denied); attribution soft"
279
+ },
280
+ {
281
+ "name": "assertion-pass-but-weak-attribution",
282
+ "origin": "derived: attribution.level strong->weak",
283
+ "sourceOperationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
284
+ "input": {
285
+ "assertion": {
286
+ "actual": true,
287
+ "expected": true,
288
+ "kind": "element_property",
289
+ "passed": true,
290
+ "property": "enabled",
291
+ "selector": {
292
+ "role": "AXButton"
293
+ }
294
+ },
295
+ "attribution": {
296
+ "contaminated": false,
297
+ "level": "weak"
298
+ },
299
+ "circuitBreaker": {
300
+ "level": 1,
301
+ "reason": "screen-recording-denied"
302
+ },
303
+ "createdAt": "2026-09-18T08:39:37.667Z",
304
+ "diagnosis": {
305
+ "class": "T3",
306
+ "report": {
307
+ "anomaly": "operation confirmed but neither the AX tree nor pixels changed; binding lost",
308
+ "evidence": "op_01M2STQMY23REZG9CPD6Z3CYGT soft attribution; actConfirmed=true; axChanged=false (digest bd76f2aba5c08ea202103eeca782292b -> bd76f2aba5c08ea202103eeca782292b, 820 nodes, 811.6888999938965ms); pixelDiff=unavailable; responsive=true pingMs=0.1289844512939453; alive true -> true; circuitBreaker=1",
309
+ "next": "verify the selector matches an enabled control; observe the tree; check the action binding and isEnabled state",
310
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff"
311
+ }
312
+ },
313
+ "operationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
314
+ "schemaVersion": "glasspane.evidence/0.1-draft",
315
+ "signals": {
316
+ "act": {
317
+ "actConfirmed": true,
318
+ "action": "press",
319
+ "selector": {
320
+ "role": "AXButton"
321
+ }
322
+ },
323
+ "axEvent": {
324
+ "axChanged": false,
325
+ "latencyMs": 811.6888999938965,
326
+ "nodeCount": 820,
327
+ "treeDigestAfter": "bd76f2aba5c08ea202103eeca782292b",
328
+ "treeDigestBefore": "bd76f2aba5c08ea202103eeca782292b"
329
+ },
330
+ "crash": {
331
+ "processAliveAfter": true,
332
+ "processAliveBefore": true
333
+ },
334
+ "handlerProbe": null,
335
+ "responsiveness": {
336
+ "pingMs": 0.1289844512939453,
337
+ "responsive": true
338
+ },
339
+ "stateDiff": null
340
+ }
341
+ },
342
+ "expectedOutcome": "inconclusive",
343
+ "expectedSummary": "assertion enabled passed: expected true, actual true; diagnosis T3: operation confirmed but neither the AX tree nor pixels changed; binding lost; circuitBreaker level 1 (screen-recording-denied); attribution weak"
344
+ },
345
+ {
346
+ "name": "assertion-pass-but-contaminated",
347
+ "origin": "derived: attribution.contaminated -> true",
348
+ "sourceOperationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
349
+ "input": {
350
+ "assertion": {
351
+ "actual": true,
352
+ "expected": true,
353
+ "kind": "element_property",
354
+ "passed": true,
355
+ "property": "enabled",
356
+ "selector": {
357
+ "role": "AXButton"
358
+ }
359
+ },
360
+ "attribution": {
361
+ "contaminated": true,
362
+ "level": "soft"
363
+ },
364
+ "circuitBreaker": {
365
+ "level": 1,
366
+ "reason": "screen-recording-denied"
367
+ },
368
+ "createdAt": "2026-09-18T08:39:37.667Z",
369
+ "diagnosis": {
370
+ "class": "T3",
371
+ "report": {
372
+ "anomaly": "operation confirmed but neither the AX tree nor pixels changed; binding lost",
373
+ "evidence": "op_01M2STQMY23REZG9CPD6Z3CYGT soft attribution; actConfirmed=true; axChanged=false (digest bd76f2aba5c08ea202103eeca782292b -> bd76f2aba5c08ea202103eeca782292b, 820 nodes, 811.6888999938965ms); pixelDiff=unavailable; responsive=true pingMs=0.1289844512939453; alive true -> true; circuitBreaker=1",
374
+ "next": "verify the selector matches an enabled control; observe the tree; check the action binding and isEnabled state",
375
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff"
376
+ }
377
+ },
378
+ "operationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
379
+ "schemaVersion": "glasspane.evidence/0.1-draft",
380
+ "signals": {
381
+ "act": {
382
+ "actConfirmed": true,
383
+ "action": "press",
384
+ "selector": {
385
+ "role": "AXButton"
386
+ }
387
+ },
388
+ "axEvent": {
389
+ "axChanged": false,
390
+ "latencyMs": 811.6888999938965,
391
+ "nodeCount": 820,
392
+ "treeDigestAfter": "bd76f2aba5c08ea202103eeca782292b",
393
+ "treeDigestBefore": "bd76f2aba5c08ea202103eeca782292b"
394
+ },
395
+ "crash": {
396
+ "processAliveAfter": true,
397
+ "processAliveBefore": true
398
+ },
399
+ "handlerProbe": null,
400
+ "responsiveness": {
401
+ "pingMs": 0.1289844512939453,
402
+ "responsive": true
403
+ },
404
+ "stateDiff": null
405
+ }
406
+ },
407
+ "expectedOutcome": "inconclusive",
408
+ "expectedSummary": "assertion enabled passed: expected true, actual true; diagnosis T3: operation confirmed but neither the AX tree nor pixels changed; binding lost; circuitBreaker level 1 (screen-recording-denied); attribution soft, contaminated"
409
+ },
410
+ {
411
+ "name": "assertion-failed",
412
+ "origin": "derived: assertion.passed -> false, assertion.actual -> false",
413
+ "sourceOperationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
414
+ "input": {
415
+ "assertion": {
416
+ "actual": false,
417
+ "expected": true,
418
+ "kind": "element_property",
419
+ "passed": false,
420
+ "property": "enabled",
421
+ "selector": {
422
+ "role": "AXButton"
423
+ }
424
+ },
425
+ "attribution": {
426
+ "contaminated": false,
427
+ "level": "soft"
428
+ },
429
+ "circuitBreaker": {
430
+ "level": 1,
431
+ "reason": "screen-recording-denied"
432
+ },
433
+ "createdAt": "2026-09-18T08:39:37.667Z",
434
+ "diagnosis": {
435
+ "class": "T3",
436
+ "report": {
437
+ "anomaly": "operation confirmed but neither the AX tree nor pixels changed; binding lost",
438
+ "evidence": "op_01M2STQMY23REZG9CPD6Z3CYGT soft attribution; actConfirmed=true; axChanged=false (digest bd76f2aba5c08ea202103eeca782292b -> bd76f2aba5c08ea202103eeca782292b, 820 nodes, 811.6888999938965ms); pixelDiff=unavailable; responsive=true pingMs=0.1289844512939453; alive true -> true; circuitBreaker=1",
439
+ "next": "verify the selector matches an enabled control; observe the tree; check the action binding and isEnabled state",
440
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff"
441
+ }
442
+ },
443
+ "operationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
444
+ "schemaVersion": "glasspane.evidence/0.1-draft",
445
+ "signals": {
446
+ "act": {
447
+ "actConfirmed": true,
448
+ "action": "press",
449
+ "selector": {
450
+ "role": "AXButton"
451
+ }
452
+ },
453
+ "axEvent": {
454
+ "axChanged": false,
455
+ "latencyMs": 811.6888999938965,
456
+ "nodeCount": 820,
457
+ "treeDigestAfter": "bd76f2aba5c08ea202103eeca782292b",
458
+ "treeDigestBefore": "bd76f2aba5c08ea202103eeca782292b"
459
+ },
460
+ "crash": {
461
+ "processAliveAfter": true,
462
+ "processAliveBefore": true
463
+ },
464
+ "handlerProbe": null,
465
+ "responsiveness": {
466
+ "pingMs": 0.1289844512939453,
467
+ "responsive": true
468
+ },
469
+ "stateDiff": null
470
+ }
471
+ },
472
+ "expectedOutcome": "fail",
473
+ "expectedSummary": "assertion enabled failed: expected true, actual false; diagnosis T3: operation confirmed but neither the AX tree nor pixels changed; binding lost; circuitBreaker level 1 (screen-recording-denied); attribution soft"
474
+ },
475
+ {
476
+ "name": "breaker-at-policy-limit",
477
+ "origin": "derived: circuitBreaker.level -> 3",
478
+ "sourceOperationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
479
+ "input": {
480
+ "assertion": {
481
+ "actual": true,
482
+ "expected": true,
483
+ "kind": "element_property",
484
+ "passed": true,
485
+ "property": "enabled",
486
+ "selector": {
487
+ "role": "AXButton"
488
+ }
489
+ },
490
+ "attribution": {
491
+ "contaminated": false,
492
+ "level": "soft"
493
+ },
494
+ "circuitBreaker": {
495
+ "level": 3,
496
+ "reason": "fixture: breaker raised to the policy limit"
497
+ },
498
+ "createdAt": "2026-09-18T08:39:37.667Z",
499
+ "diagnosis": {
500
+ "class": "T3",
501
+ "report": {
502
+ "anomaly": "operation confirmed but neither the AX tree nor pixels changed; binding lost",
503
+ "evidence": "op_01M2STQMY23REZG9CPD6Z3CYGT soft attribution; actConfirmed=true; axChanged=false (digest bd76f2aba5c08ea202103eeca782292b -> bd76f2aba5c08ea202103eeca782292b, 820 nodes, 811.6888999938965ms); pixelDiff=unavailable; responsive=true pingMs=0.1289844512939453; alive true -> true; circuitBreaker=1",
504
+ "next": "verify the selector matches an enabled control; observe the tree; check the action binding and isEnabled state",
505
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff"
506
+ }
507
+ },
508
+ "operationId": "op_01M2STQMY23REZG9CPD6Z3CYGT",
509
+ "schemaVersion": "glasspane.evidence/0.1-draft",
510
+ "signals": {
511
+ "act": {
512
+ "actConfirmed": true,
513
+ "action": "press",
514
+ "selector": {
515
+ "role": "AXButton"
516
+ }
517
+ },
518
+ "axEvent": {
519
+ "axChanged": false,
520
+ "latencyMs": 811.6888999938965,
521
+ "nodeCount": 820,
522
+ "treeDigestAfter": "bd76f2aba5c08ea202103eeca782292b",
523
+ "treeDigestBefore": "bd76f2aba5c08ea202103eeca782292b"
524
+ },
525
+ "crash": {
526
+ "processAliveAfter": true,
527
+ "processAliveBefore": true
528
+ },
529
+ "handlerProbe": null,
530
+ "responsiveness": {
531
+ "pingMs": 0.1289844512939453,
532
+ "responsive": true
533
+ },
534
+ "stateDiff": null
535
+ }
536
+ },
537
+ "expectedOutcome": "blocked",
538
+ "expectedSummary": "assertion enabled passed: expected true, actual true; diagnosis T3: operation confirmed but neither the AX tree nor pixels changed; binding lost; circuitBreaker level 3 (fixture: breaker raised to the policy limit); attribution soft"
539
+ }
540
+ ]
541
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "schemaVersion": "glasspane.evidence/0.1",
3
+ "operationId": "op_0123456789ABCDEFGHJKMNPQRS",
4
+ "createdAt": "2026-09-14T12:34:56.789Z",
5
+ "attribution": {
6
+ "level": "soft",
7
+ "contaminated": false
8
+ },
9
+ "circuitBreaker": {
10
+ "level": 0
11
+ },
12
+ "signals": {
13
+ "act": {
14
+ "selector": {
15
+ "role": "button",
16
+ "title": "Submit"
17
+ },
18
+ "action": "press",
19
+ "actConfirmed": true
20
+ },
21
+ "axEvent": {
22
+ "treeDigestBefore": "00112233445566778899aabbccddeeff",
23
+ "treeDigestAfter": "ffeeddccbbaa99887766554433221100",
24
+ "nodeCount": 128,
25
+ "axChanged": true,
26
+ "latencyMs": 42
27
+ },
28
+ "handlerProbe": null,
29
+ "stateDiff": null,
30
+ "pixelDiff": {
31
+ "changedPixelRatio": 0.023,
32
+ "bounds": {
33
+ "x": 100,
34
+ "y": 200,
35
+ "width": 80,
36
+ "height": 28
37
+ },
38
+ "windowId": 12
39
+ },
40
+ "responsiveness": {
41
+ "responsive": true,
42
+ "pingMs": 3
43
+ },
44
+ "crash": {
45
+ "processAliveBefore": true,
46
+ "processAliveAfter": true
47
+ }
48
+ },
49
+ "assertion": {
50
+ "kind": "element_property",
51
+ "selector": {
52
+ "role": "button",
53
+ "title": "Submit"
54
+ },
55
+ "property": "enabled",
56
+ "expected": true,
57
+ "actual": true,
58
+ "passed": true
59
+ },
60
+ "diagnosis": {
61
+ "class": "NO_ANOMALY",
62
+ "report": {
63
+ "path": "act.press -> ax-confirm -> tree-digest -> pixel-diff",
64
+ "anomaly": "none: operation confirmed, AX tree changed, pixels changed",
65
+ "evidence": "op_0123456789ABCDEFGHJKMNPQRS soft attribution; axChanged=true (digest 00112233445566778899aabbccddeeff -> ffeeddccbbaa99887766554433221100); changedPixelRatio=0.023; pingMs=3",
66
+ "next": "no action required; assertion passed"
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "schemaVersion": "glasspane.evidence/0.1",
3
+ "operationId": "op_112233445566778899AABBCCDD",
4
+ "createdAt": "2026-09-14T12:35:00.001Z",
5
+ "attribution": {
6
+ "level": "soft",
7
+ "contaminated": false
8
+ },
9
+ "circuitBreaker": {
10
+ "level": 1,
11
+ "reason": "screen-recording-denied"
12
+ },
13
+ "signals": {
14
+ "act": {
15
+ "selector": {
16
+ "role": "checkBox",
17
+ "identifier": "agree-checkbox"
18
+ },
19
+ "action": "confirm",
20
+ "actConfirmed": true
21
+ },
22
+ "axEvent": {
23
+ "treeDigestBefore": "00000000000000000000000000000001",
24
+ "treeDigestAfter": "00000000000000000000000000000002",
25
+ "nodeCount": 57,
26
+ "axChanged": true,
27
+ "latencyMs": 12.5
28
+ },
29
+ "handlerProbe": null,
30
+ "stateDiff": null
31
+ },
32
+ "assertion": null,
33
+ "diagnosis": null
34
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "schemaVersion": "glasspane.evidence/0.1",
3
+ "operationId": "op_0PAAAABBBBCCCCDDDDEEEEFFFF",
4
+ "createdAt": "2026-09-19T09:41:02.500Z",
5
+ "attribution": {
6
+ "level": "strong",
7
+ "contaminated": false
8
+ },
9
+ "circuitBreaker": {
10
+ "level": 0
11
+ },
12
+ "signals": {
13
+ "act": {
14
+ "selector": {
15
+ "role": "AXButton",
16
+ "title": "OK Press",
17
+ "identifier": "ok-press"
18
+ },
19
+ "action": "press",
20
+ "actConfirmed": true
21
+ },
22
+ "axEvent": {
23
+ "treeDigestBefore": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
24
+ "treeDigestAfter": "00112233445566778899aabbccddeeff",
25
+ "nodeCount": 24,
26
+ "axChanged": true,
27
+ "latencyMs": 21.4
28
+ },
29
+ "handlerProbe": {
30
+ "probeVersion": "gp-probe/0.1.0",
31
+ "hitCount": 3,
32
+ "handlers": [
33
+ { "file": "probe-demo/ProbeDemoApp.swift", "line": 64 },
34
+ { "file": "probe-demo/ProbeDemoApp.swift", "line": 65 }
35
+ ],
36
+ "lateCount": 0
37
+ },
38
+ "stateDiff": {
39
+ "source": "z3-kvc",
40
+ "changed": true,
41
+ "entries": [
42
+ { "key": "demo.count", "before": "0", "after": "1" }
43
+ ]
44
+ },
45
+ "pixelDiff": {
46
+ "changedPixelRatio": 0.014,
47
+ "bounds": { "x": 12, "y": 34, "width": 96, "height": 28 },
48
+ "windowId": 4210
49
+ },
50
+ "responsiveness": {
51
+ "responsive": true,
52
+ "pingMs": 2.1
53
+ },
54
+ "crash": {
55
+ "processAliveBefore": true,
56
+ "processAliveAfter": true
57
+ }
58
+ },
59
+ "assertion": null,
60
+ "diagnosis": {
61
+ "class": "NO_ANOMALY",
62
+ "report": {
63
+ "path": "act.press -> probe-window -> handler/state -> ax-digest -> pixel-diff",
64
+ "anomaly": "none: operation confirmed, AX tree changed and pixels changed",
65
+ "evidence": "op_0PAAAABBBBCCCCDDDDEEEEFFFF strong attribution; actConfirmed=true",
66
+ "next": "no action required; continue the recipe"
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "schemaVersion": "glasspane.evidence/0.1-draft",
3
+ "operationId": "op_04DRAFTPACK000000000000000",
4
+ "createdAt": "2026-09-17T13:33:39.275Z",
5
+ "attribution": {
6
+ "level": "soft",
7
+ "contaminated": false
8
+ },
9
+ "circuitBreaker": {
10
+ "level": 0
11
+ },
12
+ "signals": {
13
+ "act": {
14
+ "selector": {
15
+ "role": "AXButton",
16
+ "title": "Submit"
17
+ },
18
+ "action": "press",
19
+ "actConfirmed": true
20
+ },
21
+ "axEvent": {
22
+ "treeDigestBefore": "f84988c2d9a2edf3972aa9a247279fce",
23
+ "treeDigestAfter": "0b7d3f1a5c8e2946d1a70c5e8b342f61",
24
+ "nodeCount": 4,
25
+ "axChanged": true,
26
+ "latencyMs": 18.7
27
+ },
28
+ "handlerProbe": null,
29
+ "stateDiff": null,
30
+ "pixelDiff": {
31
+ "changedPixelRatio": 0.018,
32
+ "bounds": {
33
+ "x": 512,
34
+ "y": 344,
35
+ "width": 168,
36
+ "height": 32
37
+ },
38
+ "windowId": 12
39
+ },
40
+ "responsiveness": {
41
+ "responsive": true,
42
+ "pingMs": 3
43
+ },
44
+ "crash": {
45
+ "processAliveBefore": true,
46
+ "processAliveAfter": true
47
+ }
48
+ },
49
+ "assertion": null,
50
+ "diagnosis": {
51
+ "class": "NO_ANOMALY",
52
+ "report": {
53
+ "path": "act.press -> ax-digest -> pixel-diff",
54
+ "anomaly": "none: operation confirmed, AX tree changed, pixels changed",
55
+ "evidence": "op_04DRAFTPACK000000000000000 soft attribution; axChanged=true; changedPixelRatio=0.018; pingMs=3",
56
+ "next": "no action required; continue the recipe"
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "schemaVersion": "glasspane.evidence/0.1",
3
+ "operationId": "op_05AXTREEMAP000000000000000",
4
+ "createdAt": "2026-09-21T07:12:44.500Z",
5
+ "attribution": {
6
+ "level": "strong",
7
+ "contaminated": false
8
+ },
9
+ "circuitBreaker": {
10
+ "level": 0
11
+ },
12
+ "signals": {
13
+ "act": {
14
+ "selector": {
15
+ "role": "AXButton",
16
+ "title": "Toggle"
17
+ },
18
+ "action": "press",
19
+ "actConfirmed": true
20
+ },
21
+ "axEvent": {
22
+ "treeDigestBefore": "9f2c6a04d81b3e57c206af9d4b7e1358",
23
+ "treeDigestAfter": "9f2c6a04d81b3e57c206af9d4b7e1358",
24
+ "nodeCount": 6,
25
+ "axChanged": false,
26
+ "latencyMs": 2.4
27
+ },
28
+ "handlerProbe": null,
29
+ "stateDiff": null,
30
+ "pixelDiff": {
31
+ "changedPixelRatio": 0,
32
+ "windowId": 12
33
+ },
34
+ "responsiveness": {
35
+ "responsive": true,
36
+ "pingMs": 4
37
+ },
38
+ "crash": {
39
+ "processAliveBefore": true,
40
+ "processAliveAfter": true
41
+ }
42
+ },
43
+ "assertion": null,
44
+ "diagnosis": {
45
+ "class": "T2",
46
+ "report": {
47
+ "path": "act.press -> ax-digest -> pixel-diff",
48
+ "anomaly": "act confirmed but neither the AX tree nor the pixels changed",
49
+ "evidence": "op_05AXTREEMAP000000000000000 strong attribution; axChanged=false; changedPixelRatio=0",
50
+ "next": "verify the selector targets a live element; run observe before retrying"
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "schemaVersion": "glasspane.recipe/0.1-draft",
3
+ "name": "smoke-check-submit",
4
+ "steps": [
5
+ {
6
+ "kind": "act",
7
+ "params": {
8
+ "selector": {
9
+ "role": "button",
10
+ "title": "Submit"
11
+ },
12
+ "action": "press"
13
+ }
14
+ },
15
+ {
16
+ "kind": "observe",
17
+ "params": {
18
+ "maxDepth": 4
19
+ }
20
+ },
21
+ {
22
+ "kind": "assert",
23
+ "params": {
24
+ "selector": {
25
+ "role": "button",
26
+ "title": "Submit"
27
+ },
28
+ "property": "enabled",
29
+ "expected": true
30
+ }
31
+ },
32
+ {
33
+ "kind": "diagnose",
34
+ "params": {}
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,33 @@
1
+ <div class="gp-evidence" id="op_0PAAAABBBBCCCCDDDDEEEEFFFF">
2
+ <h1>op_0PAAAABBBBCCCCDDDDEEEEFFFF · NO_ANOMALY · normal</h1>
3
+ <dl class="gp-summary">
4
+ <dt>operationId</dt><dd>op_0PAAAABBBBCCCCDDDDEEEEFFFF</dd>
5
+ <dt>createdAt</dt><dd>2026-09-19T09:41:02.500Z</dd>
6
+ <dt>schemaVersion</dt><dd>glasspane.evidence/0.1</dd>
7
+ <dt class="gp-line">·</dt><dd>attribution: strong | contaminated=false</dd>
8
+ <dt class="gp-line">·</dt><dd>circuitBreaker: level 0 (normal)</dd>
9
+ <dt class="gp-line">·</dt><dd>act press AXButton &quot;OK Press&quot; #ok-press: confirmed</dd>
10
+ <dt class="gp-line">·</dt><dd>axEvent: changed=true nodes=24 latencyMs=1234.57</dd>
11
+ <dt class="gp-line">·</dt><dd>handlerProbe: probeVersion=gp-probe/0.1.0 hitCount=3 late=1 handlers=[probe-demo/ProbeDemoApp.swift:64, probe-demo/ProbeDemoApp.swift:65]</dd>
12
+ <dt class="gp-line">·</dt><dd>stateDiff: source=z3-kvc changed=true entries=[demo.count &quot;0&quot; -&gt; &quot;1&quot;, demo.label &quot;idle&quot; -&gt; &quot;pressed&quot;]</dd>
13
+ <dt class="gp-line">·</dt><dd>pixelDiff: changedRatio=0.123457 windowId=4210 bounds=12,34,96,28</dd>
14
+ <dt class="gp-line">·</dt><dd>responsiveness: responsive=true pingMs=2.1</dd>
15
+ <dt class="gp-line">·</dt><dd>crash: aliveBefore=true aliveAfter=true</dd>
16
+ </dl>
17
+ <section class="gp-section">
18
+ <h2>PATH</h2>
19
+ <p>act.press -&gt; probe-window -&gt; handler/state -&gt; ax-digest -&gt; pixel-diff</p>
20
+ </section>
21
+ <section class="gp-section">
22
+ <h2>ANOMALY</h2>
23
+ <p>none: operation confirmed, AX tree changed and pixels changed</p>
24
+ </section>
25
+ <section class="gp-section">
26
+ <h2>EVIDENCE</h2>
27
+ <p>op_0PAAAABBBBCCCCDDDDEEEEFFFF strong attribution; actConfirmed=true</p>
28
+ </section>
29
+ <section class="gp-section">
30
+ <h2>NEXT</h2>
31
+ <p>no action required; continue the recipe</p>
32
+ </section>
33
+ </div>
@@ -0,0 +1,30 @@
1
+ # op_0PAAAABBBBCCCCDDDDEEEEFFFF · NO_ANOMALY · normal
2
+
3
+ **operationId**: op_0PAAAABBBBCCCCDDDDEEEEFFFF
4
+ **createdAt**: 2026-09-19T09:41:02.500Z
5
+ **schemaVersion**: glasspane.evidence/0.1
6
+ * attribution: strong | contaminated=false
7
+ * circuitBreaker: level 0 (normal)
8
+ * act press AXButton "OK Press" #ok-press: confirmed
9
+ * axEvent: changed=true nodes=24 latencyMs=1234.57
10
+ * handlerProbe: probeVersion=gp-probe/0.1.0 hitCount=3 late=1 handlers=[probe-demo/ProbeDemoApp.swift:64, probe-demo/ProbeDemoApp.swift:65]
11
+ * stateDiff: source=z3-kvc changed=true entries=[demo.count "0" -> "1", demo.label "idle" -> "pressed"]
12
+ * pixelDiff: changedRatio=0.123457 windowId=4210 bounds=12,34,96,28
13
+ * responsiveness: responsive=true pingMs=2.1
14
+ * crash: aliveBefore=true aliveAfter=true
15
+
16
+ ## PATH
17
+
18
+ act.press -> probe-window -> handler/state -> ax-digest -> pixel-diff
19
+
20
+ ## ANOMALY
21
+
22
+ none: operation confirmed, AX tree changed and pixels changed
23
+
24
+ ## EVIDENCE
25
+
26
+ op_0PAAAABBBBCCCCDDDDEEEEFFFF strong attribution; actConfirmed=true
27
+
28
+ ## NEXT
29
+
30
+ no action required; continue the recipe
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iterate-kernel",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "iterate ecosystem shared kernel: schemas, the evidence->decision transcription, the decision-log audit chain and public validators. Verification reasoning stays in the engine; this layer transcribes.",
6
6
  "type": "module",
@@ -62,6 +62,7 @@
62
62
  "files": [
63
63
  "dist",
64
64
  "schemas",
65
+ "fixtures",
65
66
  "README.md"
66
67
  ],
67
68
  "scripts": {