compmech-reference-pack 0.3.1__tar.gz

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 (25) hide show
  1. compmech_reference_pack-0.3.1/PKG-INFO +74 -0
  2. compmech_reference_pack-0.3.1/README.md +60 -0
  3. compmech_reference_pack-0.3.1/pyproject.toml +49 -0
  4. compmech_reference_pack-0.3.1/setup.cfg +4 -0
  5. compmech_reference_pack-0.3.1/src/compmech_reference_pack/__init__.py +22 -0
  6. compmech_reference_pack-0.3.1/src/compmech_reference_pack/adapters/__init__.py +15 -0
  7. compmech_reference_pack-0.3.1/src/compmech_reference_pack/adapters/mechdsl_runner.py +321 -0
  8. compmech_reference_pack-0.3.1/src/compmech_reference_pack/capabilities.py +67 -0
  9. compmech_reference_pack-0.3.1/src/compmech_reference_pack/domain_pack/domain_pack.yaml +49 -0
  10. compmech_reference_pack-0.3.1/src/compmech_reference_pack/domain_pack/source_packs/constkit.yaml +28 -0
  11. compmech_reference_pack-0.3.1/src/compmech_reference_pack/domain_pack/source_packs/mechdsl.yaml +26 -0
  12. compmech_reference_pack-0.3.1/src/compmech_reference_pack/domain_pack/source_packs/symbolic_fem_workbench.yaml +29 -0
  13. compmech_reference_pack-0.3.1/src/compmech_reference_pack/normalize.py +192 -0
  14. compmech_reference_pack-0.3.1/src/compmech_reference_pack/paths.py +30 -0
  15. compmech_reference_pack-0.3.1/src/compmech_reference_pack.egg-info/PKG-INFO +74 -0
  16. compmech_reference_pack-0.3.1/src/compmech_reference_pack.egg-info/SOURCES.txt +23 -0
  17. compmech_reference_pack-0.3.1/src/compmech_reference_pack.egg-info/dependency_links.txt +1 -0
  18. compmech_reference_pack-0.3.1/src/compmech_reference_pack.egg-info/requires.txt +9 -0
  19. compmech_reference_pack-0.3.1/src/compmech_reference_pack.egg-info/top_level.txt +1 -0
  20. compmech_reference_pack-0.3.1/tests/test_capabilities.py +43 -0
  21. compmech_reference_pack-0.3.1/tests/test_domain_pack.py +67 -0
  22. compmech_reference_pack-0.3.1/tests/test_import.py +63 -0
  23. compmech_reference_pack-0.3.1/tests/test_integration.py +128 -0
  24. compmech_reference_pack-0.3.1/tests/test_mechdsl_runner.py +193 -0
  25. compmech_reference_pack-0.3.1/tests/test_normalize.py +121 -0
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: compmech-reference-pack
3
+ Version: 0.3.1
4
+ Summary: Computational-mechanics companion adapter — bridges AKMS LSP excerpts to the MechDSL executable backend.
5
+ Requires-Python: <3.14,>=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: akms-learn
8
+ Provides-Extra: mechdsl
9
+ Requires-Dist: mechdsl-core; extra == "mechdsl"
10
+ Requires-Dist: algo2code; extra == "mechdsl"
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=9.0.2; extra == "dev"
13
+ Requires-Dist: compmech-reference-pack[mechdsl]; extra == "dev"
14
+
15
+ # compmech-reference-pack
16
+
17
+ The computational-mechanics companion adapter for
18
+ [AKMS](https://github.com/CEmM2/AKMS). It bridges `akms-learn` Learning Source
19
+ Packet excerpts to the [MechDSL](https://github.com/CEmM2/MechDSL) executable
20
+ backend, so an algorithm described in a knowledge node can be transpiled and
21
+ compiled rather than only read.
22
+
23
+ It ships the `compmech` domain pack — the descriptor and source packs that tell
24
+ `akms-learn` which companions exist and what each can do.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install compmech-reference-pack
30
+ ```
31
+
32
+ That gives you the domain pack and the adapter's declared capability surface,
33
+ and pulls in `akms-learn`. It does **not** pull in the MechDSL backend: every
34
+ `mechdsl` and `algo2code` import in this package is function-scoped, so it
35
+ installs and imports cleanly without them.
36
+
37
+ To enable the actual compile, transpile and verify path:
38
+
39
+ ```bash
40
+ pip install "compmech-reference-pack[mechdsl]"
41
+ ```
42
+
43
+ The extra exists so a downstream consumer can depend on this package without
44
+ dragging the executable backend — and transitively Taichi — into its
45
+ resolution.
46
+
47
+ ## What it provides
48
+
49
+ - **`MechDSLRunner`** — the `executable_bridge` adapter. Given an LSP excerpt
50
+ it normalises the algorithmic block, derives a safe algorithm name, and
51
+ delegates to MechDSL's `transpile_algorithm` / `compile_from_sources`.
52
+ Provenance is preserved from node to generated artefact.
53
+ - **`capabilities()`** — a declaration of what the package offers, kept
54
+ deliberately import-light and Taichi-free so a caller can ask without paying
55
+ for a backend it may not use.
56
+ - **The `compmech` domain pack** — `domain_pack.yaml` plus the source packs
57
+ under `domain_pack/source_packs/`, addressed through
58
+ `compmech_reference_pack.paths`.
59
+
60
+ ## Companion status
61
+
62
+ | Companion | Role | Status |
63
+ |---|---|---|
64
+ | `mechdsl` | executable bridge | available |
65
+ | `constkit` | concept kit | planned |
66
+ | `symbolic_fem_workbench` | pedagogical workbench | planned |
67
+
68
+ `planned` describes the adapter, not the source: the material for both planned
69
+ companions is public, in
70
+ [SOSOVSKI/Teaching-materials](https://github.com/SOSOVSKI/Teaching-materials).
71
+
72
+ ## Licence
73
+
74
+ Apache-2.0, matching AKMS.
@@ -0,0 +1,60 @@
1
+ # compmech-reference-pack
2
+
3
+ The computational-mechanics companion adapter for
4
+ [AKMS](https://github.com/CEmM2/AKMS). It bridges `akms-learn` Learning Source
5
+ Packet excerpts to the [MechDSL](https://github.com/CEmM2/MechDSL) executable
6
+ backend, so an algorithm described in a knowledge node can be transpiled and
7
+ compiled rather than only read.
8
+
9
+ It ships the `compmech` domain pack — the descriptor and source packs that tell
10
+ `akms-learn` which companions exist and what each can do.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install compmech-reference-pack
16
+ ```
17
+
18
+ That gives you the domain pack and the adapter's declared capability surface,
19
+ and pulls in `akms-learn`. It does **not** pull in the MechDSL backend: every
20
+ `mechdsl` and `algo2code` import in this package is function-scoped, so it
21
+ installs and imports cleanly without them.
22
+
23
+ To enable the actual compile, transpile and verify path:
24
+
25
+ ```bash
26
+ pip install "compmech-reference-pack[mechdsl]"
27
+ ```
28
+
29
+ The extra exists so a downstream consumer can depend on this package without
30
+ dragging the executable backend — and transitively Taichi — into its
31
+ resolution.
32
+
33
+ ## What it provides
34
+
35
+ - **`MechDSLRunner`** — the `executable_bridge` adapter. Given an LSP excerpt
36
+ it normalises the algorithmic block, derives a safe algorithm name, and
37
+ delegates to MechDSL's `transpile_algorithm` / `compile_from_sources`.
38
+ Provenance is preserved from node to generated artefact.
39
+ - **`capabilities()`** — a declaration of what the package offers, kept
40
+ deliberately import-light and Taichi-free so a caller can ask without paying
41
+ for a backend it may not use.
42
+ - **The `compmech` domain pack** — `domain_pack.yaml` plus the source packs
43
+ under `domain_pack/source_packs/`, addressed through
44
+ `compmech_reference_pack.paths`.
45
+
46
+ ## Companion status
47
+
48
+ | Companion | Role | Status |
49
+ |---|---|---|
50
+ | `mechdsl` | executable bridge | available |
51
+ | `constkit` | concept kit | planned |
52
+ | `symbolic_fem_workbench` | pedagogical workbench | planned |
53
+
54
+ `planned` describes the adapter, not the source: the material for both planned
55
+ companions is public, in
56
+ [SOSOVSKI/Teaching-materials](https://github.com/SOSOVSKI/Teaching-materials).
57
+
58
+ ## Licence
59
+
60
+ Apache-2.0, matching AKMS.
@@ -0,0 +1,49 @@
1
+ [project]
2
+ name = "compmech-reference-pack"
3
+ version = "0.3.1"
4
+ description = "Computational-mechanics companion adapter — bridges AKMS LSP excerpts to the MechDSL executable backend."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11,<3.14"
7
+ dependencies = [
8
+ "akms-learn",
9
+ ]
10
+
11
+ [project.optional-dependencies]
12
+ # The executable-build path (MechDSLRunner.build_executable / transpile /
13
+ # verify) lazily imports the MechDSL Tier-1 backend — every mechdsl/algo2code
14
+ # import in src/ is function-scoped, so the package installs and imports
15
+ # cleanly without them. They are an optional extra so a downstream consumer
16
+ # (e.g. Logic-Loom's frozen core sidecar) can resolve and install
17
+ # compmech-reference-pack WITHOUT pulling mechdsl-core/algo2code — and
18
+ # transitively Taichi — into its uv lock closure. Install the `mechdsl` extra
19
+ # to enable the actual compile/transpile/verify capability.
20
+ mechdsl = [
21
+ "mechdsl-core",
22
+ "algo2code",
23
+ ]
24
+ dev = [
25
+ "pytest>=9.0.2",
26
+ "compmech-reference-pack[mechdsl]",
27
+ ]
28
+
29
+ [build-system]
30
+ requires = ["setuptools>=68.0"]
31
+ build-backend = "setuptools.build_meta"
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["src"]
35
+
36
+ [tool.setuptools.package-data]
37
+ compmech_reference_pack = [
38
+ "domain_pack/*.yaml",
39
+ "domain_pack/source_packs/*.yaml",
40
+ ]
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ pythonpath = ["src"]
45
+ markers = [
46
+ "unit: fast unit-level tests",
47
+ "integration: cross-module/integration tests",
48
+ "slow: tests that initialise Taichi (the only Taichi-paying adapter path)",
49
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ """compmech_reference_pack — Tier-2 computational-mechanics companion adapter.
2
+
3
+ Bridges AKMS ``akms_learn`` Learning Source Packet (LSP) excerpts to the
4
+ MechDSL Tier-1 ``mechdsl.integration`` façade: it normalises human-authored
5
+ algpseudocode into algo2code-grammar-clean form, then emits executable Python
6
+ and/or compiled-solver summaries with provenance.
7
+
8
+ This package depends on **both** ``akms-learn`` and ``mechdsl-core`` (plus
9
+ ``algo2code``, MechDSL's transpiler backend). It registers the
10
+ ``executable_bridge`` adapter so ``akms_learn`` reports
11
+ ``executable_bridge_adapter = available``.
12
+
13
+ Companion-adapter pattern: MechDSL stays AKMS-unaware; this package is the only
14
+ place that knows about both sides. The public surface is populated across the
15
+ the executable-bridge tier.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ __version__ = "0.1.0"
21
+
22
+ __all__: list[str] = []
@@ -0,0 +1,15 @@
1
+ """compmech_reference_pack adapters — the executable-bridge runner (Tier 2)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from compmech_reference_pack.adapters.mechdsl_runner import (
6
+ MechDSLRunner,
7
+ adapter_registry_overrides,
8
+ available_adapter_registry,
9
+ )
10
+
11
+ __all__ = [
12
+ "MechDSLRunner",
13
+ "adapter_registry_overrides",
14
+ "available_adapter_registry",
15
+ ]
@@ -0,0 +1,321 @@
1
+ """mechdsl_runner.py — MechDSLRunner, the executable_bridge adapter.
2
+
3
+ Bridges a bounded AKMS LSP excerpt to the MechDSL Tier-1 façade
4
+ (``mechdsl.integration``) and assembles a provenance-carrying artefact dict.
5
+
6
+ Contract (the real one, NOT the spec's ``build_artifacts``)::
7
+
8
+ build_executable(excerpt: dict, *, options: dict | None = None) -> dict
9
+
10
+ Behaviour
11
+ ---------
12
+ - **Emit-only by default.** ``build_executable`` normalises the node's
13
+ ``extracted["implementation"]`` (algpseudocode) and calls Tier-1
14
+ ``transpile_algorithm``, and — when a ``% mechanics`` problem source plus an
15
+ energy ``derivation`` are present — Tier-1 ``compile_from_sources``. Both are
16
+ Taichi-free.
17
+ - **Taichi only on demand.** Tier-1 ``verify`` is called **only** when
18
+ ``options["run_verify"]`` is truthy; that is the single Taichi-paying branch.
19
+ - **Never invalidates the packet** (spec 09 §7 rule 5): a transpile/compile
20
+ failure is captured into ``warnings`` and reported as ``status="error"``
21
+ only when the caller explicitly required executable output
22
+ (``options["require_executable"]``); otherwise ``status`` stays ``"ok"``.
23
+
24
+ No-mutation invariant: this adapter never writes to any AKMS path.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import re
30
+ from typing import Any
31
+
32
+ from akms_learn.adapters.status import AdapterStatus, adapter_registry
33
+
34
+ ADAPTER_ID = "compmech.mechdsl_runner"
35
+
36
+ __all__ = [
37
+ "ADAPTER_ID",
38
+ "MechDSLRunner",
39
+ "adapter_registry_overrides",
40
+ "available_adapter_registry",
41
+ ]
42
+
43
+
44
+ def adapter_registry_overrides() -> dict[str, AdapterStatus]:
45
+ """Registry override that marks the executable bridge available."""
46
+ return {"executable_bridge_adapter": AdapterStatus.available}
47
+
48
+
49
+ def available_adapter_registry() -> dict[str, AdapterStatus]:
50
+ """Return the akms_learn adapter registry with this adapter marked available."""
51
+ return adapter_registry(adapter_registry_overrides())
52
+
53
+
54
+ def _algo_name_from_node_id(node_id: str) -> str:
55
+ """Derive a safe algo2code algorithm name from a node id."""
56
+ tail = node_id.rsplit(".", 1)[-1].rsplit("/", 1)[-1]
57
+ cleaned = re.sub(r"[^0-9A-Za-z_]", "_", tail).strip("_")
58
+ return cleaned or "algorithm"
59
+
60
+
61
+ class MechDSLRunner:
62
+ """ExecutableBridgeAdapter implementation backed by MechDSL Tier-1.
63
+
64
+ Satisfies ``akms_learn.adapters.protocols.ExecutableBridgeAdapter`` via
65
+ structural subtyping (the protocol is ``@runtime_checkable``).
66
+ """
67
+
68
+ adapter_id = ADAPTER_ID
69
+
70
+ # -- protocol surface ---------------------------------------------------
71
+
72
+ def build_executable(
73
+ self, excerpt: dict[str, Any], *, options: dict[str, Any] | None = None
74
+ ) -> dict[str, Any]:
75
+ """Build an executable artefact from a bounded LSP excerpt.
76
+
77
+ Returns the 8-key contract dict ``{adapter, status, emitted_source,
78
+ transpiled, normalized_input, provenance, vv_plan, warnings}``. When
79
+ ``options["run_verify"]`` is truthy a 9th key ``verification`` (the
80
+ Tier-1 ``verify`` result) is added — that opt-in path is the only one
81
+ that pays the Taichi cost. Never raises on a malformed excerpt.
82
+ """
83
+ options = options or {}
84
+ run_verify = bool(options.get("run_verify", False))
85
+ require_executable = bool(options.get("require_executable", False))
86
+
87
+ node = self._select_node(excerpt)
88
+ node_id = str(node.get("node_id") or excerpt.get("node_id") or "<unknown>")
89
+ extracted = node.get("extracted")
90
+ if not isinstance(extracted, dict):
91
+ extracted = {}
92
+ implementation = extracted.get("implementation")
93
+ derivation = extracted.get("derivation")
94
+ problem = extracted.get("problem")
95
+
96
+ warnings: list[str] = []
97
+ status = "ok"
98
+ normalized_input: str | None = None
99
+ transpiled: dict[str, Any] | None = None
100
+ emitted_source: str | None = None
101
+
102
+ # --- implementation -> normalize -> Tier-1 transpile (Taichi-free) ---
103
+ if implementation:
104
+ from compmech_reference_pack.normalize import normalize
105
+
106
+ norm = normalize(
107
+ implementation, algorithm_name=_algo_name_from_node_id(node_id)
108
+ )
109
+ normalized_input = norm.normalized
110
+ warnings.extend(norm.warnings)
111
+ if norm.algorithmic_block_found:
112
+ try:
113
+ from mechdsl.integration import transpile_algorithm
114
+ except ImportError as exc:
115
+ warnings.append(
116
+ "MechDSL backend unavailable; install "
117
+ '"compmech-reference-pack[mechdsl]" '
118
+ f"({type(exc).__name__}: {exc})"
119
+ )
120
+ if require_executable:
121
+ status = "error"
122
+ else:
123
+ try:
124
+ transpiled = transpile_algorithm(
125
+ norm.normalized, backend="taichi"
126
+ )
127
+ if not transpiled.get("valid_python", False):
128
+ warnings.append(
129
+ "transpiled code did not compile as valid Python"
130
+ )
131
+ if require_executable:
132
+ status = "error"
133
+ except Exception as exc:
134
+ warnings.append(
135
+ f"transpile failed: {type(exc).__name__}: {exc}"
136
+ )
137
+ if require_executable:
138
+ status = "error"
139
+
140
+ # --- derivation (+ problem) -> Tier-1 compile (Taichi-free) ----------
141
+ if derivation and problem:
142
+ try:
143
+ from mechdsl.integration import compile_from_sources
144
+ except ImportError as exc:
145
+ warnings.append(
146
+ "MechDSL backend unavailable; install "
147
+ '"compmech-reference-pack[mechdsl]" '
148
+ f"({type(exc).__name__}: {exc})"
149
+ )
150
+ if require_executable:
151
+ status = "error"
152
+ else:
153
+ try:
154
+ compiled = compile_from_sources(
155
+ problem_source=problem, energy_source=derivation
156
+ )
157
+ emitted_source = compiled["emitted_source"]
158
+ except Exception as exc:
159
+ warnings.append(
160
+ f"compile_from_sources failed: {type(exc).__name__}: {exc}"
161
+ )
162
+ if require_executable:
163
+ status = "error"
164
+ elif derivation and not problem:
165
+ warnings.append(
166
+ "node carries a derivation but no '% mechanics' problem source; "
167
+ "skipping compile_from_sources (provide extracted['problem'] to compile)"
168
+ )
169
+
170
+ if implementation is None and derivation is None:
171
+ status = "error"
172
+ warnings.append(
173
+ f"excerpt node {node_id!r} carries neither an implementation nor a "
174
+ "derivation; nothing to build"
175
+ )
176
+
177
+ result: dict[str, Any] = {
178
+ "adapter": ADAPTER_ID,
179
+ "status": status,
180
+ "emitted_source": emitted_source,
181
+ "transpiled": transpiled,
182
+ "normalized_input": normalized_input,
183
+ "provenance": {
184
+ node_id: {
185
+ "sections": self._sections(node),
186
+ "references": self._references(node_id, node, excerpt),
187
+ }
188
+ },
189
+ "vv_plan": self._vv_plan(node_id, node, excerpt, options),
190
+ "warnings": warnings,
191
+ }
192
+
193
+ # --- the only Taichi-paying branch ----------------------------------
194
+ if run_verify:
195
+ result["verification"] = self._run_verify(options, warnings)
196
+
197
+ return result
198
+
199
+ # -- extra surface (per plan: status() / can_handle()) ------------------
200
+
201
+ def status(self) -> dict[str, Any]:
202
+ """Lightweight, Taichi-free availability descriptor for status routes."""
203
+ return {
204
+ "adapter": ADAPTER_ID,
205
+ "available": True,
206
+ "companion_role": "executable_bridge",
207
+ "taichi_required_for": ["verify"],
208
+ }
209
+
210
+ def can_handle(self, excerpt: dict[str, Any]) -> bool:
211
+ """True when the excerpt has a node carrying implementation/derivation.
212
+
213
+ Total: returns ``False`` (never raises) for any malformed excerpt
214
+ shape — missing ``nodes``, non-dict nodes, non-dict ``extracted``.
215
+ """
216
+ node = self._select_node(excerpt)
217
+ extracted = node.get("extracted")
218
+ if not isinstance(extracted, dict):
219
+ return False
220
+ return bool(extracted.get("implementation") or extracted.get("derivation"))
221
+
222
+ # -- internals ----------------------------------------------------------
223
+
224
+ @staticmethod
225
+ def _select_node(excerpt: dict[str, Any]) -> dict[str, Any]:
226
+ """Pick the node dict to build from.
227
+
228
+ Accepts a node-shaped excerpt directly, a ``{"nodes": [...]}`` excerpt
229
+ (first node carrying implementation/derivation, else the first node),
230
+ or any dict (treated as the node).
231
+ """
232
+ nodes = excerpt.get("nodes")
233
+ if isinstance(nodes, list):
234
+ dict_nodes = [n for n in nodes if isinstance(n, dict)]
235
+ for node in dict_nodes:
236
+ extracted = node.get("extracted")
237
+ if isinstance(extracted, dict) and (
238
+ extracted.get("implementation") or extracted.get("derivation")
239
+ ):
240
+ return node
241
+ # No build-bearing node — return the first dict node, or {} so
242
+ # callers never touch a non-dict (None, str, …).
243
+ return dict_nodes[0] if dict_nodes else {}
244
+ return excerpt
245
+
246
+ @staticmethod
247
+ def _sections(node: dict[str, Any]) -> Any:
248
+ return node.get("included_sections") or node.get("sections") or []
249
+
250
+ @staticmethod
251
+ def _references(
252
+ node_id: str, node: dict[str, Any], excerpt: dict[str, Any]
253
+ ) -> list[Any]:
254
+ """Collect references attributable to this node.
255
+
256
+ Prefers node-local references; otherwise filters packet-level
257
+ references by ``source_node_ids`` membership (falling back to all).
258
+ """
259
+ node_refs = node.get("references")
260
+ if isinstance(node_refs, list) and node_refs:
261
+ return list(node_refs)
262
+
263
+ packet_refs = excerpt.get("references")
264
+ if not isinstance(packet_refs, list):
265
+ return []
266
+ scoped = [
267
+ ref
268
+ for ref in packet_refs
269
+ if isinstance(ref, dict) and node_id in (ref.get("source_node_ids") or [])
270
+ ]
271
+ return scoped or list(packet_refs)
272
+
273
+ @classmethod
274
+ def _vv_plan(
275
+ cls,
276
+ node_id: str,
277
+ node: dict[str, Any],
278
+ excerpt: dict[str, Any],
279
+ options: dict[str, Any],
280
+ ) -> dict[str, Any]:
281
+ """Assemble a verification-and-validation plan {benchmark, citation}.
282
+
283
+ The citation is drawn from the same node-scoped reference list used for
284
+ provenance (via :meth:`_references`), so the two never disagree.
285
+ """
286
+ extracted = node.get("extracted")
287
+ if not isinstance(extracted, dict):
288
+ extracted = {}
289
+ benchmark = (
290
+ options.get("benchmark")
291
+ or extracted.get("benchmark")
292
+ or excerpt.get("benchmark")
293
+ )
294
+ citation: Any = None
295
+ for ref in cls._references(node_id, node, excerpt):
296
+ if isinstance(ref, dict):
297
+ citation = ref.get("citation") or ref.get("title")
298
+ if citation:
299
+ break
300
+ return {"benchmark": benchmark, "citation": citation}
301
+
302
+ @staticmethod
303
+ def _run_verify(options: dict[str, Any], warnings: list[str]) -> dict[str, Any]:
304
+ """Run the single Taichi-paying Tier-1 verify branch."""
305
+ kind = options.get("verify_kind", "patch_test")
306
+ params = options.get("verify_params", {})
307
+
308
+ try:
309
+ from mechdsl.integration import verify
310
+
311
+ return verify(kind, params)
312
+ except ImportError as exc:
313
+ warnings.append(
314
+ "MechDSL backend unavailable; install "
315
+ '"compmech-reference-pack[mechdsl]" '
316
+ f"({type(exc).__name__}: {exc})"
317
+ )
318
+ return {"kind": kind, "passed": False, "details": {"error": str(exc)}}
319
+ except Exception as exc:
320
+ warnings.append(f"verify failed: {type(exc).__name__}: {exc}")
321
+ return {"kind": kind, "passed": False, "details": {"error": str(exc)}}
@@ -0,0 +1,67 @@
1
+ """Capability declarations for compmech_reference_pack.
2
+
3
+ `CEmM2/Logic-Loom <https://github.com/CEmM2/Logic-Loom>`_ imports this package
4
+ from its ``GET /api/mechdsl/status`` route and reads the capability surface to
5
+ decide whether to expose the MechDSL gate.
6
+ This module is deliberately import-light and **Taichi-free**: it declares
7
+ *what* the package offers; it never runs a solve or initialises Taichi.
8
+
9
+ Two capabilities are declared:
10
+
11
+ - ``executable_bridge_adapter`` — the package registers ``MechDSLRunner`` as
12
+ the ``executable_bridge`` adapter (``akms_learn`` reports it available).
13
+ - ``code_mirror_provenance`` — ``build_executable`` attaches per-node
14
+ provenance (source sections + references) to every emitted artefact.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from compmech_reference_pack import __version__
20
+
21
+ __all__ = [
22
+ "ADAPTER_ID",
23
+ "CODE_MIRROR_PROVENANCE",
24
+ "EXECUTABLE_BRIDGE_ADAPTER",
25
+ "capabilities",
26
+ ]
27
+
28
+ #: Stable id of the executable-bridge adapter this package registers.
29
+ ADAPTER_ID = "compmech.mechdsl_runner"
30
+
31
+ #: Capability keys (also the akms_learn adapter-registry capability names).
32
+ EXECUTABLE_BRIDGE_ADAPTER = "executable_bridge_adapter"
33
+ CODE_MIRROR_PROVENANCE = "code_mirror_provenance"
34
+
35
+
36
+ def capabilities() -> dict:
37
+ """Return the machine-readable capability surface for status discovery.
38
+
39
+ Shape consumed by Logic-Loom's status route::
40
+
41
+ {package, version, domain_pack, adapter_id, capabilities: {...}}
42
+
43
+ The dict is JSON-serialisable and contains no runtime objects.
44
+ """
45
+ return {
46
+ "package": "compmech_reference_pack",
47
+ "version": __version__,
48
+ "domain_pack": "compmech.reference",
49
+ "adapter_id": ADAPTER_ID,
50
+ "capabilities": {
51
+ EXECUTABLE_BRIDGE_ADAPTER: {
52
+ "available": True,
53
+ "adapter_id": ADAPTER_ID,
54
+ "companion_role": "executable_bridge",
55
+ "actions": ["emit", "transpile", "verify"],
56
+ # Mirrors the Tier-1 contract: only ``verify`` pays Taichi.
57
+ "taichi_required_for": ["verify"],
58
+ },
59
+ CODE_MIRROR_PROVENANCE: {
60
+ "available": True,
61
+ "source_pack_id": "compmech.mechdsl",
62
+ "repo": "CEmM2/MechDSL",
63
+ # build_executable attaches {node_id: {sections, references}}.
64
+ "provenance_keys": ["sections", "references"],
65
+ },
66
+ },
67
+ }
@@ -0,0 +1,49 @@
1
+ domain_pack_schema: akms-learn-domain-pack/v1
2
+ domain_id: compmech
3
+ pack_id: compmech.reference
4
+ name: Computational Mechanics Reference Pack
5
+ version: "0.1.0"
6
+ status: reference
7
+ summary: >-
8
+ Reference computational-mechanics domain pack for AKMS Learn. Promoted from
9
+ the AKMS_learn test fixture by compmech_reference_pack (Tier-2 executable
10
+ bridge); the MechDSL companion is now an available executable runner.
11
+ compatibility:
12
+ akms_learn_schema_min: learn/v0.1
13
+ akms_learn_schema_max: learn/v0.1
14
+ roots:
15
+ nodes: nodes/compmech
16
+ code_mirror: code-mirror/compmech
17
+ examples: learning_examples/compmech
18
+ bundles: lesson_bundles/compmech
19
+ capabilities:
20
+ static_markdown: true
21
+ static_notebook: true
22
+ executable_notebook: false
23
+ external_runner: true
24
+ code_mirror: true
25
+ # `constkit` and `symbolic_fem_workbench` stay `planned`: their adapters are
26
+ # not written. Their source is public — both live under
27
+ # https://github.com/SOSOVSKI/Teaching-materials — so `planned` here describes
28
+ # the adapter, not the availability of the material.
29
+ companion_roles:
30
+ - id: constkit
31
+ package_name: compmech.constkit
32
+ runtime_hint: optional
33
+ capability_status: planned
34
+ - id: symbolic_fem_workbench
35
+ package_name: compmech.symbolic_fem_workbench
36
+ runtime_hint: optional
37
+ capability_status: planned
38
+ - id: mechdsl
39
+ package_name: compmech.mechdsl
40
+ runtime_hint: required
41
+ capability_status: available
42
+ source_packs:
43
+ - source_packs/constkit.yaml
44
+ - source_packs/symbolic_fem_workbench.yaml
45
+ - source_packs/mechdsl.yaml
46
+ provenance:
47
+ source_repos: []
48
+ generated_vault_ref: null
49
+ zotero_collection_refs: []