opy-rs 0.1.4

Standalone OverPy-compatible .opy implementation: lexer, CST/parser, preprocessing, semantic resolution, and Opy HIR lowering (Workshop-independent).
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
{
  "schemaVersion": 1,
  "visibility": "internal-engineering-metadata",
  "artifact": "opy-rs OverPy feature inventory and support matrix",
  "reference": {
    "name": "overpy",
    "version": "9.7.10",
    "contentCommit": "889d9749d1def17f146548cbddb94ea1ab015847",
    "integrity": "sha512-oX17nauJcPTaKIrRFY/rD0Rl8atqFUVv9Hg2TKH+A68/fC8+ZO344Mkd1A/Y0oOVp1hr5tktMBjzMEDDnMEYUw=="
  },
  "snapshot": {
    "date": "2026-08-29",
    "note": "Readiness baseline through the bounded #37 compiler slice. Settings, catalog-declared locale emission, and post-compile hooks have explicit OPY -> HIR -> WIR -> validated Workshop emission evidence. Optimizer controls remain non-blocking presentation differences; semantic replacement directives remain explicit gaps and fail at the compiler boundary until canonical lowering exists. Canonical Workshop catalog data, settings tables, locale spellings, WIR, validation, and emission remain owned by workshop-rs.",
    "asOfCommit": "9f7c62b1958a3804780a2de7d1bd55e2fb298533"
  },
  "states": {
    "planned": "Declared surface, not yet implemented in opy-rs; evidence/provenance recorded for the implementing issue.",
    "source-supported": "Source implementation behavior (lex/parse/preprocess/macro expansion) implemented in opy-rs and corpus-evidenced.",
    "semantic-supported": "Semantic resolution implemented in opy-rs (names, members, enums, call semantics covered by the semantic model).",
    "lowering-dependent": "Completion requires canonical Workshop semantics/catalog/emission owned by workshop-rs; inventory-only until the integration stage.",
    "end-to-end-supported": "A declared feature or bounded integration slice has explicit OPY -> HIR -> WIR -> validated Workshop emission evidence for that scope; this state does not imply full-language OPY-to-Workshop parity."
  },
  "categories": [
    "syntax",
    "semantics",
    "preprocessing",
    "macros",
    "directives",
    "translations",
    "optimization",
    "runtime",
    "compilation",
    "decompilation"
  ],
  "features": [
    {
      "id": "syntax/lexing",
      "name": "Lexer: identifiers, literals, strings, comments, #! directives, operators",
      "category": "syntax",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/basic-rule",
        "fixtures:synthetic/control-flow",
        "fixtures:synthetic/expressions-values",
        "fixtures:synthetic/diagnostics",
        "fixtures:real-world/overpy-cake",
        "upstream:src/tests/comments.opy",
        "upstream:src/tests/operators.opy",
        "upstream:src/tests/strings.opy",
        "upstream:src/tests/arrays.opy"
      ],
      "notes": "Corpus-evidenced: differential suite runs 40 fixtures; upstream tokenizer surface probed."
    },
    {
      "id": "syntax/expressions",
      "name": "Expression/postfix/member/call grammar, precedence, indexing",
      "category": "syntax",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/expressions-values",
        "fixtures:synthetic/receiver-calls",
        "fixtures:real-world/overpy-cake",
        "upstream:src/tests/operators.opy",
        "upstream:src/tests/arrays.opy",
        "upstream:src/tests/strings_args.opy"
      ],
      "notes": "Corpus-evidenced: expression fixtures + receiver-calls fixture resolve through the semantic model."
    },
    {
      "id": "syntax/declarations",
      "name": "Declarations: globalvar/playervar (index + initializer), subroutine, def, enum, macro constants",
      "category": "syntax",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/declarations-rules",
        "fixtures:synthetic/declarations-numbers",
        "fixtures:synthetic/preprocessing",
        "fixtures:real-world/overpy-cake",
        "upstream:src/tests/variables.opy",
        "upstream:src/tests/subroutines.opy",
        "upstream:src/tests/enums.opy"
      ],
      "notes": "Corpus-evidenced: declarations fixtures + overpy-cake resolve; diagnostics for malformed declarations."
    },
    {
      "id": "syntax/assignments-control-flow",
      "name": "Assignments and control flow: =, +=, -=, *=, /=, %=, **=, if/elif/else, for-in-range, while, pass",
      "category": "syntax",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/control-flow",
        "fixtures:synthetic/for-range-agentlab",
        "fixtures:synthetic/chase-condition-agentlab",
        "upstream:src/tests/loops.opy",
        "upstream:src/tests/conditions.opy"
      ],
      "notes": "Corpus-evidenced: the supported augmented assignment subset is +=, -=, *=, /=, %=, and **=; control-flow fixtures resolve; parser rejects out-of-surface forms structurally. min=/max= and ++/-- remain explicit follow-ups (#59, wrightkit/workshop-rs#95)."
    },
    {
      "id": "syntax/switch",
      "name": "switch/case/default",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "fixtures:synthetic/issue-33-switch-break", "upstream:src/tests/switches.opy"],
      "notes": "Issue #28/#33: switch/case/default preserve source-order arms and fall through into subsequent arms; explicit break exits the innermost switch or loop. Workshop lowering remains out of scope."
    },
    {
      "id": "syntax/break",
      "name": "break statements in switch and loops",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-33-switch-break", "upstream:src/tests/switches.opy", "upstream:src/tests/loops.opy"],
      "notes": "Issue #33: break is a real HIR statement, validates its enclosing switch/loop context, and is retained without implicit arm exits."
    },
    {
      "id": "syntax/do-while",
      "name": "do … while",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "fixtures:real-world/overpy-santa/regressions/do-while.opy", "upstream:src/tests/loops.opy"],
      "notes": "Issue #28: the body executes before the condition and the condition is retained as an OPY HIR expression; malformed/truncated conditions remain structured parse errors."
    },
    {
      "id": "syntax/hex-literals",
      "name": "Hexadecimal numeric literals (0x/0X)",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "upstream:src/tests/operators.opy"],
      "notes": "Issue #28: hexadecimal source spelling is preserved in the numeric HIR text while the numeric value is decoded independently."
    },
    {
      "id": "syntax/membership",
      "name": "Expression-level in/not in membership",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "upstream:src/tests/operators.opy"],
      "notes": "Issue #28: in/not in are represented as source-semantic binary operators; no Workshop Array Contains catalog or lowering is copied here."
    },
    {
      "id": "syntax/string-modifiers",
      "name": "String modifiers (f/w/l/b/c/t)",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-string-modifiers", "fixtures:synthetic/issue-28-syntax", "fixtures:synthetic/issue-33-f-string", "upstream:src/tests/strings.opy"],
      "notes": "Issue #28/#33: f-string interpolation lowers to a semantic format node with source-spanned arguments; w/b/c remain semantic string modifiers and l/t remain syntax-carried without duplicating translation data."
    },
    {
      "id": "syntax/dicts",
      "name": "Dictionary literals and keyed access",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "upstream:src/tests/dicts.opy"],
      "notes": "Issue #28: dictionary entries and keyed access are represented in OPY HIR; bare dictionaries and malformed entries produce structured diagnostics."
    },
    {
      "id": "syntax/comprehensions",
      "name": "List comprehensions (mapping/filtering, element and index binders)",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "upstream:src/tests/dicts.opy"],
      "notes": "Issue #28: one-for-clause comprehensions with an optional filter and optional element/index binders preserve local scope in HIR."
    },
    {
      "id": "syntax/lambda",
      "name": "Lambda expressions for array operations",
      "category": "syntax",
      "state": "source-supported",
      "evidence": ["fixtures:synthetic/issue-28-syntax", "fixtures:synthetic/issue-33-f-string", "fixtures:synthetic/issue-33-lambda-negative", "upstream:src/tests/dicts.opy"],
      "notes": "Issue #28/#33: lambda x: expr is accepted only in signature-approved positions (sorted index 1/key and array map/filter/all/any index 0); standalone and other argument positions produce a structured diagnostic."
    },
    {
      "id": "syntax/settings-blocks",
      "name": "settings { ... } custom-game-settings blocks: JSONC parse into the typed HIR payload",
      "category": "syntax",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/settings",
        "fixtures:real-world/overpy-meipocalypse/settings.opy",
        "fixtures:real-world/6v6-adjustments/lobby/lobby.opy",
        "upstream:src/tests/customGameSettings.opy",
        "upstream:src/tests/workshopSettings.opy"
      ],
      "notes": "Corpus-evidenced: settings fixtures parse into the typed HIR payload. Validation is structural only (group shape, span validity, non-empty key names); key-existence and leaf-kind settings validation was removed from the core and is lowering-dependent (#8). Emission lowering-dependent."
    },
    {
      "id": "semantics/declaration-resolution",
      "name": "Name resolution: undeclared identifiers, subroutine and constant references, enum types",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/declarations-rules",
        "fixtures:synthetic/expressions-values",
        "upstream:src/tests/functions.opy",
        "upstream:src/tests/subroutines.opy"
      ],
      "notes": "Resolved in Opy HIR with structured unknown-identifier/unsupported-member diagnostics; fixtures + tooling tests."
    },
    {
      "id": "semantics/for-binder",
      "name": "for-loop binder: declared globalvar or implicit default variables A-Z … DA-DX",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/for-range-agentlab",
        "upstream:src/tests/loops.opy"
      ],
      "notes": "for-loop binders resolve to declared globals or implicit default variables (A-Z .. DA-DX); fixture for-range-agentlab."
    },
    {
      "id": "semantics/builtin-actions-values",
      "name": "OPY builtin actions and values: manifest identities, signatures, aliases, and call semantics",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "probes:generic-builtins",
        "probes:chase-over-time",
        "probes:is-game-in-progress",
        "probes:get-players-in-radius",
        "probes:catalog-only-names",
        "probes:unknown-function",
        "probes:unknown-value",
        "probes:action-in-value-position",
        "probes:value-in-action-position",
        "fixtures:synthetic/basic-rule",
        "fixtures:synthetic/chase-condition-agentlab"
      ],
      "notes": "Issue #30. The manifest-declared OPY overlay is semantic-supported: source identities, action/value position, signatures, keyword binding, aliases, and canonical catalogId links are probe-validated against the pinned oracle. Canonical Workshop existence/content/emission breadth is tracked separately as lowering-dependent."
    },
    {
      "id": "semantics/workshop-builtin-catalog",
      "name": "Canonical Workshop builtin action/value catalog existence, content, and emission",
      "category": "semantics",
      "state": "lowering-dependent",
      "evidence": [
        "probes:catalog-only-names",
        "fixtures:synthetic/receiver-calls",
        "fixtures:synthetic/chase-condition-agentlab",
        "upstream:src/data/opy/functions.ts"
      ],
      "notes": "Issue #42 closes a bounded catalog-backed slice: manifest catalogId links lower to canonical action/value ids and representative receiver/chase cases emit through workshop-rs with WIR and canonical-id validation. Full Workshop catalog breadth, content domains, localized spellings, and emission remain lowering-dependent; opy-rs does not copy the catalog or claim full 225/267 coverage."
    },
    {
      "id": "semantics/receiver-members",
      "name": "OPY receiver/member semantics: receiver categories and explicit-argument signatures",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "probes:receiver-calls",
        "probes:enum-gated-members",
        "probes:invalid-arity-member",
        "probes:generic-member-only-action",
        "probes:member-value-in-action-position",
        "probes:invalid-receiver-append",
        "probes:invalid-receiver-format",
        "fixtures:synthetic/receiver-calls",
        "upstream:src/data/opy/memberFunctions.ts"
      ],
      "notes": "Issue #30. The manifest-declared OPY member overlay is semantic-supported: receiver syntax/category semantics, explicit-argument signatures, variable receiver rules, aliases, and catalogId links are probe-validated. Canonical member existence/content and Workshop emission remain lowering-dependent."
    },
    {
      "id": "semantics/workshop-receiver-catalog",
      "name": "Canonical Workshop receiver/member catalog existence, content, and emission",
      "category": "semantics",
      "state": "lowering-dependent",
      "evidence": [
        "probes:receiver-calls",
        "fixtures:synthetic/receiver-calls",
        "upstream:src/data/opy/memberFunctions.ts"
      ],
      "notes": "Issue #42 closes the evidenced receiver slice: member action/value catalogIds are lowered with the receiver as the canonical leading operand, and catalog-gap members remain explicit integration diagnostics. The OPY receiver/member source-language surface (names, aliases, receiver categories, and signatures) belongs to opy-rs; workshop-rs owns canonical Workshop target identities and semantics, content domains, localization, validation, and emission."
    },
    {
      "id": "semantics/receiver-playervar",
      "name": "Bare playervar receiver member access (`A = B.C`)",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/receiver-playervar",
        "upstream:src/tests/variables.opy",
        "upstream:src/data/opy/memberFunctions.ts"
      ],
      "notes": "Issue #30 repair. The pinned oracle accepts this OPY-owned receiver form and the source implementation preserves its variable receiver and member identity in HIR with source provenance. Canonical member existence and emission remain Workshop-owned and lowering-dependent; #8 must not be used to claim the OPY expression incomplete."
    },
    {
      "id": "semantics/enum-domains",
      "name": "OPY enum/domain semantics: declared domain identities and contextual dispatch",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "probes:unknown-enum",
        "fixtures:synthetic/chase-enums",
        "fixtures:synthetic/chase-keywords",
        "upstream:src/tests/builtinenums.opy",
        "upstream:src/data/opy/constants.ts"
      ],
      "notes": "Issue #30. Manifest parameter domains and contextual dispatch are semantic-supported OPY identity links with oracle/corpus evidence. Domain member lists, member existence, domain membership, localized spellings, and emission remain Workshop-owned and are never approximated in opy-rs."
    },
    {
      "id": "semantics/workshop-enum-domains",
      "name": "Canonical Workshop enum/domain member lists, membership, and emission",
      "category": "semantics",
      "state": "lowering-dependent",
      "evidence": [
        "probes:unknown-enum",
        "fixtures:synthetic/chase-enums",
        "fixtures:synthetic/chase-condition-agentlab",
        "upstream:src/data/opy/constants.ts"
      ],
      "notes": "Issue #42 closes catalog validation for the representative declared and contextual enum slice: canonical domains/members are checked through workshop-rs and contextual chase dispatch reaches canonical action ids. Full Hero, Map, Gamemode, Team, and settings/content domain breadth remains Workshop-owned and lowering-dependent."
    },
    {
      "id": "semantics/aliases",
      "name": "Source aliases: non-contextual (stopChasingVariable, getCurrentHero, hasStatusEffect) and the ChaseReeval contextual alias",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "probes:aliases",
        "probes:member-aliases",
        "probes:chase-reeval-context",
        "probes:chase-reeval-outside"
      ],
      "notes": "Issue #4. Declared alias surface (3 non-contextual + ChaseReeval contextual) resolves; probes pass (chase-reeval-outside stays: it documents the contextual-domain identity rule). Wrong-domain member rejection is lowering-dependent (#8). Remaining alias surface legacy-quirk/demand-driven."
    },
    {
      "id": "semantics/modules",
      "name": "Modules: random.{randint,uniform,choice,shuffle}",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:real-world/overpy-cake",
        "fixtures:real-world/overpy-zencopter/heli.opy",
        "fixtures:real-world/overpy-meipocalypse/meipocalypse.opy",
        "upstream:src/data/opy/modules.ts"
      ],
      "notes": "random.{uniform,choice} calls resolve; corpus-evidenced (overpy-cake, zencopter, meipocalypse)."
    },
    {
      "id": "semantics/keyword-arguments",
      "name": "Named/keyword arguments: generic name=expr binding and the chase/ChaseReeval special form",
      "category": "semantics",
      "state": "semantic-supported",
      "evidence": [
        "probes:chase-keywords",
        "probes:chase-keyword-binding",
        "probes:chase-arg3-keyword-required",
        "probes:chase-duplicate-keyword",
        "probes:chase-missing-argument",
        "probes:chase-positional-after-keyword",
        "probes:chase-unknown-keyword",
        "probes:wait-keyword-names",
        "probes:keyword-arguments-unsupported",
        "fixtures:synthetic/chase-keywords"
      ],
      "notes": "Generic keyword binding + chase/ChaseReeval special form; probe-evidenced (chase-keywords set)."
    },
    {
      "id": "semantics/diagnostics",
      "name": "Source identity and diagnostics: structured, source-located source implementation errors, wright-result/v1 envelope",
      "category": "semantics",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/diagnostics",
        "fixtures:synthetic/declarations-rules",
        "upstream:runTests.mjs"
      ],
      "notes": "Structured stable-code diagnostics with 1-based spans; the stable-code contract is documented in docs/opy/tooling-api.md and tested in opy-rs tooling tests."
    },
    {
      "id": "semantics/settings-emission",
      "name": "Workshop settings-section emission: key table, enum values, map/hero list elements",
      "category": "semantics",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/settings",
        "fixtures:real-world/6v6-adjustments/lobby/lobby.opy",
        "upstream:src/tests/customGameSettings.opy"
      ],
      "notes": "Settings lower directly into the neutral workshop-rs carrier; workshop-rs owns key/value validation, locale spellings, and emission. Emitted settings are deliberately not reparseable (round-trip boundary)."
    },
    {
      "id": "preprocessing/include",
      "name": "#!include: root-relative resolution, cycle detection, missing-file diagnostics, file registry",
      "category": "preprocessing",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/preprocessing",
        "fixtures:real-world/ow1-emulator",
        "fixtures:real-world/6v6-adjustments",
        "upstream:src/tests/include.opy",
        "upstream:src/tests/include3.opy",
        "upstream:src/tests/include5.opy"
      ],
      "notes": "Root-relative include resolution, cycle detection, missing-file diagnostics, file registry; deterministic multi-file tests."
    },
    {
      "id": "preprocessing/define-undef",
      "name": "#!define (object- and function-like), #!undef, recursive expansion, recursion guard",
      "category": "preprocessing",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/preprocessing",
        "fixtures:real-world/overpy-cake",
        "upstream:src/tests/macros.opy",
        "upstream:src/tests/builtinmacros.opy"
      ],
      "notes": "Object- and function-like #!define, #!undef, recursive expansion with recursion guard; preprocessing fixtures."
    },
    {
      "id": "preprocessing/advanced-directives",
      "name": "#!mainFile, #!allowMacroRedeclaration, #!optimize*/#!replace0By* family, #!rulePrefix*",
      "category": "preprocessing",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "fixtures:synthetic/issue-29-main-file",
        "upstream:src/tests/rulePrefix.opy",
        "upstream:src/tests/compression.opy",
        "upstream:src/data/opy/preprocessing.ts"
      ],
      "notes": "Issue #29: source implementation records directive state, macro-redeclaration policy, main-file provenance, and rule-prefix application. Optimizer and generated Workshop effects remain separate."
    },
    {
      "id": "preprocessing/directive-effects",
      "name": "Preprocessing directive effects on Workshop emission and optimization",
      "category": "preprocessing",
      "state": "lowering-dependent",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "upstream:src/data/opy/preprocessing.ts"
      ],
      "notes": "Rule-prefix metadata is already reflected in HIR rule names. Optimizer controls remain non-blocking presentation differences. The compiler rejects replacement directives at their source anchor until a canonical lowering and corpus evidence exist; it does not silently drop or approximate semantic rewrites."
    },
    {
      "id": "macros/definitions",
      "name": "macro name(params): statement bodies with MacroParam references, macro constants",
      "category": "macros",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/preprocessing",
        "fixtures:real-world/overpy-cake",
        "fixtures:real-world/overpy-meipocalypse",
        "fixtures:real-world/ow1-emulator/common/macro_functions.opy",
        "upstream:src/tests/macros.opy",
        "upstream:src/tests/astMacros.opy",
        "upstream:src/tests/builtinmacros.opy"
      ],
      "notes": "macro name(params): statement bodies with MacroParam references expand; corpus-evidenced (cake, meipocalypse, ow1-emulator)."
    },
    {
      "id": "macros/javascript",
      "name": "__script__ JavaScript macros (QuickJS runtime); #!postCompileHook parsed and recorded",
      "category": "macros",
      "state": "source-supported",
      "evidence": [
        "upstream:runTests.mjs",
        "upstream:src/tests/postCompileHook.opy",
        "upstream:src/tests/quickjs-modern.js",
        "upstream:src/tests/quickjs-invalid-return.js",
        "upstream:src/tests/quickjs-runaway.js",
        "upstream:src/quickjs.ts",
        "test:opy-rs-macro-integration",
        "test-fixture:crates/opy-rs/tests/fixtures/macros",
        "test:opy-rs-differential",
        "fixtures:real-world/overpy-meipocalypse"
      ],
      "notes": "Issue #6 + #7 part B. `#!define name(args) __script__(\"path.js\")` parsed (root-relative script resolution, script-not-found at the define site like the reference's ENOENT), expanded through opy_macro_js::MacroRuntime with the reference's var-injection ABI, indentation rule, and string-only completion contract — compile-time expansion executes and is source-supported. `#!postCompileHook` is parsed, validated, and recorded (duplicate rejection); compiler execution against final Workshop text is tracked by hooks/post-compile-workshop. Structured script-* diagnostics carry script provenance. Catalog constants remain lowering-dependent; `#!require` does not exist in the pinned reference."
    },
    {
      "id": "hooks/post-compile-workshop",
      "name": "Post-compile hook execution against the final Workshop text",
      "category": "macros",
      "state": "end-to-end-supported",
      "evidence": [
        "upstream:src/tests/postCompileHook.opy",
        "upstream:src/quickjs.ts",
        "test:opy-macro-js-hooks",
        "test:opy-rs-macro-integration",
        "test:opy-compiler"
      ],
      "notes": "The compiler runs the bounded opy-macro-js hook only after successful workshop-rs emission, passes the exact emitted Workshop text, and exposes the string completion as final output; hook failures retain both the directive anchor and structured script provenance."
    },
    {
      "id": "directives/rule-annotations",
      "name": "Rule annotations: @Event, @Condition, bare @Team/@Slot",
      "category": "directives",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/basic-rule",
        "fixtures:synthetic/declarations-rules",
        "fixtures:synthetic/control-flow",
        "upstream:src/tests/rules.opy",
        "upstream:README.md"
      ],
      "notes": "Core rule annotations and event/condition structure are source implementation-owned."
    },
    {
      "id": "directives/advanced-rule-annotations",
      "name": "Rule annotations: @Team/@Slot args, @Name, @Hero, @Disabled, @Delimiter, @NewPage, @SuppressWarnings",
      "category": "directives",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "fixtures:synthetic/issue-29-invalid",
        "upstream:src/data/opy/annotations.ts"
      ],
      "notes": "Issue #29: annotation arguments, rule metadata, and source diagnostics are retained in OPY HIR; hero/team/slot domain validation and Workshop UI effects remain lowering-dependent."
    },
    {
      "id": "directives/rule-model",
      "name": "Rule model: rule \"name\": with events (global, eachPlayer), conditions list, statements",
      "category": "directives",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic/basic-rule",
        "fixtures:synthetic/chase-condition-agentlab",
        "fixtures:synthetic/control-flow",
        "upstream:src/tests/rules.opy",
        "upstream:src/tests/eventVars.opy"
      ],
      "notes": "rule \"name\": with global/eachPlayer events, conditions, statements; differential fixtures."
    },
    {
      "id": "translations/directive",
      "name": "#!translations directive recognition and .po generation surface",
      "category": "translations",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "upstream:src/tests/translations.opy",
        "upstream:src/tests/translations2.opy",
        "upstream:src/tests/translations.es.po",
        "upstream:src/tests/translations2.fr.po",
        "upstream:src/compiler/translations.ts"
      ],
      "notes": "Issue #29: language-tag syntax, uniqueness/conflict validation, provenance, and translation state are source implementation-owned; locale availability, .po content, and generated Workshop helpers remain lowering-dependent."
    },
    {
      "id": "translations/locale-emission",
      "name": "Localized Workshop output (--language flag, localizedStrings data)",
      "category": "translations",
      "state": "end-to-end-supported",
      "evidence": [
        "upstream:src/data/localizedStrings.ts",
        "oracle:CLI --language en-US invocation recorded in compatibility/run_oracle.py",
        "test:opy-compiler"
      ],
      "notes": "Compiler locale selection delegates to workshop-rs catalog coverage and rejects undeclared locales explicitly; missing per-identity mappings remain fail-explicit."
    },
    {
      "id": "optimization/controls",
      "name": "#!optimize*/#!replace0By* family and compression controls",
      "category": "optimization",
      "state": "semantic-supported",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "upstream:src/tests/compression.opy",
        "upstream:src/data/opy/preprocessing.ts"
      ],
      "notes": "Issue #29: optimizer/replacement controls are parsed, validated, ordered, and exposed as source implementation state; transformation execution is not part of opy-rs."
    },
    {
      "id": "optimization/backend-effects",
      "name": "Optimizer transformations and replacement rewrites",
      "category": "optimization",
      "state": "lowering-dependent",
      "evidence": [
        "fixtures:synthetic/issue-29-directives",
        "upstream:src/data/opy/preprocessing.ts"
      ],
      "notes": "Optimizer transformations and replacement rewrites remain lowering-dependent. Optimizer controls remain non-blocking; replacement directives fail explicitly rather than silently changing Workshop output."
    },
    {
      "id": "optimization/emission-form",
      "name": "Workshop text emission form (variable naming, enum spellings, formatting)",
      "category": "optimization",
      "state": "lowering-dependent",
      "evidence": [
        "fixtures:synthetic/basic-rule/oracle.json",
        "fixtures:real-world/overpy-cake/oracle.json"
      ],
      "notes": "Output-text identity is explicitly not the compatibility contract; exact-vs-normalized differences are presentation differences. Emission form is workshop-rs-owned."
    },
    {
      "id": "runtime/js-hooks",
      "name": "QuickJS runtime for __script__ macro and hook execution (synthetic-content hook ABI)",
      "category": "runtime",
      "state": "source-supported",
      "evidence": [
        "upstream:runTests.mjs",
        "upstream:src/quickjs.ts",
        "oracle:quickjs-ng.wasm shipped in the pinned npm package",
        "test:opy-macro-js-abi",
        "test:opy-macro-js-hooks",
        "test:opy-macro-js-limits",
        "test:opy-rs-macro-integration"
      ],
      "notes": "Issue #6 + #7 part B. Bounded runtime surface wired into the source implementation: macro execution with argument injection, `vect` helper, empty constant objects, console capture, reference-compatible accept/reject and result semantics, resource limits defaulting to the pinned reference constants (1000 ms macro / 2000 ms hook budgets, 64 MiB memory, 512 KiB stack). The hook ABI runs against synthetic content in opy-macro-js; hook execution against the Workshop output is lowering-dependent (see hooks/post-compile-workshop, issue #8). Browser/WASM execution remains unsupported (native embedding only), matching the declared boundary."
    },
    {
      "id": "compilation/source implementation-pipeline",
      "name": "Source implementation pipeline: lexer -> preprocess -> CST/parser -> semantic resolution -> Opy HIR v2",
      "category": "compilation",
      "state": "source-supported",
      "evidence": [
        "fixtures:synthetic",
        "fixtures:real-world",
        "docs:docs/hir/opy-hir-v2.md",
        "test:opy-rs-differential"
      ],
      "notes": "Issues #3-#7, #25, and the #28/#29/#30/#33 readiness tracks. Fully Workshop-independent; the pinned differential corpus is the acceptance corpus. Differential harness runs every fixture through the native pipeline in cargo test with structural self-checks (HIR validation, wire round-trip, deterministic dump), status/rule-name parity against recorded oracle.json snapshots, explicit native evidence expectations, and a machine-readable report (target/opy-differential-report.json). The generated report records per-fixture matches and known gaps; no unexpected divergence or inconclusive result is a support claim."
    },
    {
      "id": "compilation/opy-integration-vertical-slice",
      "name": "Minimal OPY -> canonical WIR -> Workshop emission vertical slice",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-35-integration",
        "test:opy-compiler-vertical-slice",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #35. The dedicated opy-compiler crate consumes resolved OPY HIR, preserves source files/spans in workshop-rs WIR, cross-checks manifest catalogId/domain links against Catalog, validates canonical WIR, and emits deterministic en-US Workshop through the published workshop-rs v0.1.11 contract. This is a bounded first slice; broader OPY lowering remains lowering-dependent and is not reclassified by this fixture."
    },
    {
      "id": "compilation/opy-structural-lowering",
      "name": "OPY structural HIR -> canonical WIR lowering: declarations, subroutines, rules, events, and provenance",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-35-integration",
        "fixtures:synthetic/issue-40-structural",
        "test:opy-compiler-structural-lowering",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #40. Global/player variables and subroutines use deterministic canonical indices with source/name spans; subroutine definitions and calls, rule disabled state, conditions, supported event/filter identities, and source-file provenance lower directly into workshop-rs WIR. Unsupported settings, declarations, annotations, events, filters, and statement forms remain explicit source-attributed integration diagnostics. This does not claim full statement/expression, catalog/member/enum, settings, locale, optimizer, hook, or decompilation coverage."
    },
    {
      "id": "compilation/opy-assignment-lowering",
      "name": "OPY assignment and modification HIR -> canonical WIR lowering",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-46-primitives",
        "test:opy-compiler-primitive-lowering",
        "test:opy-compiler-issue-46-oracle-equivalence",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #46. Global/player assignments and augmented assignments (+=, -=, *=, /=, %=, **=), single-level indexed variable assignments and modifications (setGlobalVariableAtIndex, modifyGlobalVariableAtIndex, setPlayerVariableAtIndex, modifyPlayerVariableAtIndex), and pass no-op statements lower into canonical workshop-rs WIR. Declaration initializer evidence covers non-null initializers; OverPy null-default initializer semantics remain tracked by #58. Deeper indexed writes remain tracked by #60. Direct global/player assignments and modifications carry full statement and target-variable span provenance; the single-level indexed forms lower to canonical Call actions, which carry only the statement-level source span (the canonical WIR Call shape has no separate target-span field)."
    },
    {
      "id": "compilation/opy-implicit-default-variables",
      "name": "OverPy implicit default global and player variables (A-DX) at fixed Workshop slots",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-46-primitives",
        "test:opy-compiler-implicit-default-variables",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #46. Undeclared A-Z, AA-AZ, ..., DA-DX global references and eventPlayer.<name> player references resolve through the source implementation default_var_index contract and lower to separate Workshop variable namespaces at their fixed reference slots (A=0 ... DX=127); used implicit slots are reserved independently for declared global/player allocation, an explicit declared index colliding with a used implicit slot fails with the stable source-attributed index-collision diagnostic, and a declared name wins in its own namespace. The pinned oracle snapshot for the issue-46 fixture constrains global and player slots through structural equivalence."
    },
    {
      "id": "compilation/opy-primitive-lowering-limits",
      "name": "Negative primitive-lowering diagnostics for forms outside canonical WIR",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-46-unsupported",
        "test:opy-compiler-primitive-lowering-limits"
      ],
      "notes": "Issue #46 negative contract. A non-control-flow primitive the canonical WIR surface cannot represent (the fixture uses a dict-indexed assignment, which the pinned oracle compiles by constant folding) is rejected with the stable unsupported-integration-surface diagnostic attributed to the source statement; no unsupported HIR node is silently discarded or guessed."
    },
    {
      "id": "compilation/opy-expression-lowering",
      "name": "OPY non-control-flow value expression HIR -> canonical WIR lowering",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-46-primitives",
        "test:opy-compiler-primitive-lowering",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #46. Literals (numbers, strings, booleans, null), arrays, vectors (vect), enum constants, global/player/eventPlayer variable references, array indexing (valueInArray; a literal zero index lowers to firstOf, matching the pinned oracle), string formatting (customString), arithmetic/comparison/logical binary operations, unary operations (not, -; not on a comparison lowers to the negated comparison, matching the pinned oracle), and power operations lower into canonical workshop-rs WIR. Value-position power uses the canonical raiseToPower Value contract; direct and indexed power modifications use the canonical Workshop Operation contract."
    },
    {
      "id": "compilation/opy-control-flow-lowering",
      "name": "OPY control-flow HIR -> canonical WIR lowering",
      "category": "compilation",
      "state": "end-to-end-supported",
      "evidence": [
        "fixtures:synthetic/issue-47-control-flow",
        "fixtures:synthetic/issue-47-unsupported",
        "fixtures:synthetic/issue-47-switch-order",
        "fixtures:synthetic/issue-47-switch-structured-target",
        "fixtures:synthetic/issue-47-switch-multiple-break",
        "fixtures:synthetic/issue-47-do-while-shapes",
        "fixtures:synthetic/issue-47-do-while-invalid-placement",
        "fixtures:synthetic/issue-33-switch-break",
        "test:opy-compiler-issue-47-oracle-equivalence",
        "contract:workshop-rs-v0.1.11"
      ],
      "notes": "Issue #47. If/elif/else, while, global-binder range-for, do-while expansion, source-ordered switch fallthrough/default, and direct loop/switch/do-while break lower into canonical workshop-rs WIR. Switch offsets and do-while distances use workshop-rs v0.1.11 canonical emitted action widths; direct, conditional, nested, and structured-tail do-while shapes plus structured switch targets are pinned and oracle-equivalent. A nested conditional switch break and a multi-break switch with later reachable actions remain stable source-attributed unsupported-integration-surface diagnostics because workshop-rs v0.1.11 has no lossless multi-target switch carrier."
    },
    {
      "id": "compilation/workshop-lowering",
      "name": "HIR -> Workshop lowering and emission through workshop-rs",
      "category": "compilation",
      "state": "lowering-dependent",
      "evidence": [
        "fixtures:synthetic",
        "fixtures:real-world"
      ],
      "notes": "Issue #8 remains the broader lowering track. The released workshop-rs v0.1.11 public contract now supports the bounded #35 adapter, the #40 structural skeleton, and the separately evidenced #47 control-flow slice; full OPY statement/expression lowering, catalog/member/enum breadth, settings/content, locales, optimizer effects, and hooks remain lowering-dependent follow-up work. Oracle snapshots (fixtures/**/oracle.json) remain preserved reference evidence; no temporary Workshop IR is introduced here."
    },
    {
      "id": "compilation/end-to-end",
      "name": "End-to-end OPY -> Workshop compile parity",
      "category": "compilation",
      "state": "lowering-dependent",
      "evidence": [
        "fixtures:synthetic",
        "fixtures:real-world",
        "fixtures:census/workshop-feature-census"
      ],
      "notes": "Full OPY-to-Workshop parity remains lowering-dependent after the bounded #35 first slice; the OPY-side feature census records opaque workshop-rs#10 identities without duplicating catalog definitions. Differential harness contract is ready (compatibility/diff.py, issue #25)."
    },
    {
      "id": "decompilation/workshop-to-opy",
      "name": "Workshop -> OPY decompilation",
      "category": "decompilation",
      "state": "lowering-dependent",
      "evidence": [
        "upstream:src/tests/decompiler",
        "upstream:src/decompiler"
      ],
      "notes": "Deferred until the canonical Workshop semantic representation exists (workshop-rs integration); a non-goal before it. Upstream decompiler corpus (17 inputs) is the future reference."
    },
    {
      "id": "decompilation/roundtrip-boundary",
      "name": "Round-trip boundary: emitted settings reparsing, .ws round-trip",
      "category": "decompilation",
      "state": "lowering-dependent",
      "evidence": [
        "docs:docs/opy/support-matrix.md"
      ],
      "notes": "Documented boundary: emitted settings sections are deliberately not reparseable; a .ws decompiler is a non-goal. Reconstruction of arbitrary Workshop text is out of scope."
    }
  ],
  "summary": {
    "byState": {
      "planned": 0,
      "source-supported": 23,
      "semantic-supported": 13,
      "lowering-dependent": 10,
      "end-to-end-supported": 10
    },
    "byCategory": {
      "syntax": 14,
      "semantics": 14,
      "preprocessing": 4,
      "macros": 3,
      "directives": 3,
      "translations": 2,
      "optimization": 3,
      "runtime": 1,
      "compilation": 10,
      "decompilation": 2
    }
  }
}