-
Notifications
You must be signed in to change notification settings - Fork 0
feat(ahbg): close construction (UCNS authority) + pass-5 release assets #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:width="108dp" | ||
| android:height="108dp" | ||
| android:viewportWidth="108" | ||
| android:viewportHeight="108"> | ||
| <path | ||
| android:fillColor="#E8E6F0" | ||
| android:pathData="M54,30 A24,24 0 1,1 54,78 A24,24 0 1,1 54,30" /> | ||
| <path | ||
| android:fillColor="#2F3154" | ||
| android:pathData="M54,42 A12,12 0 1,1 54,66 A12,12 0 1,1 54,42" /> | ||
| <path | ||
| android:fillColor="#E8E6F0" | ||
| android:pathData="M54,18 A6,6 0 1,1 54,30 A6,6 0 1,1 54,18 M54,78 A6,6 0 1,1 54,90 A6,6 0 1,1 54,78 M18,54 A6,6 0 1,1 30,54 A6,6 0 1,1 18,54 M78,54 A6,6 0 1,1 90,54 A6,6 0 1,1 78,54" /> | ||
| </vector> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <background android:drawable="@color/ic_launcher_background" /> | ||
| <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||
| </adaptive-icon> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <resources> | ||
| <color name="ic_launcher_background">#10121C</color> | ||
| </resources> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <network-security-config> | ||
| <base-config cleartextTrafficPermitted="false" /> | ||
| <debug-overrides> | ||
| <trust-anchors> | ||
| <certificates src="system" /> | ||
| <certificates src="user" /> | ||
| </trust-anchors> | ||
| </debug-overrides> | ||
| <domain-config cleartextTrafficPermitted="true"> | ||
| <domain includeSubdomains="false">10.0.2.2</domain> | ||
| <domain includeSubdomains="false">localhost</domain> | ||
| <domain includeSubdomains="false">127.0.0.1</domain> | ||
| </domain-config> | ||
| </network-security-config> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| """Bind AHBG construct to the UCNS construction state. | ||
|
|
||
| UCNS now supplies the authoritative build state for the seven-band Mobius | ||
| Seed of Life (``ucns.mobius_seed_construction``). AHBG maps that state onto | ||
| its UCNS-derived tiles by ``ucns_slot`` and persists it beside the engine | ||
| field. This module adds no geometry: buildable-next is read from UCNS | ||
| structural-vesica relations only. | ||
|
|
||
| Usage guidance: | ||
| The runtime constructs the ledger automatically inside ``run_plane`` and | ||
| the HTTP bridge. Direct use is also supported:: | ||
|
|
||
| ledger = ConstructionLedger.open(field) | ||
| for tile_id in ledger.legal_build_tiles(field): | ||
| ledger, event = ledger.apply_build(field, tile_id, unit_id="A0") | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import json | ||
| import sys | ||
| from dataclasses import dataclass | ||
| from pathlib import Path | ||
| from typing import Any, Mapping | ||
|
|
||
| _UCNS = Path(__file__).resolve().parents[2] / "libs" / "ucns" / "src" | ||
| if str(_UCNS) not in sys.path: | ||
| sys.path.insert(0, str(_UCNS)) | ||
|
|
||
| from ucns.mobius_seed_construction import ( # noqa: E402 | ||
| ConstructionState, | ||
| buildable_slots, | ||
| construct, | ||
| from_built, | ||
| initial_construction_state, | ||
| ) | ||
|
|
||
| LEDGER_SCHEMA = "interdependency.ahbg.construction-ledger/1" | ||
|
|
||
|
|
||
| class ConstructionError(ValueError): | ||
| """A construct intent violates the UCNS construction boundary.""" | ||
|
|
||
|
|
||
| def _slot_for_tile(field: Any, tile_id: str) -> str: | ||
| for tile in field.snapshot()["tiles"]: | ||
| if tile["tile_id"] == tile_id: | ||
| return str(tile.get("ucns_slot") or tile["tile_id"]) | ||
| raise ConstructionError(f"unknown tile {tile_id}") | ||
|
|
||
|
|
||
| def _tile_for_slot(field: Any, slot: str) -> str: | ||
| for tile in field.snapshot()["tiles"]: | ||
| if str(tile.get("ucns_slot") or tile["tile_id"]) == slot: | ||
| return str(tile["tile_id"]) | ||
| raise ConstructionError(f"no tile for UCNS slot {slot}") | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class ConstructionLedger: | ||
| state: ConstructionState | ||
|
|
||
| @classmethod | ||
| def open(cls, field: Any) -> "ConstructionLedger": | ||
| return cls(initial_construction_state()) | ||
|
|
||
| @classmethod | ||
| def load(cls, field: Any, directory: Path) -> "ConstructionLedger": | ||
| path = directory / "construction.json" | ||
| if not path.exists(): | ||
| return cls.open(field) | ||
| raw = json.loads(path.read_text(encoding="utf-8")) | ||
| if raw.get("schema") != LEDGER_SCHEMA: | ||
| raise ConstructionError("unknown construction ledger schema") | ||
| built = [str(slot) for slot in raw.get("built", [])] | ||
| from ucns.mobius_seed import BandSlot | ||
|
|
||
| slots = [BandSlot(slot) for slot in built if slot in {item.value for item in BandSlot}] | ||
| return cls(from_built(slots)) | ||
|
Comment on lines
+75
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a ledger contains an unknown slot—for example after corruption or loading state written by a newer schema—this comprehension silently drops it and reconstructs a smaller built set. The next dump then permanently normalizes away the missing construction instead of failing closed, so validate every persisted entry and raise Useful? React with 👍 / 👎. |
||
|
|
||
| def dump(self, directory: Path) -> None: | ||
| directory.mkdir(parents=True, exist_ok=True) | ||
| (directory / "construction.json").write_text( | ||
| json.dumps( | ||
| { | ||
| "schema": LEDGER_SCHEMA, | ||
| "built": [slot.value for slot in sorted(self.state.built, key=lambda item: item.value)], | ||
| "buildable": [slot.value for slot in buildable_slots(self.state)], | ||
| }, | ||
| indent=2, | ||
| sort_keys=True, | ||
| ) | ||
| + "\n", | ||
| encoding="utf-8", | ||
| ) | ||
|
|
||
| def legal_build_tiles(self, field: Any) -> tuple[str, ...]: | ||
| slots = buildable_slots(self.state) | ||
| return tuple(_tile_for_slot(field, slot.value) for slot in slots) | ||
|
|
||
| def apply_build( | ||
| self, | ||
| field: Any, | ||
| *, | ||
| unit_id: str, | ||
| from_tile_id: str, | ||
| to_tile_id: str, | ||
| ) -> tuple["ConstructionLedger", dict[str, Any]]: | ||
| unit = field.occupants.get(unit_id) | ||
| if unit is None or unit.tile_id != from_tile_id: | ||
| raise ConstructionError(f"{unit_id} is not on {from_tile_id}") | ||
| slot = _slot_for_tile(field, to_tile_id) | ||
| from ucns.mobius_seed import BandSlot | ||
|
|
||
| band = BandSlot(slot) | ||
| try: | ||
| next_state = construct(self.state, band) | ||
| except Exception as exc: | ||
| raise ConstructionError(f"construct {slot} violates UCNS construction boundary: {exc}") from exc | ||
| event = { | ||
| "kind": "construct", | ||
| "unit_id": unit_id, | ||
| "from_tile_id": from_tile_id, | ||
| "to_tile_id": to_tile_id, | ||
| "ucns_slot": slot, | ||
| "built_count": len(next_state.built), | ||
| } | ||
| return ConstructionLedger(next_state), event | ||
|
|
||
| def as_dict(self) -> Mapping[str, Any]: | ||
| return { | ||
| "schema": LEDGER_SCHEMA, | ||
| "built": [slot.value for slot in sorted(self.state.built, key=lambda item: item.value)], | ||
| "buildable": [slot.value for slot in buildable_slots(self.state)], | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
domain-configis outsidedebug-overrides, so its cleartext exceptions apply to release builds as well as debug builds. A release assembled with a localhost or emulatorruntimeUrlcan therefore send the runtime protocol over HTTP despite the documented debug-only boundary; put these domains in a debug-specific network-security resource or manifest overlay.Useful? React with 👍 / 👎.