expressir 2.4.3 → 2.4.4

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config.toml +3 -0
  3. data/.github/workflows/rust-ext.yml +41 -0
  4. data/.github/workflows/verify_remarks.yml +33 -0
  5. data/.gitignore +6 -0
  6. data/.rubocop.yml +4 -0
  7. data/.rubocop_todo.yml +1 -0
  8. data/Cargo.toml +7 -0
  9. data/README.adoc +65 -0
  10. data/Rakefile +12 -0
  11. data/TODO.parity-ee/00-overview.md +58 -0
  12. data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
  13. data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
  14. data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
  15. data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
  16. data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
  17. data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
  18. data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
  19. data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
  20. data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
  21. data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
  22. data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
  23. data/TODO.parity-ee/parity-matrix.md +108 -0
  24. data/exe/expressir +6 -0
  25. data/ext/expressir_core/Cargo.toml +24 -0
  26. data/ext/expressir_core/extconf.rb +30 -0
  27. data/ext/expressir_core/src/lib.rs +446 -0
  28. data/lib/expressir/cli.rb +49 -4
  29. data/lib/expressir/commands/check.rb +56 -0
  30. data/lib/expressir/commands/expand.rb +26 -0
  31. data/lib/expressir/commands/fix.rb +33 -0
  32. data/lib/expressir/commands/flatten.rb +29 -0
  33. data/lib/expressir/commands/parity_inputs.rb +85 -0
  34. data/lib/expressir/commands/validate.rb +22 -0
  35. data/lib/expressir/commands.rb +5 -0
  36. data/lib/expressir/express/builder_registry.rb +11 -2
  37. data/lib/expressir/express/builders/entity_decl_builder.rb +17 -7
  38. data/lib/expressir/express/builders/subtype_constraint_builder.rb +3 -1
  39. data/lib/expressir/express/builders/type_builder.rb +8 -0
  40. data/lib/expressir/express/builders/unique_rule_builder.rb +8 -1
  41. data/lib/expressir/express/checker.rb +458 -0
  42. data/lib/expressir/express/concatenator.rb +79 -0
  43. data/lib/expressir/express/core.rb +66 -0
  44. data/lib/expressir/express/formatter.rb +25 -3
  45. data/lib/expressir/express/formatters/data_types_formatter.rb +2 -2
  46. data/lib/expressir/express/formatters/declarations_formatter.rb +1 -0
  47. data/lib/expressir/express/formatters/remark_formatter.rb +30 -6
  48. data/lib/expressir/express/formatters/statements_formatter.rb +7 -1
  49. data/lib/expressir/express/interface_dot.rb +105 -0
  50. data/lib/expressir/express/listing.rb +174 -0
  51. data/lib/expressir/express/model_traversal.rb +42 -0
  52. data/lib/expressir/express/node_position_index.rb +18 -4
  53. data/lib/expressir/express/parser.rb +242 -4
  54. data/lib/expressir/express/pretty_gate.rb +61 -0
  55. data/lib/expressir/express/refs_overlay.rb +47 -0
  56. data/lib/expressir/express/remark_attacher.rb +122 -10
  57. data/lib/expressir/express/remark_overlay.rb +86 -0
  58. data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
  59. data/lib/expressir/express/schema_source_formatter.rb +5 -5
  60. data/lib/expressir/express/self_schema_reference.rb +126 -0
  61. data/lib/expressir/express/shtolo.rb +522 -0
  62. data/lib/expressir/express.rb +13 -0
  63. data/lib/expressir/model/concerns.rb +15 -1
  64. data/lib/expressir/model/declarations/entity.rb +6 -1
  65. data/lib/expressir/model/declarations/interface.rb +13 -0
  66. data/lib/expressir/model/declarations/schema.rb +74 -23
  67. data/lib/expressir/model/indexes/item_graph.rb +135 -0
  68. data/lib/expressir/model/indexes.rb +1 -0
  69. data/lib/expressir/model/model_element.rb +30 -1
  70. data/lib/expressir/model/remark_info.rb +20 -1
  71. data/lib/expressir/model/remark_placement.rb +15 -2
  72. data/lib/expressir/model/repository.rb +8 -2
  73. data/lib/expressir/model.rb +2 -1
  74. data/lib/expressir/version.rb +1 -1
  75. data/lib/tasks/verify_remarks.rake +9 -0
  76. data/rakelib/verify_remarks.rake +16 -0
  77. metadata +42 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b0fe8cde3b24a7a4ce39599fa68b61b02d3f8af45c1a8f5e45ce2607a213922
4
- data.tar.gz: 869991a150512a7b12fb94f18f97e66bc6954317c311f630b3fac41d55d001b0
3
+ metadata.gz: faa2eff1343ffba0a34111f1b9c48f2ea65fc8585da64b15844e39cd413b067f
4
+ data.tar.gz: 34ad23a65dabd3806206cf741c4e19d468bad9f6c566b89c0af10c594e0ca99b
5
5
  SHA512:
6
- metadata.gz: d04f62c906dc98f43a469f88ec56382decf8636407766c94b1248f94fbc21a2667144cc421a021dda592ea5d56987937ca20ea819a4300540589ea935c2767c2
7
- data.tar.gz: eeaa19435f4e66921136fbe3cee4ac729f5dfd5fa4f5731cc5b88a601639518c6be3ebfa70af4d29ef8f78500e80586a50df7636a88892a03f93787d9bee2182
6
+ metadata.gz: 05d55fe19517184f73d6f97815be45fef28a7c8d84360ee8a83288e2d0de63671f8fd5715bd4e14c0154cc731d3531871ebeccf83a52c41d6dc1f6dc412e433f
7
+ data.tar.gz: fc4a6d27fde05257a4b8023ed7507caecdbbb6f79a28f32085ce17c79d1f30428bae762d70b80906f3b6e1e8a46237e7fe5a6ab2d67f407b8fc5cf0c86bf8864
@@ -0,0 +1,3 @@
1
+ # Git deps fetch over SSH by the system git CLI (cargo HTTPS auth fails locally).
2
+ [net]
3
+ git-fetch-with-cli = true
@@ -0,0 +1,41 @@
1
+ name: rust-ext
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ build-ext:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: dtolnay/rust-toolchain@stable
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: "3.4"
17
+ bundler-cache: true
18
+ - name: Build the expressir-core extension
19
+ working-directory: ext/expressir_core
20
+ run: |
21
+ gem install rb_sys
22
+ ruby extconf.rb
23
+ RB_SYS_CARGO_PROFILE=release make
24
+ - name: Smoke test the bridge
25
+ run: |
26
+ bundle exec ruby -e '
27
+ require "expressir"
28
+ require "expressir/express/core"
29
+ raise "native unavailable" unless Expressir::Express::Core::NATIVE_AVAILABLE
30
+ src = File.read("spec/syntax/multiple.exp")
31
+ m = Expressir::Express::Core.parse_to_model_hash(src, "multiple.exp")
32
+ raise "bad model" unless m["schemas"].first["id"] == "multiple_schema"
33
+ puts "bridge OK"
34
+ '
35
+ # The default `rake` CI job covers the pure-Ruby parse path (no
36
+ # extension built there); this job pins the core parse path: with the
37
+ # extension present the parser defaults to it, so the whole suite runs
38
+ # against the Rust wire hydration.
39
+ - name: Run the suite on the core parse path
40
+ run: |
41
+ bundle exec rspec spec/expressir spec/syntax --tag ~production_scale
@@ -0,0 +1,33 @@
1
+ name: "verify_remarks"
2
+
3
+ permissions:
4
+ contents: read
5
+
6
+ on:
7
+ push:
8
+ branches: [ main ]
9
+ pull_request:
10
+ workflow_dispatch:
11
+
12
+ concurrency:
13
+ group: '${{ github.workflow }}-${{ github.ref }}'
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ remarks:
18
+ name: Verify remark conservation
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install Ruby
26
+ uses: ruby/setup-ruby@master
27
+ with:
28
+ ruby-version: "3.2"
29
+ bundler-cache: true
30
+ cache-version: 0 # Increment this number if you need to re-download cached gems
31
+
32
+ - name: Verify remark conservation
33
+ run: bundle exec rake verify:remarks
data/.gitignore CHANGED
@@ -42,3 +42,9 @@ Gemfile.local.lock
42
42
  Gemfile.original
43
43
  benchmark/
44
44
  CLAUDE.md
45
+
46
+ # Rust workspace
47
+ /target/
48
+ Cargo.lock
49
+ /ext/expressir_core/target/
50
+ /ext/expressir_core/*.bundle
data/.rubocop.yml CHANGED
@@ -12,3 +12,7 @@ AllCops:
12
12
  NewCops: enable
13
13
  Exclude:
14
14
  - 'vendor/**/*'
15
+ - 'metanorma-mirror-*/**/*'
16
+
17
+ Lint/UnusedMethodArgument:
18
+ AllowUnusedKeywordArguments: true
data/.rubocop_todo.yml CHANGED
@@ -144,6 +144,7 @@ Performance/MapMethodChain:
144
144
  RSpec/AnyInstance:
145
145
  Exclude:
146
146
  - 'spec/expressir/commands/package_edge_cases_spec.rb'
147
+ - 'spec/expressir/express/remark_attacher_performance_spec.rb'
147
148
 
148
149
  # Offense count: 11
149
150
  # Configuration parameters: Prefixes, AllowedPatterns.
data/Cargo.toml ADDED
@@ -0,0 +1,7 @@
1
+ [workspace]
2
+ resolver = "2"
3
+ members = ["crates/expressir-core"]
4
+
5
+ [workspace.package]
6
+ edition = "2021"
7
+ license = "MIT"
data/README.adoc CHANGED
@@ -211,10 +211,13 @@ Commands:
211
211
  expressir benchmark-cache FILE_OR_YAML # Benchmark schema loading with caching
212
212
  expressir changes SUBCOMMAND # Commands for EXPRESS Changes files
213
213
  expressir clean PATH # Strip remarks and prettify EXPRESS schema at PATH
214
+ expressir expand PATH # Concatenate the interface closure into one .exp
215
+ expressir flatten PATH # Flatten the interface closure into an ISO 10303-11:1994 longform schema
214
216
  expressir format PATH # pretty print EXPRESS schema located at PATH
215
217
  expressir help [COMMAND] # Describe available commands or one specific command
216
218
  expressir validate load *PATH # validate EXPRESS schema located at PATH
217
219
  expressir validate ascii PATH # Validate EXPRESS files for ASCII-only content (excluding remarks)
220
+ expressir validate check *PATHS # eeng check-p11 semantic checks
218
221
  expressir coverage *PATH # List EXPRESS entities and check documentation coverage
219
222
  expressir version # Expressir Version
220
223
  ----
@@ -508,6 +511,48 @@ expressir clean schemas/resources/action_schema/action_schema.exp --output clean
508
511
  | `--output PATH` | Path to save the cleaned schema (optional, defaults to stdout)
509
512
  |===
510
513
 
514
+ === Expand schema (concatenated artifact)
515
+
516
+ The `expand` command flattens the interface closure of a root EXPRESS schema
517
+ into a single concatenated artifact (one section per source schema, ordered
518
+ alphabetically — the same shape eeng emits for `--concat_schema`).
519
+
520
+ [source, sh]
521
+ ----
522
+ expressir expand schemas/resources/action_schema/action_schema.exp \
523
+ --output action-concatenated.exp
524
+ ----
525
+
526
+ [options="header"]
527
+ |===
528
+ | Option | Description
529
+ | `--output PATH`, `-o PATH` | Write the artifact to PATH (defaults to stdout)
530
+ |===
531
+
532
+ The closure is resolved by scanning `USE FROM` / `REFERENCE FROM` names in the
533
+ root source and looking them up in the same directory.
534
+
535
+ === Flatten schema (SHTOLO longform)
536
+
537
+ The `flatten` command converts a STEPmod-style multi-schema root into a single
538
+ ISO 10303-11:1994 "longform" schema (expressir#32). It runs the Annex G
539
+ conversion locally: interface-closure copy with rename resolution and name
540
+ munging, then extensible enum/select resolution, subtype-constraint
541
+ elimination, RENAMED→DERIVE, GENERIC_ENTITY→GENERIC.
542
+
543
+ [source, sh]
544
+ ----
545
+ expressir flatten schemas/resources/action_schema/action_schema.exp \
546
+ --output action_lf.exp --longform_name action_schema_lf
547
+ ----
548
+
549
+ [options="header"]
550
+ |===
551
+ | Option | Description
552
+ | `--output PATH`, `-o PATH` | Write the longform schema to PATH (defaults to stdout)
553
+ | `--longform_name ID` | Identifier for the resulting SCHEMA (default: `<root>_lf`)
554
+ |===
555
+
511
556
  === Validate schema
512
557
 
513
558
  The `validate load` command performs validation checks on EXPRESS schema files.
@@ -536,6 +581,26 @@ The command reports any schemas that:
536
581
 
537
582
  If all validations pass, it will display "Validation passed for all EXPRESS schemas."
538
583
 
584
+ === Validate semantic checks (eeng check-p11)
585
+
586
+ The `validate check` command runs the eeng `check-p11` note subset
587
+ implemented in `Expressir::Express::Checker`: redundant interfaces,
588
+ duplicate interface resources, unresolved interface schema/resource
589
+ refs, SUBTYPE OF targets, SELECT/ENUM BASED_ON targets, and WHERE/UNIQUE
590
+ label patterns.
591
+
592
+ [source, sh]
593
+ ----
594
+ # Check a single file
595
+ expressir validate check schemas/resources/action_schema/action_schema.exp
596
+
597
+ # Check all .exp files under a directory
598
+ expressir validate check schemas/resources/
599
+
600
+ # Exit 1 when any :error note fires
601
+ expressir validate check schemas/resources/action_schema/action_schema.exp
602
+ ----
603
+
539
604
  === Validate ASCII content
540
605
 
541
606
  The `validate ascii` command validates that EXPRESS schema files contain only
data/Rakefile CHANGED
@@ -14,3 +14,15 @@ task default: %i[spec rubocop]
14
14
  require "yard"
15
15
 
16
16
  YARD::Rake::YardocTask.new
17
+
18
+ Dir.glob(File.expand_path("lib/tasks/*.rake", __dir__)).each { |task| load task }
19
+
20
+ desc "Regenerate the EXPRESS grammar JSON embedded in expressir-rs"
21
+ task :"expressir:grammar:dump" do
22
+ require "expressir/express/grammar/parser"
23
+ json = Expressir::Express::Grammar::Parser.cached_grammar_json
24
+ dir = ENV.fetch("EXPRESSIR_RS_DIR", File.expand_path("../expressir-rs", __dir__))
25
+ path = File.join(dir, "assets", "express-grammar.json")
26
+ File.write(path, "#{json}\n")
27
+ puts "wrote #{path}"
28
+ end
@@ -0,0 +1,58 @@
1
+ # Parity with Express Engine (eeng) — SHTOLO and algorithms
2
+
3
+ **Status: PLANNED (2026-09-21)**
4
+
5
+ ## Mission
6
+
7
+ 1. **SHTOLO** (expressir#32): SHort-TO-LOng — generate ISO 10303-11:1994
8
+ "long form EXPRESS" (one self-contained schema) from the STEPmod
9
+ multi-schema structure (edition 2: shared files, USE FROM /
10
+ REFERENCE FROM). The normative conversion rules are
11
+ **ISO 10303-11:2004 Annex G** — local sources:
12
+ `~/src/mn/iso-10303-11/sources/sections/ag-single-schema.adoc`.
13
+ 2. **Concatenation** (expressir#247, metanorma/iso-10303#539): the SHTOLO
14
+ precursor — a dependency-closure concatenation of all interfaced
15
+ schemas into one publication artifact (`.exp`), plus SMRL index.
16
+ 3. **Validation** of both, against the reference implementation:
17
+ Express Engine (`~/src/external/exp-engine-engine`, Common Lisp),
18
+ whose `qualify.sh` runs the full operation catalog over the exact
19
+ SMRL corpus we already load (`resources.lst`/`modules.lst` ==
20
+ our SRL manifests).
21
+
22
+ ## Reference implementation map
23
+
24
+ | eeng source | operation (qualify.sh) | task |
25
+ |---|---|---|
26
+ | `plugins/p11/wo-pretty.lisp` | Pretty Print `.exp` + compare | 08 |
27
+ | `plugins/p11/wo-flat.lisp` + `run-op :flat` | **Flatten to long form** | 05 |
28
+ | mode `:concatenated` (`kernel/engine.lisp`) | **Concatenate schema** | 04 |
29
+ | `plugins/p11/wo-list.lisp` | List declarations | 09 |
30
+ | `plugins/p11/wo-smrl-xml.lisp` | SMRL index XML | 09 |
31
+ | `kernel/dot-graph.lisp` | Dot interface graph | 10 |
32
+ | `kernel/check.lisp` (835 lines) | semantic checks | 07 |
33
+ | `plugins/p11/schedule-*.lisp`, `kernel/resolve-interface.lisp` | load/resolution scheduling | 06 |
34
+ | `kernel/compute-inheritance.lisp`, `supertypes.lisp`, `derive-attrs.lisp`, `inverse-attrs.lisp` | entity computations | 02/07 |
35
+
36
+ ## What we already have (expressir)
37
+
38
+ Compiled schema set (batch + EXSCS1 artifact + overlays), repository
39
+ indexes + reference graph (37.7k subtype edges, interfaces, closures),
40
+ `Schema#interfaced_items`, resolver, formatter (clean/hyperlink),
41
+ `RepositoryValidator`, Part 21 parser = **not started** (see 02).
42
+
43
+ ## Task index
44
+
45
+ 01 Annex G rule extraction · 02 eeng algorithm inventory (what we do
46
+ differently) · 03 eeng oracle harness · 04 concatenation (#247) ·
47
+ 05 SHTOLO longform flatten (#32) · 06 interface scheduling parity ·
48
+ 07 semantic checks port · 08 pretty-print round-trip gate ·
49
+ 09 SMRL index + listing · 10 interface dot graph ·
50
+ 11 import the eeng test suite (scripts/ drivers, docs/issues bugs,
51
+ SHTOLO paper, BNFs, DTDs)
52
+
53
+ ## Additional eeng assets (via 11)
54
+
55
+ `scripts/*.sh` — 14 release-suite drivers (qual/pretty/xml/dot);
56
+ `docs/issues/` — bug corpus incl. a shtolo old-vs-new differential;
57
+ `docs/` — SHTOLO paper PDF, Part 11/14/21 BNFs, XML DTDs,
58
+ interface/qualify notes; `00check.txt` — check design notes.
@@ -0,0 +1,41 @@
1
+ # 01 — Annex G rule extraction (executable spec for SHTOLO)
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ Turn `~/src/mn/iso-10303-11/sources/sections/ag-single-schema.adoc`
8
+ (1957 lines) into an executable checklist: every conversion rule with
9
+ an identifier, inputs, outputs, and a fixture that exercises it. This
10
+ is the contract both for our implementation (05) and for judging
11
+ eeng's coverage.
12
+
13
+ ## Source structure (verified)
14
+
15
+ - Fundamentals: multi-schema → intermediate single "artifact" schema →
16
+ rewrite using 1994-only constructs; subtype/supertype graph pruning;
17
+ interface knowledge (visibility + instantiability) becomes rules;
18
+ total_over constraints become rules.
19
+ - **Name munging**: name-clash policy; identifiers-as-strings.
20
+ - **Stage 1 (multi → intermediate)**: primary population (per
21
+ interfaced item: artifact-schema rule + function capturing
22
+ visibility/instantiability), secondary population, **prune** rules
23
+ (rules whose parameters are not all visible are deleted, etc.).
24
+ - Stage 2 (intermediate → 1994 longform): rewrite of constructs not in
25
+ the 1994 edition.
26
+
27
+ ## Steps
28
+
29
+ 1. Read the full annex; number every rule `G.<n>` with a one-line
30
+ statement, inputs/outputs, and stage.
31
+ 2. Build a fixture matrix: for each rule, the smallest STEPmod schema
32
+ pair(s) that trigger it (mine the SMRL corpus for real cases).
33
+ 3. Cross-reference which rules eeng implements (grep its sources for
34
+ the mechanisms) and mark: implemented-in-eeng / our-gap / both-gap.
35
+ 4. Encode the checklist as a spec document under
36
+ `spec/fixtures/shtolo/rules.md` (or adoc) that 05's suite cites.
37
+
38
+ ## Acceptance
39
+
40
+ Every rule in Annex G has an id, a fixture, and an eeng-coverage flag;
41
+ no rule left "uncategorized".
@@ -0,0 +1,8 @@
1
+ # 02 — eeng algorithm inventory: what they do vs what we do differently
2
+
3
+ **Status: SHIPPED (2026-09-21) — see parity-matrix.md for the audit and
4
+ expressir#373 for the bug the audit surfaced.**
5
+
6
+ See `parity-matrix.md` (same directory) for the full algorithm-by-
7
+ algorithm comparison: resolution scoping, interface scheduling,
8
+ entity computations, writers, and the concrete expressir gaps found.
@@ -0,0 +1,33 @@
1
+ # 03 — Build and run eeng as a differential oracle
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ A working `eengine` binary (SBCL build) we can run over the SMRL corpus
8
+ to produce reference outputs (pretty, flat, concatenated, list,
9
+ smrl-xml, dot, checks) for differential validation of our ports.
10
+
11
+ ## Steps
12
+
13
+ 1. Install/locate SBCL; build: `sbcl --load sbcl/compile` then
14
+ `sbcl --load sbcl/deliver` (per README.txt) → `eengine`.
15
+ 2. Reproduce `qualify.sh` flow for a handful of modules from
16
+ `qualify-mod.txt` (their lists == our SRL corpus names).
17
+ 3. Golden corpus: run all qualify operations for the full
18
+ `resources.lst` + `modules.lst`; commit distilled outputs (not the
19
+ whole tree) under `spec/fixtures/eeng-oracle/` (LFS-sized check
20
+ first).
21
+ 4. Script `script/eeng-oracle` (or Rake task) exposing one-command
22
+ regeneration; document known eeng bugs/limitations found while
23
+ driving it (feeds 01's coverage flags).
24
+
25
+ ## Acceptance
26
+
27
+ One command regenerates the golden corpus; at least arm/mim pretty +
28
+ flat + concatenated outputs exist for 10 modules and 10 resources.
29
+
30
+ ## Tests
31
+
32
+ Refreshes the expected outputs consumed by 11's imported specs; the
33
+ qual-* drivers are the oracle's entry points.
@@ -0,0 +1,44 @@
1
+ # 04 — Concatenated EXPRESS artifact (expressir#247)
2
+
3
+ **Status: SHIPPED (2026-09-21)** — `Expressir::Express::Concatenator`
4
+ (closure + writer + one-call `call`), eeng-semantics ordering and
5
+ section format (alphabetical, `-- NAME (file)` separators, verbatim
6
+ source copies); specs: synthetic closure/round-trip + ENV-gated eeng
7
+ differential (byte-identical sections vs `--concat_schema` for
8
+ description_assignment ARM). Golden oracle outputs committed for ARM
9
+ and MIM. During this stage the small-input USE FROM parse bug was
10
+ found and reported as expressir#373.
11
+
12
+ ## Goal
13
+
14
+ `expressir` command producing a **concatenated** `.exp`: the root
15
+ schema followed by every USE FROM / REFERENCE FROM dependency
16
+ (non-circular closure), each as plain EXPRESS (no remarks), with an
17
+ SRL publication header listing the schemas. This is the SHTOLO
18
+ precursor and a WG12 qualification/provenance artifact.
19
+
20
+ ## Reference
21
+
22
+ - eeng mode `(:arm/:mim :concatenated)` — `kernel/engine.lisp` mode
23
+ table, `plugins/p11/top-level.lisp` (concatenated handling +
24
+ `arm_concatenated.exp` outputs in qualify.sh), SMRL index hook at
25
+ wo-smrl-xml.
26
+ - Our graph: dependency closure via `Repository#reference_index`
27
+ (interface edges) + topological, cycle-safe ordering already
28
+ demonstrated by the item-graph work.
29
+
30
+ ## Design sketch
31
+
32
+ - `Expressir::Express::Concatenator.call(repository, root_schema)` →
33
+ model-level ordered schema list (respect eeng's ordering rules —
34
+ read their code in 02 first).
35
+ - Writer: plain schemas (no remarks) + banner comment enumerating
36
+ sources (schema name, file, copyright per SRL conventions).
37
+ - CLI: `expressir concatenate <manifest/root.exp> -o out.exp`.
38
+
39
+ ## Acceptance
40
+
41
+ - Output parses back with our parser (self round-trip).
42
+ - Diff vs eeng `arm_concatenated.exp`/`mim_concatenated.exp` for the
43
+ 03 golden set: schema set + order identical (formatting differences
44
+ documented, ideally zero after 08).
@@ -0,0 +1,53 @@
1
+ # 05 — SHTOLO longform flatten (expressir#32) — the core port
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ Port eeng's flatten (Annex G) into expressir: convert the STEPmod
8
+ multi-schema web into ONE ISO 10303-11:1994 longform schema — no
9
+ interfaces, no name clashes, interface visibility/instantiability
10
+ preserved as rules, pruned unreachable declarations.
11
+
12
+ ## Sources to port
13
+
14
+ - **Spec**: `ag-single-schema.adoc` (see 01's rule ids).
15
+ - **eeng**: `run-op (:flat)` + `print-flatten`
16
+ (`plugins/p11/top-level.lisp:847`), writer `plugins/p11/wo-flat.lisp`
17
+ (373 lines; note: eeng's flat output keeps structure and lowercases
18
+ identifiers — verify how much of Annex G eeng actually implements
19
+ before treating it as gospel; where eeng and the standard disagree,
20
+ the standard wins and the difference goes into 02's matrix).
21
+ - **Model surgery**: `add-declaration.lisp`, `remove-declaration.lisp`,
22
+ `copy-object.lisp`, `cleanup-interface.lisp`.
23
+
24
+ ## Design sketch
25
+
26
+ 1. Model-level `Expressir::Express::Flattener` operating on the
27
+ resolved repository (compiled set warm model): build the artifact
28
+ schema per Annex G — primary population (per interfaced item:
29
+ visibility/instantiability rules + generated function), secondary
30
+ population, name munging (clash policy), prune pass (rules whose
31
+ parameters are not all visible; unreachable subtype branches),
32
+ total_over → rules, then the 1994-construct rewrite.
33
+ 2. Writer: reuse the formatter with a "flat/1994" encoder profile
34
+ (no interfaces section; artifact rules emitted per Annex G).
35
+ 3. Validation gates:
36
+ - Annex G rule fixtures from 01 (each rule exercised).
37
+ - Differential: flatten output vs eeng `.flat` over the 03 golden
38
+ corpus; divergences classified standard-vs-eeng.
39
+ - Output parses as 1994 (no edition-2-only constructs — the
40
+ grammar-level edition profile check).
41
+ 4. SMRL-scale run: all 132 SRL resources + module arm/mim set; memory
42
+ via the compiled-set warm model.
43
+
44
+ ## Acceptance
45
+
46
+ - All Annex G fixtures green; SMRL corpus flatten completes with zero
47
+ unexplained diffs vs the 1994 profile.
48
+ - `expressir shtolo <manifest> -o longform.exp` ships.
49
+
50
+ ## Tests
51
+
52
+ bug39's shtolo old-vs-new outputs (see 11) are an additional
53
+ differential: eeng shtolo vs stepcode exppp vs us.
@@ -0,0 +1,47 @@
1
+ # 06 — Interface loading/resolution parity with eeng scheduling
2
+
3
+ **Status: SHIPPED (2026-09-21) — the resolution-side fix.**
4
+ `Schema#interfaced_items` is now repository-aware (foreign schemas
5
+ found through the parent chain into the enclosing repository) and
6
+ transitively USE-aware (items USEd by the foreign schema are visible,
7
+ unfiltered per the implicit-interfacing rule, cycle-guarded by a
8
+ visited-schema set). Probe results before/after: direct cross-file
9
+ item ref resolved; transitive-USE item resolved; interface cycle
10
+ terminates. Spec: `interface_visibility_spec.rb` (3 examples);
11
+ express suite 321/0. Remaining: unresolved-resource diagnostics and
12
+ USE-vs-REFERENCE error severity (eeng hard-errors; we warn) — folded
13
+ into 07's checker.
14
+
15
+ ## Goal
16
+
17
+ Match eeng's multi-schema load semantics: which declarations are
18
+ visible where, transitive USE FROM (implicit interfacing), rename
19
+ (AS) handling, and error cases ("Resource '~A' not found").
20
+
21
+ ## Differences already known
22
+
23
+ - eeng `resolve-interface.lisp`: USE FROM resolves **only**
24
+ entity+type; REFERENCE FROM resolves constant/entity/function/
25
+ procedure/type; unresolved resource = hard error. Our resolver
26
+ stamps base_path but never errors on unresolved interfaces.
27
+ - eeng runs interface **scheduling** (schedule-interfaces.lisp) so a
28
+ USE FROM can pull schemas already loaded in the session
29
+ (schemata/schemata1/schemata2) — closest to our repository + graph.
30
+ - Implicit interfacing (11-interface_specification.adoc): items
31
+ visible through USE FROM chains; our `interfaced_items` is
32
+ single-hop — verify transitive semantics.
33
+
34
+ ## Steps
35
+
36
+ 1. From 02's matrix, list each semantic difference with a fixture
37
+ (rename chains, transitively used items, interface cycles,
38
+ missing resource).
39
+ 2. Fix expressir resolution where we are wrong (spec wins), or
40
+ document deliberate divergence.
41
+ 3. Add unresolved-interface reporting (warning set) — SHTOLO's prune
42
+ stage consumes it.
43
+
44
+ ## Acceptance
45
+
46
+ Fixture suite covering rename/transitive/cycle/missing passes on both
47
+ paths (Ruby parser + core path byte-parity preserved).
@@ -0,0 +1,35 @@
1
+ # 07 — Port eeng semantic checks (kernel/check.lisp)
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ A `check` operation in expressir that walks a schema/repository and
8
+ reports the same diagnostics eeng's check-p11 passes produce — the
9
+ validation half of the SHTOLO mission (inputs must be sound before
10
+ flattening).
11
+
12
+ ## Source catalog (check.lisp, 835 lines)
13
+
14
+ Per-node `check-p11` methods: schema, use-from/reference-from,
15
+ constant, local, entity (explicit/derive/inverse attributes),
16
+ function/procedure/rule parameters, subtype_constraint, type, plus
17
+ expression/statement checks. Also `check-notes.lisp` (note
18
+ collection) and `compare.lisp` (schema comparison — two loaded
19
+ sessions).
20
+
21
+ ## Design
22
+
23
+ - `Expressir::Express::Checker` modeled on our visitor infra; each
24
+ eeng check becomes one rule with the eeng note id preserved for
25
+ cross-referencing oracle output.
26
+ - Wire into `Repository#validate` (RepositoryValidator today is
27
+ interface-level only).
28
+ - Run order: checks → report (eeng note ids + our explanation) →
29
+ nonzero exit on error-class notes (eeng error severity model).
30
+
31
+ ## Acceptance
32
+
33
+ Golden-diff check reports vs eeng for the 03 corpus subset; any
34
+ divergent verdict justified against Part 11 clause text
35
+ (`~/src/mn/iso-10303-11/sources/sections/`).
@@ -0,0 +1,27 @@
1
+ # 08 — Pretty-printer parity gate (eeng wo-pretty)
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ qualify.sh's core self-check, adopted for us: `.exp` → pretty `.exp`
8
+ → re-parse → identical model; plus diff vs eeng's `-pretty.exp` over
9
+ the golden corpus so SHTOLO outputs (04/05) can target eeng-stable
10
+ formatting.
11
+
12
+ ## Steps
13
+
14
+ 1. Read `plugins/p11/wo-pretty.lisp` encoder (spacing, casing,
15
+ remark policy, schema ordering) → document deltas vs our
16
+ `Formatter` (clean mode).
17
+ 2. Add `parser → formatter → parser` identity spec across the SMRL
18
+ corpus (model-level to_hash equality, not bytes, first; byte mode
19
+ only where eeng parity is wanted).
20
+ 3. Byte-diff our pretty vs eeng pretty on the 03 corpus; decide
21
+ adopt-eeng-format vs keep-ours (default: keep ours for rendering,
22
+ eeng profile as an encoder option for SHTOLO artifacts).
23
+
24
+ ## Acceptance
25
+
26
+ Corpus-wide round-trip identity green; eeng-profile diffs either zero
27
+ or explained line-by-line.
@@ -0,0 +1,22 @@
1
+ # 09 — SMRL index XML + declaration listing (wo-list, wo-smrl-xml)
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ The SRL publication byproducts eeng generates: declaration listings
8
+ (`-list.txt`) and the SMRL index XML for longform/concatenated files
9
+ (`<concatenated_express_file_content_list>`), emitted from the same
10
+ model that powers 04/05.
11
+
12
+ ## Sources
13
+
14
+ `plugins/p11/wo-list.lisp`, `wo-smrl-xml.lisp` (element names:
15
+ concatenated_express_file_content_list, per-schema content entries),
16
+ top-level.lisp:748-793 (when the index is generated: XML output +
17
+ longform/concatenated modes).
18
+
19
+ ## Acceptance
20
+
21
+ Index/list output for the 03 golden set structurally identical
22
+ (element-for-element) to eeng's; wired into the same CLI as 04.
@@ -0,0 +1,21 @@
1
+ # 10 — Interface dependency dot graph (kernel/dot-graph.lisp)
2
+
3
+ **Status: NOT STARTED**
4
+
5
+ ## Goal
6
+
7
+ Emit GraphViz dot for schema interface dependencies exactly like eeng
8
+ (qualify.sh "Generate Dot File (interface)"), from our compiled
9
+ reference graph (already computes interface edges + closures over the
10
+ full SMRL).
11
+
12
+ ## Notes
13
+
14
+ eeng's dot generation honors the concatenated mode (root-schema
15
+ subgraph); replicate node/edge/styling choices so WG12 visual
16
+ diffing stays stable. Trivial once 02 documents their exact output
17
+ shape — deliberately last in the queue.
18
+
19
+ ## Acceptance
20
+
21
+ Byte-comparable dot output vs eeng for arm/mim of the golden modules.