From 4bb56be202c0c559416ffcfc0be3e3c781b57423 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 00:28:24 -0700 Subject: [PATCH 01/25] feat(english): build expanded Unicode public gonol and full-corpus ordinal construction --- .../workflows/english-ordinal-affixiation.yml | 157 ++++++ .../docs/ordinal-construction.md | 107 ++++ .../docs/ordinal-work-graph.json | 43 ++ .../english_gonol/ordinal_construct.py | 502 ++++++++++++++++++ .../tests/test_ordinal_construct.py | 233 ++++++++ 5 files changed, 1042 insertions(+) create mode 100644 .github/workflows/english-ordinal-affixiation.yml create mode 100644 research/english-gonol/docs/ordinal-construction.md create mode 100644 research/english-gonol/docs/ordinal-work-graph.json create mode 100644 research/english-gonol/english_gonol/ordinal_construct.py create mode 100644 research/english-gonol/tests/test_ordinal_construct.py diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml new file mode 100644 index 0000000..f4e2a1a --- /dev/null +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -0,0 +1,157 @@ +name: English ordinal affixiation +on: + pull_request: + paths: + - 'research/english-gonol/english_gonol/ordinal_construct.py' + - 'research/english-gonol/tests/test_ordinal_construct.py' + - 'research/english-gonol/docs/ordinal-*' + - '.github/workflows/english-ordinal-affixiation.yml' +permissions: + contents: read +defaults: + run: + shell: bash +jobs: + full-corpus: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: The-Interdependency/ucns + ref: a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb + path: _inputs/ucns + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: The-Interdependency/ucns + ref: 4f863ad37096b7baab8f62820ad5cb937b62a3a7 + path: _inputs/admission-carrier + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: globalwordnet/english-wordnet + ref: dc343f2683279ecbb13fab4e2fd778d7b162d287 + path: _inputs/oewn + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: The-Interdependency/skill-lib + ref: e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128 + path: _inputs/skill-lib + persist-credentials: false + sparse-checkout: | + wdll + gonol-build + msdmd + meta-module-build + interdependent-work-graph + tools/skill_usage.py + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 + with: + python-version: '3.12.14' + - name: Preflight resources and install exact build dependencies + run: | + python - <<'PY' + import json, pathlib, platform, shutil, sqlite3 + free = shutil.disk_usage('.').free + # Source, two verified SQLite bundles, dependencies and retained evidence. + assert free >= 4 * 1024**3, '4 GiB working space required before full build' + print(json.dumps({'python':platform.python_version(),'sqlite':sqlite3.sqlite_version,'free_bytes':free})) + PY + python -m pip install uv==0.11.18 PyYAML==6.0.2 + uv sync --project _inputs/ucns --locked --python python --extra test + uv pip install --python _inputs/ucns/.venv/bin/python PyYAML==6.0.2 + - name: Verify exact participant graph and unchanged source reader + env: + PYTHONPATH: research/english-gonol + run: | + git fetch --no-tags --depth=1 origin e3eb83764355b4b760a79323cda6a6d75c3a501a + _inputs/ucns/.venv/bin/python - <<'PY' + import hashlib,json,pathlib,subprocess + from english_gonol.structural_construct import IMPLEMENTATION_FILES + graph=json.loads(pathlib.Path('research/english-gonol/docs/ordinal-work-graph.json').read_text()) + body={k:graph[k] for k in ('repositories','boundaries')} + assert hashlib.sha256(json.dumps(body,sort_keys=True,separators=(',',':')).encode()).hexdigest()==graph['work_graph_sha256'] + roots={'The-Interdependency/ucns':'_inputs/ucns','globalwordnet/english-wordnet':'_inputs/oewn','The-Interdependency/skill-lib':'_inputs/skill-lib'} + for item in graph['repositories']: + if item['repository'] in roots: + assert subprocess.check_output(['git','-C',roots[item['repository']],'rev-parse','HEAD'],text=True).strip()==item['commit'] + base=next(r['commit'] for r in graph['repositories'] if r['repository']=='The-Interdependency/stack') + for name in IMPLEMENTATION_FILES: + path='research/english-gonol/english_gonol/'+name + assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',base+':'+path]),path + PY + - name: Acquire declared Unicode release and license + run: | + mkdir -p _inputs/ucd _evidence + for name in UnicodeData.txt DerivedCoreProperties.txt ReadMe.txt; do + curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ + "https://www.unicode.org/Public/18.0.0/ucd/$name" -o "_inputs/ucd/$name" + done + curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ + https://www.unicode.org/license.txt -o _inputs/ucd/LICENSE-Unicode.txt + sha256sum _inputs/ucd/* | tee _evidence/unicode-acquisition.sha256 + git rev-parse HEAD > _evidence/stack-head.txt + git -C _inputs/ucns rev-parse HEAD > _evidence/ucns-head.txt + git -C _inputs/oewn rev-parse HEAD > _evidence/corpus-head.txt + - name: Unit and cross-repository geometry tests + env: + PYTHONPATH: research/english-gonol + run: | + _inputs/ucns/.venv/bin/python -m pytest -q \ + _inputs/ucns/tests/test_ordinal_affixiation.py \ + research/english-gonol/tests/test_ordinal_construct.py \ + | tee _evidence/tests.txt + - name: Build complete source admission then the replacement geometry + env: + PYTHONPATH: research/english-gonol + run: | + /usr/bin/time -v _inputs/ucns/.venv/bin/python -m english_gonol.structural_construct build \ + --source-root _inputs/oewn/src/yaml \ + --ucns-source-root _inputs/admission-carrier \ + --out-dir _admission 2> _evidence/admission-resources.txt + /usr/bin/time -v _inputs/ucns/.venv/bin/python -m english_gonol.ordinal_construct build \ + _admission _inputs/ucd _constructed \ + 2> _evidence/geometry-resources.txt | tee _evidence/full-verification.json + mkdir -p _constructed/licenses + cp _inputs/oewn/LICENSE.md _constructed/licenses/OEWN-LICENSE.md + cp _inputs/oewn/README.md _constructed/licenses/OEWN-README.md + cp _inputs/ucd/LICENSE-Unicode.txt _constructed/licenses/ + cp _inputs/ucd/ReadMe.txt _constructed/licenses/Unicode-ReadMe.txt + cp research/english-gonol/docs/ordinal-work-graph.json _constructed/ + cp _constructed/public-gonol.json _constructed/manifest.json _constructed/verification.json _evidence/ + python - <<'PY' + import json,pathlib + p=json.loads(pathlib.Path('_constructed/public-gonol.json').read_text()) + n=len(p['identities']) + lines=['index\tcodepoint\tscalar_json\tangle_turns'] + lines += [f'{i}\tU+{ord(c):04X}\t{json.dumps(c,ensure_ascii=False)}\t{i}/{n}' for i,c in enumerate(p['identities'])] + pathlib.Path('_evidence/public-gonol.tsv').write_text('\n'.join(lines)+'\n') + print(json.dumps(p['admission_counts'],indent=2)) + PY + - name: Exercise source-exact text query on the completed field + env: + PYTHONPATH: research/english-gonol + run: | + _inputs/ucns/.venv/bin/python -m english_gonol.ordinal_construct query \ + _constructed 'the geometry' > _evidence/query.json + - name: Retain evidence even after a deterministic failure + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + with: + name: english-ordinal-evidence + path: _evidence/ + if-no-files-found: error + retention-days: 30 + - name: Retain the actual completed construction, including constitutive source + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + with: + name: english-ordinal-construction + path: _constructed/ + if-no-files-found: error + retention-days: 30 diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md new file mode 100644 index 0000000..21b9a25 --- /dev/null +++ b/research/english-gonol/docs/ordinal-construction.md @@ -0,0 +1,107 @@ +# English ordinal construction — replacement profile + +Operator request: radial distance is repeated halving by occurrence ordinal; +angle is defined by the newly expanded public gonol. This profile constructs +that law instead of reinterpreting the previous orthogonal or overlap metrics. + +## Public gonol + +Admission is the exact union of all scalars admitted by the complete pinned +OEWN structural field, all inherited Public Gonol scalars, Unicode 18.0.0 +numeric categories Nd/Nl/No, its derived Math property, and the explicit logical +supplement in `ordinal_construct.py`. No normalization, case folding, surrogate +positions, prime padding, missing-scalar fallback, or inferred operator meaning. + +The new layout keeps SPACE first and the inherited 157 anchors in their +relative cyclic order. Additional scalars, sorted by code point, are distributed +as evenly as possible after those anchors. Every resulting position i has the +exact angle i/N turns. The actual N comes from the union, not an estimated count. +This balanced insertion is an explicit engineering profile choice. It is not +claimed to recover a hidden algorithm behind the old fixed arrangement. + +Closed words use a second explicit carrier ordered lexicographically by their +sequences of new public-gonol indexes. That ordering is likewise a declared +profile choice, not a semantic ranking or a last-glyph angle. The UCNS constructor +accepts any explicitly declared carrier for further recursive scales. + +## Geometry and recovery + +For zero-based occurrence i among n participants, radius = R/2**(n-i). +The newest participant is at R/2; an append halves previous radii without +changing their carrier angles. Each closed word retains its full ordered glyph +interior. A higher construction contains references to those actual closed +interiors, with repeated occurrences, whitespace, punctuation and original +source relations intact. + +The initial equidistant field and the angular placement are distinct stages. +Arbitrary circular placement is not an isometry of a high-dimensional simplex. +SPACE's scalar angle is zero; the local frame center is the radial reference. +A SPACE occurrence is not silently placed at radius zero or discarded. + +## Artifact + +`build` creates a new directory only: + +- `admission/`: exact verified corpus, raw source evidence, ordered words, + components, definition origins and provenance. This is constitutive material, + not an optional cache. Its old carrier positions are historical admission + metadata and never supply the replacement's angles. +- `public-gonol.json`, `word-carrier.json`: complete exact angular registries. +- `geometry.db`: every closed word/source frame and its ordinal placements, + linked to the retained interiors and source records. +- `ucd/`: the exact property input bytes and manifest-bound hashes. +- `manifest.json`, `verification.json`: new profile identity and independent + all-placement replay; neither is a substitute for the construction itself. + +The hosted workflow also retains source licenses, an exact angular TSV, query +output and resource receipts. It writes no repository files and does not merge. +Old structural receipts are never presented as receipts for this geometry. + +## Execute + +Use the exact UCNS commit in `ordinal-work-graph.json`. Install its locked test +extra and PyYAML 6.0.2. The existing structural parser remains separately pinned; +expanding the public scalar registry does not silently change its segmentation. + +```bash +export PYTHONPATH=research/english-gonol +python -m english_gonol.structural_construct build \ + --source-root /path/to/pinned-oewn/src/yaml \ + --ucns-source-root /path/to/pinned-admission-carrier \ + --out-dir /path/to/new-admission +python -m english_gonol.ordinal_construct build \ + /path/to/new-admission /path/to/unicode-18-ucd /path/to/new-geometry +python -m english_gonol.ordinal_construct verify /path/to/new-geometry +python -m english_gonol.ordinal_construct query /path/to/new-geometry 'the geometry' +``` + +Full corpus means the source verifier has replayed the exact 73-file OEWN tree +and every source record. The new independent checker additionally recomputes all +local exponents, angles, references and closure receipts without calling the +producer's placement function. Missing, added or altered rows fail. A fixture +Unicode file or unit-test success alone is not complete-corpus evidence. + +## File plan and resources + +`english_gonol/ordinal_construct.py` owns admission expansion, composition and +artifact verification; UCNS owns the geometric law. `tests/test_ordinal_construct.py` +owns fixture/property regressions. The workflow owns explicit input acquisition +and full replay. `ordinal-work-graph.json` binds input ownership and exact source +states. No root Stack participant, release pin, UCHC graduation or website is +changed. The candidate source commit is recorded by hosted evidence, avoiding a +self-referential committed head hash. + +Expected working footprint is below 4 GiB; the hosted runner checks free disk +before work. The source has 46,372,711 raw YAML bytes. No artificial science +stopping time is introduced; the workflow uses the platform's job boundary. +The local environment cannot fetch the complete public source/UCD bytes, so +full construction is executed by the repository workflow rather than calling a +small local fixture the full construct. + +## hmmm + +The layout choices are explicit and replaceable only through a new profile and +full rebuild. Native Mobius lift, global transport/definition-origin attachment, +operator function semantics, inference quality and UCHC release remain separate +questions. Local placement does not manufacture evidence for those questions. +A complete hosted receipt must exist before claiming complete-corpus success. diff --git a/research/english-gonol/docs/ordinal-work-graph.json b/research/english-gonol/docs/ordinal-work-graph.json new file mode 100644 index 0000000..cd30f14 --- /dev/null +++ b/research/english-gonol/docs/ordinal-work-graph.json @@ -0,0 +1,43 @@ +{ + "schema": "the-interdependency.stack-manifest", + "version": "1.0.0", + "repositories": [ + { + "repository": "The-Interdependency/ucns", + "commit": "a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb", + "authority": "generic exact ordinal geometry", + "relation": "new producer; no English semantic authority" + }, + { + "repository": "The-Interdependency/stack", + "commit": "e3eb83764355b4b760a79323cda6a6d75c3a501a", + "authority": "English source admission and construction forge", + "relation": "unchanged structural-source baseline; candidate source bound by generated implementation digest and observed head" + }, + { + "repository": "globalwordnet/english-wordnet", + "commit": "dc343f2683279ecbb13fab4e2fd778d7b162d287", + "authority": "complete English corpus evidence", + "relation": "all exact pinned source records" + }, + { + "repository": "The-Interdependency/skill-lib", + "commit": "e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128", + "authority": "build discipline", + "relation": "current loaded governing contracts" + } + ], + "boundaries": { + "authority_transfer": false, + "proof_status_transfer": false, + "measurement_status_transfer": false, + "semantic_mapping": "English supplies exact participants and explicit ordering policy; UCNS supplies geometry only", + "agent_scope": "cross-repository-work-graph", + "hmmm": [ + "Native Mobius lift and global frame attachment remain unresolved.", + "Balanced scalar insertion and composite angular ordering are declared profile choices.", + "The historical admission carrier is pinned separately in preserved source metadata; its angles are not consumed by the new constructor." + ] + }, + "work_graph_sha256": "7d0ec15d06ed32c29f8352afb63b3b73be340f1dace935f1da4e43b207a483b0" +} diff --git a/research/english-gonol/english_gonol/ordinal_construct.py b/research/english-gonol/english_gonol/ordinal_construct.py new file mode 100644 index 0000000..cdf94ef --- /dev/null +++ b/research/english-gonol/english_gonol/ordinal_construct.py @@ -0,0 +1,502 @@ +"""Build the replacement English angular/radial construction. + +Usage (from research/english-gonol, with UCNS on PYTHONPATH): + python -m english_gonol.ordinal_construct build ADMISSION UCD NEW_OUTPUT + python -m english_gonol.ordinal_construct verify OUTPUT + python -m english_gonol.ordinal_construct query OUTPUT 'the geometry' + +ADMISSION is a complete, verified structural-profile field, used for source +admission and relations only. The new construction never consumes its old +public_position column. UCD contains UnicodeData.txt and DerivedCoreProperties.txt +from the explicitly declared Unicode release. No network occurs in this module. +""" +from __future__ import annotations + +import argparse +from contextlib import closing +from functools import lru_cache +from hashlib import sha256 +from itertools import groupby +import json +from pathlib import Path +import shutil +import sqlite3 +import tempfile + +from ucns.ordinal_affixiation import Carrier, Participant, affixiate + +# === MODULE_BUILD === +# id: english_ordinal_construction +# module_name: ordinal_construct +# module_kind: engine +# summary: expanded corpus/Unicode public gonol and exact recursive ordinal geometry +# owner: Erin Spencer +# public_surface: repertoire, Factory, build, verify, query, main +# internal_surface: canonical artifact rows and strict corpus admission +# auth_boundary: read-only exact complete structural source +# storage_boundary: new caller-selected output; no overwrite +# network_boundary: none +# user_data_boundary: query text in memory unless explicitly saved by caller +# admin_only: false +# tests: tests/test_ordinal_construct.py +# rollout: explicit replacement profile english.ordinal/1; legacy receipts remain historical +# rollback: remove candidate import/output; no silent profile downgrade +# unresolved: native Mobius lift, global frame attachment, semantic interpretation +# === END MODULE_BUILD === +# === CONTRACTS === +# id: english_expanded_repertoire +# given: complete corpus scalars, exact inherited carrier, pinned Unicode properties +# then: every required scalar is admitted once; SPACE stays first; registry is reproducible +# id: english_recursive_ordinal_geometry +# given: closed words and exact source components +# then: UCNS places by ordinal radius and declared carrier angle while interiors remain recoverable +# id: english_complete_geometry_replay +# given: a complete replacement artifact +# then: independently check every placement, source reference, closure receipt and raw source input +# === END CONTRACTS === + +PROFILE = 'english.ordinal/1' +UNICODE_VERSION = '18.0.0' +UCD_FILES = ('UnicodeData.txt', 'DerivedCoreProperties.txt') +LOGIC = tuple('¬∧∨⊻⊼⊽→←↔⇒⇐⇔∀∃∄⊢⊣⊤⊥⊨⊭⊬⊮⊯≡≠=<>≤≥') +LAYOUT = 'legacy-anchor-balanced-insertion/1' +WORD_LAYOUT = 'lexicographic-public-gonol-index-sequences/1' +UCNS_COMMIT = 'a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb' +UCNS_MODULE_SHA256 = '784cf61d185d2a54259c0e013af8c0ea2b6d79fad32beaffda7819f0c0e512ad' +SQL = ''' +PRAGMA foreign_keys=ON; +PRAGMA journal_mode=DELETE; +CREATE TABLE frames(kind TEXT NOT NULL, id INTEGER NOT NULL, identity TEXT NOT NULL, + origin TEXT NOT NULL, relation TEXT NOT NULL, source TEXT NOT NULL, receipt TEXT NOT NULL, + length INTEGER NOT NULL CHECK(length>0), PRIMARY KEY(kind,id)) WITHOUT ROWID; +CREATE TABLE placements(kind TEXT NOT NULL, id INTEGER NOT NULL, ordinal INTEGER NOT NULL, + participant_kind TEXT NOT NULL CHECK(participant_kind IN ('word','character')), + participant_id INTEGER NOT NULL, carrier_index INTEGER NOT NULL, + exponent INTEGER NOT NULL CHECK(exponent>0), interior_receipt TEXT, + PRIMARY KEY(kind,id,ordinal), FOREIGN KEY(kind,id) REFERENCES frames(kind,id)) WITHOUT ROWID; +''' + + +def canonical(value: object) -> bytes: + return json.dumps(value, ensure_ascii=False, sort_keys=True, + separators=(',', ':'), allow_nan=False).encode('utf-8') + + +def digest(value: object) -> str: + return sha256(canonical(value)).hexdigest() + + +def file_hash(path: Path) -> str: + with path.open('rb') as stream: + return sha256(stream.read()).hexdigest() + + +def _producer_check() -> None: + import ucns.ordinal_affixiation as geometry + if file_hash(Path(geometry.__file__)) != UCNS_MODULE_SHA256: + raise ValueError('UCNS geometry source differs from the exact pinned producer') + + +def scalar(value: str) -> str: + if (not isinstance(value, str) or len(value) != 1 + or 0xD800 <= ord(value) <= 0xDFFF): + raise ValueError('one exact Unicode scalar required') + return value + + +def _range(value: str) -> range: + bounds = value.strip().split('..') + first, last = int(bounds[0], 16), int(bounds[-1], 16) + if len(bounds) > 2 or not 0 <= first <= last <= 0x10FFFF: + raise ValueError('invalid Unicode property range') + return range(first, last + 1) + + +def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: + """Read numeric categories and the derived Math property, never host Unicode.""" + numbers: set[str] = set() + maths: set[str] = set() + pending = None + blobs = {name: (ucd / name).read_bytes() for name in UCD_FILES} + if any(len(raw) > 10_000_000 for raw in blobs.values()): + raise ValueError('Unicode input exceeds per-file acquisition budget') + data = blobs[UCD_FILES[0]].decode('utf-8') + for line in data.splitlines(): + if not line.strip(): + continue + fields = line.split(';') + if len(fields) != 15: + raise ValueError('invalid UnicodeData record') + cp, name, category = int(fields[0], 16), fields[1], fields[2] + if not 0 <= cp <= 0x10FFFF: + raise ValueError('UnicodeData code point out of range') + if name.endswith(', First>'): + if pending is not None: + raise ValueError('nested UnicodeData range') + pending = (cp, category) + continue + if name.endswith(', Last>'): + if pending is None or pending[1] != category or cp < pending[0]: + raise ValueError('unmatched UnicodeData range') + points = range(pending[0], cp + 1) + pending = None + else: + if pending is not None: + raise ValueError('unterminated UnicodeData range') + points = (cp,) + if category in ('Nd', 'Nl', 'No'): + numbers.update(scalar(chr(p)) for p in points) + if pending is not None: + raise ValueError('unterminated UnicodeData range') + derived = blobs[UCD_FILES[1]].decode('utf-8') + if f'DerivedCoreProperties-{UNICODE_VERSION}.txt' not in derived[:4096]: + raise ValueError('Unicode release header mismatch') + for line in derived.splitlines(): + body = line.split('#', 1)[0].strip() + if not body: + continue + fields = [field.strip() for field in body.split(';')] + if len(fields) >= 2 and fields[1] == 'Math': + maths.update(scalar(chr(p)) for p in _range(fields[0])) + if not set('0123456789') <= numbers or not set('+<=>') <= maths: + raise ValueError('incomplete numeric or Math property input') + return numbers, maths, {name: sha256(blobs[name]).hexdigest() for name in UCD_FILES} + + +def repertoire(corpus: tuple[str, ...], legacy: tuple[str, ...], ucd: Path) -> dict: + """Expand the repertoire without assigning Unicode categories geometric roles.""" + for c in (*corpus, *legacy): + scalar(c) + if len(set(legacy)) != len(legacy) or not legacy or legacy[0] != ' ': + raise ValueError('legacy anchors must be unique with SPACE first') + numbers, maths, hashes = unicode_admission(ucd) + admitted = set(corpus) | set(legacy) | numbers | maths | set(LOGIC) + extras = sorted(admitted - set(legacy), key=ord) + order: list[str] = [] + for i, anchor in enumerate(legacy): + order.append(anchor) + order.extend(extras[i * len(extras) // len(legacy): + (i + 1) * len(extras) // len(legacy)]) + if len(order) != len(admitted) or set(order) != admitted: + raise AssertionError('repertoire union lost or duplicated a scalar') + return {'schema': 'english.public-gonol/1', 'unicode_version': UNICODE_VERSION, + 'layout': LAYOUT, 'normalization': 'none', 'origin_scalar': ' ', + 'corpus_scalars': sorted(corpus, key=ord), 'legacy_anchors': list(legacy), + 'unicode_files_sha256': hashes, 'logical_supplement': list(LOGIC), + 'admission_counts': {'corpus': len(set(corpus)), 'legacy': len(legacy), + 'numbers': len(numbers), 'math': len(maths), + 'logical_supplement': len(set(LOGIC)), + 'additional_to_legacy': len(extras), 'union': len(order)}, + 'identities': order} + + +class Factory: + """Actual recursive constructions; carriers and closed interiors remain available.""" + def __init__(self, public: dict, words: dict[int, str], source_receipt: str): + self.public = json.loads(canonical(public)) + self.words = dict(words) + self.word_ids = {word: wid for wid, word in words.items()} + self.source_receipt = source_receipt + self.glyph_carrier = Carrier(tuple(public['identities']), + f'{PROFILE}:public:{digest(public)}') + ordered = tuple(sorted(words.values(), key=lambda w: tuple( + self.glyph_carrier.index(c) for c in w))) + if not ordered: + raise ValueError('no closed words admitted') + self.word_carrier = Carrier(ordered, f'{PROFILE}:{WORD_LAYOUT}:{source_receipt}') + self._atoms = {c: Participant.atom(self.glyph_carrier, c) + for c in self.glyph_carrier.identities} + + @lru_cache(maxsize=8192) + def word(self, wid: int): + text = self.words[wid] + return affixiate(text, tuple(self._atoms[c] for c in text), origin='SPACE', + relation='ordered-glyphs', + source=f'{self.source_receipt}:word:{wid}') + + def record(self, rid: int, kind: str, parts): + participants = tuple(self._atoms[value] if pkind == 'character' else + Participant.closed(self.word_carrier, self.word(value)) + for pkind, value in parts) + return affixiate(f'{kind}:{rid}', participants, origin='SPACE', + relation=f'ordered-{kind}', + source=f'{self.source_receipt}:record:{rid}') + + +def _inventory(db): + return dict(db.execute('SELECT id,scalar FROM characters ORDER BY id')), dict( + db.execute('SELECT id,surface FROM words ORDER BY id')) + + +def _groups(db): + rows = db.execute('SELECT record_id,ordinal,kind,word_id,character_id ' + 'FROM components ORDER BY record_id,ordinal') + for rid, group in groupby(rows, key=lambda r: r[0]): + yield rid, tuple(group) + + +def _geometry_receipt(db) -> str: + result = sha256() + for table, ordering in (('frames', 'kind,id'), ('placements', 'kind,id,ordinal')): + result.update(canonical(table) + b'\n') + for row in db.execute(f'SELECT * FROM {table} ORDER BY {ordering}'): + result.update(canonical(row) + b'\n') + return result.hexdigest() + + +def _write_frame(db, kind, identity, obj, refs): + db.execute('INSERT INTO frames VALUES(?,?,?,?,?,?,?,?)', + (kind, identity, obj.identity, obj.origin, obj.relation, + obj.source, obj.receipt, len(obj.participants))) + db.executemany('INSERT INTO placements VALUES(?,?,?,?,?,?,?,?)', ( + (kind, identity, i, pkind, pid, + p.carrier.index(p.identity), obj.placement(i).exponent, + None if p.interior is None else p.interior.receipt) + for i, ((pkind, pid), p) in enumerate(zip(refs, obj.participants, strict=True)))) + + +def _json_write(path, value): + Path(path).write_bytes(canonical(value) + b'\n') + + +def _json_read(path): + raw = Path(path).read_bytes() + value = json.loads(raw) + if raw != canonical(value) + b'\n': + raise ValueError('noncanonical JSON artifact') + return value + + +def build(admission: Path, ucd: Path, output: Path) -> dict: + """Consume complete source admission, create a fresh self-contained geometry bundle.""" + from english_gonol.structural_construct import _verified_connection + _producer_check() + if output.exists(): + raise ValueError('output exists; select a new directory') + output.parent.mkdir(parents=True, exist_ok=True) + stage = Path(tempfile.mkdtemp(prefix='.ordinal-', dir=output.parent)) + try: + with _verified_connection(admission) as verified: + source_db, source_manifest = verified + if source_manifest['metadata']['complete_corpus'] is not True: + raise ValueError('replacement construction requires complete pinned source') + (stage / 'admission').mkdir() + with closing(sqlite3.connect(stage / 'admission' / 'construct.db')) as copy: + source_db.backup(copy) + _json_write(stage / 'admission' / 'manifest.json', source_manifest) + (stage / 'ucd').mkdir() + for name in UCD_FILES: + shutil.copyfile(ucd / name, stage / 'ucd' / name) + chars, words = _inventory(source_db) + legacy = tuple(source_manifest['metadata']['producer']['carrier']) + public = repertoire(tuple(chars.values()), legacy, stage / 'ucd') + factory = Factory(public, words, source_manifest['receipt_sha256']) + _json_write(stage / 'public-gonol.json', public) + _json_write(stage / 'word-carrier.json', { + 'layout': WORD_LAYOUT, 'identities': list(factory.word_carrier.identities), + 'source': factory.word_carrier.source, 'receipt': factory.word_carrier.receipt}) + character_ids = {c: cid for cid, c in chars.items()} + with closing(sqlite3.connect(stage / 'geometry.db')) as geometry: + geometry.executescript(SQL) + for wid, text in words.items(): + _write_frame(geometry, 'word', wid, factory.word(wid), + tuple(('character', character_ids[c]) for c in text)) + records = dict(source_db.execute('SELECT id,kind FROM records')) + record_count = 0 + for rid, rows in _groups(source_db): + record_count += 1 + obj = factory.record(rid, records[rid], tuple( + (pk, chars[cid] if pk == 'character' else wid) + for _, _, pk, wid, cid in rows)) + refs = tuple((pk, cid if pk == 'character' else wid) + for _, _, pk, wid, cid in rows) + _write_frame(geometry, 'record', rid, obj, refs) + if record_count != len(records): + raise ValueError('source has empty records; empty closure is not licensed') + geometry.commit() + counts = {table: geometry.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] + for table in ('frames', 'placements')} + manifest = {'schema': PROFILE, 'source_receipt': source_manifest['receipt_sha256'], + 'source': source_manifest['metadata']['source'], + 'ucns_commit': UCNS_COMMIT, 'implementation_sha256': file_hash(Path(__file__)), + 'public_sha256': digest(public), + 'glyph_carrier_receipt': factory.glyph_carrier.receipt, + 'word_carrier_receipt': factory.word_carrier.receipt, + 'counts': counts, 'geometry_receipt': _geometry_receipt(geometry), + 'hmmm': ['Local frame placement is constructed; global origin attachment is not inferred.', + 'Layout recipes are explicit profile choices, not discovered semantic laws.', + 'Native Mobius lift and inference quality remain untested.']} + _json_write(stage / 'manifest.json', manifest) + report = verify(stage) + _json_write(stage / 'verification.json', report) + stage.rename(output) + return report + except BaseException: + shutil.rmtree(stage, ignore_errors=True) + raise + + +def _independent_frame(kind, frame_id, identity, relation, source_receipt, refs, + factory, chars, word_receipts): + """Reference checker: literal ordinal formula, no Placement/affixiate calls.""" + from fractions import Fraction + positions, stored = [], [] + n = len(refs) + for i, (pk, pid) in enumerate(refs): + carrier = factory.glyph_carrier if pk == 'character' else factory.word_carrier + name = chars[pid] if pk == 'character' else factory.words[pid] + index = carrier.index(name) + turn = Fraction(index, len(carrier.identities)) + interior = None if pk == 'character' else word_receipts[pid] + positions.append({'identity': name, 'carrier_receipt': carrier.receipt, + 'index': index, 'arity': len(carrier.identities), + 'turn': [turn.numerator, turn.denominator], + 'radius': {'numerator': 1, 'power_of_two_denominator': n-i}, + 'interior_receipt': interior}) + stored.append((kind, frame_id, i, pk, pid, index, n-i, interior)) + source = f'{source_receipt}:{kind}:{frame_id}' + receipt = digest({'schema': 'ucns.ordinal-affixiation.v1', 'identity': identity, + 'origin': 'SPACE', 'relation': relation, 'source': source, + 'placements': positions}) + return (kind, frame_id, identity, 'SPACE', relation, source, receipt, n), stored + + +def verify(output: Path) -> dict: + """Replay every source and placement; structural bytes alone never prove new geometry.""" + from english_gonol.structural_construct import _verified_connection, open_readonly, _schema + _producer_check() + manifest = _json_read(output / 'manifest.json') + if manifest['schema'] != PROFILE or manifest['ucns_commit'] != UCNS_COMMIT: + raise ValueError('profile/geometry producer mismatch') + if manifest['implementation_sha256'] != file_hash(Path(__file__)): + raise ValueError('implementation changed; rebuild explicitly') + with _verified_connection(output / 'admission') as verified: + source, source_manifest = verified + if not source_manifest['metadata']['complete_corpus']: + raise ValueError('partial source cannot verify the replacement') + if (manifest['source_receipt'] != source_manifest['receipt_sha256'] or + manifest['source'] != source_manifest['metadata']['source']): + raise ValueError('source binding mismatch') + chars, words = _inventory(source) + public = repertoire(tuple(chars.values()), tuple( + source_manifest['metadata']['producer']['carrier']), output / 'ucd') + if public != _json_read(output / 'public-gonol.json') or digest(public) != manifest['public_sha256']: + raise ValueError('public gonol mismatch') + factory = Factory(public, words, manifest['source_receipt']) + expected_words = {'layout': WORD_LAYOUT, 'identities': list(factory.word_carrier.identities), + 'source': factory.word_carrier.source, 'receipt': factory.word_carrier.receipt} + if _json_read(output / 'word-carrier.json') != expected_words: + raise ValueError('word carrier mismatch') + if (factory.glyph_carrier.receipt != manifest['glyph_carrier_receipt'] or + factory.word_carrier.receipt != manifest['word_carrier_receipt']): + raise ValueError('carrier receipt mismatch') + word_receipts = {} + character_ids = {c: cid for cid, c in chars.items()} + with closing(open_readonly(output / 'geometry.db')) as db: + db.execute('BEGIN') + with closing(sqlite3.connect(':memory:')) as expected: + expected.executescript(SQL) + if _schema(db) != _schema(expected): + raise ValueError('geometry schema mismatch') + if db.execute('PRAGMA integrity_check').fetchone() != ('ok',) or db.execute('PRAGMA foreign_key_check').fetchone(): + raise ValueError('geometry integrity failure') + frames_checked = placements_checked = 0 + + def check(kind, frame_id, identity, relation, refs): + nonlocal frames_checked, placements_checked + frame, positions = _independent_frame(kind, frame_id, identity, relation, + manifest['source_receipt'], refs, factory, chars, word_receipts) + actual_frame = db.execute('SELECT * FROM frames WHERE kind=? AND id=?', (kind, frame_id)).fetchone() + actual = db.execute('SELECT * FROM placements WHERE kind=? AND id=? ORDER BY ordinal', + (kind, frame_id)).fetchall() + if actual_frame != frame or actual != positions: + raise ValueError(f'geometry mismatch at {kind}:{frame_id}') + frames_checked += 1 + placements_checked += len(positions) + return frame[6] + + for wid, text in words.items(): + word_receipts[wid] = check('word', wid, text, 'ordered-glyphs', + tuple(('character', character_ids[c]) for c in text)) + records = dict(source.execute('SELECT id,kind FROM records')) + for rid, rows in _groups(source): + check('record', rid, f'{records[rid]}:{rid}', f'ordered-{records[rid]}', + tuple((pk, cid if pk == 'character' else wid) for _, _, pk, wid, cid in rows)) + counts = {table: db.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] + for table in ('frames', 'placements')} + if (frames_checked != len(words) + len(records) or counts != manifest['counts'] + or counts != {'frames': frames_checked, 'placements': placements_checked}): + raise ValueError('missing or extra geometry') + if _geometry_receipt(db) != manifest['geometry_receipt']: + raise ValueError('geometry receipt mismatch') + return {'schema': 'english.ordinal-verification/1', 'status': 'SURVIVED', + 'scope': 'complete pinned corpus; source recovery plus every local placement', + 'public_gonol_size': len(public['identities']), 'words': len(words), + **counts, 'manifest_sha256': digest(manifest), + 'source_receipt': manifest['source_receipt'], 'hmmm': manifest['hmmm']} + + +def query(output: Path, text: str) -> dict: + """Construct exact ordered text from the sealed admission; never admit unknown words.""" + from english_gonol.structural_construct import _verified_connection + from english_gonol.structural_rules import segment + report = verify(output) + geometry_manifest = _json_read(output / 'manifest.json') + if digest(geometry_manifest) != report['manifest_sha256']: + raise ValueError('manifest changed after verification') + with _verified_connection(output / 'admission') as verified: + source, manifest = verified + _, words = _inventory(source) + public = _json_read(output / 'public-gonol.json') + if (digest(public) != geometry_manifest['public_sha256'] or + manifest['receipt_sha256'] != geometry_manifest['source_receipt']): + raise ValueError('query inputs changed after verification') + factory = Factory(public, words, manifest['receipt_sha256']) + parts = segment(text, manifest['metadata']['profile']['abbreviations']) + participants = [] + interiors = {} + for part in parts: + if part.kind == 'word': + if part.text not in factory.word_ids: + raise ValueError(f'word not admitted: {part.text!r}') + word = factory.word(factory.word_ids[part.text]) + participants.append(Participant.closed(factory.word_carrier, word)) + interiors[word.receipt] = word.record() + else: + if part.text not in factory._atoms: + raise ValueError(f'scalar not admitted: U+{ord(part.text):04X}') + participants.append(factory._atoms[part.text]) + obj = affixiate('query', tuple(participants), origin='SPACE', relation='ordered-text', + source=f'query:{digest(text)}:{manifest["receipt_sha256"]}') + recovered = ''.join(obj.recover()) + if recovered != text: + raise AssertionError('query source recovery failed') + return {'construction': obj.record(), 'interiors': interiors, 'recovered': recovered, + 'public_gonol_sha256': digest(factory.public), + 'word_carrier_receipt': factory.word_carrier.receipt, + 'closure': 'ordered-text; no grammatical or semantic assertion'} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + sub = parser.add_subparsers(dest='command', required=True) + builder = sub.add_parser('build') + for name in ('admission', 'ucd', 'output'): + builder.add_argument(name, type=Path) + checker = sub.add_parser('verify') + checker.add_argument('output', type=Path) + request = sub.add_parser('query') + request.add_argument('output', type=Path) + request.add_argument('text') + args = parser.parse_args() + if args.command == 'build': + value = build(args.admission, args.ucd, args.output) + elif args.command == 'verify': + value = verify(args.output) + else: + value = query(args.output, args.text) + print(json.dumps(value, ensure_ascii=False, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/research/english-gonol/tests/test_ordinal_construct.py b/research/english-gonol/tests/test_ordinal_construct.py new file mode 100644 index 0000000..3d28ea5 --- /dev/null +++ b/research/english-gonol/tests/test_ordinal_construct.py @@ -0,0 +1,233 @@ +# === CHECKS === +# id: english_ordinal_union_and_layout +# proves: english_expanded_repertoire +# call: self::test_union_and_layout +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_supplementary_scalar_not_utf16_units +# proves: english_expanded_repertoire +# call: self::test_supplementary_scalar_not_utf16_units +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_no_normalization +# proves: english_expanded_repertoire +# call: self::test_no_normalization +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_wrong_version_refuses +# proves: english_expanded_repertoire +# call: self::test_wrong_version_refuses +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_missing_property_data_refuses +# proves: english_expanded_repertoire +# call: self::test_missing_property_data_refuses +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_unclosed_unicode_range_refuses +# proves: english_expanded_repertoire +# call: self::test_unclosed_unicode_range_refuses +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_invalid_scalar_and_anchor_refusal +# proves: english_expanded_repertoire +# call: self::test_invalid_scalar_and_anchor_refusal +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_word_and_recursive_record +# proves: english_recursive_ordinal_geometry +# call: self::test_word_and_recursive_record +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_append_does_not_change_angle +# proves: english_recursive_ordinal_geometry +# call: self::test_append_does_not_change_angle +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_sql_materialization_and_independent_replay +# proves: english_complete_geometry_replay +# call: self::test_sql_materialization_and_independent_replay +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_unknown_word_refuses +# proves: english_recursive_ordinal_geometry +# call: self::test_unknown_word_refuses +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_geometry_producer_bytes_are_bound +# proves: english_complete_geometry_replay +# call: self::test_geometry_producer_bytes_are_bound +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# === END CHECKS === + +"""Fixture tests are not full Unicode or corpus receipts; hosted build supplies those.""" +from fractions import Fraction +import sqlite3 +import pytest +from english_gonol.ordinal_construct import ( + Factory, LOGIC, SQL, UNICODE_VERSION, repertoire, scalar, unicode_admission, + _write_frame, _independent_frame, _producer_check, +) +from ucns.ordinal_affixiation import Carrier, Participant, affixiate + + +def ucd_fixture(tmp_path): + rows = [] + for c in '0123456789': + rows.append(';'.join([f'{ord(c):04X}', 'DIGIT', 'Nd'] + [''] * 12)) + rows.extend([';'.join(['00B2', 'SUPERSCRIPT TWO', 'No'] + [''] * 12), + ';'.join(['2160', 'ROMAN NUMERAL ONE', 'Nl'] + [''] * 12)]) + (tmp_path / 'UnicodeData.txt').write_text('\n'.join(rows) + '\n') + (tmp_path / 'DerivedCoreProperties.txt').write_text( + f'# DerivedCoreProperties-{UNICODE_VERSION}.txt\n002B ; Math\n003C..003E ; Math\n2200 ; Math\n') + return tmp_path + + +def factory_fixture(tmp_path): + public = repertoire(tuple(' ABCé\u0301'), tuple(' ABC'), ucd_fixture(tmp_path)) + return Factory(public, {1: 'ABA', 2: 'C', 3: 'é', 4: 'A\u0301'}, 'fixture-source') + + +def test_union_and_layout(tmp_path): + ucd = ucd_fixture(tmp_path) + public = repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) + values = public['identities'] + assert values[0] == ' ' + assert [c for c in values if c in ' ABC'] == list(' ABC') + assert set('0123456789²Ⅰé\u0301') | set(LOGIC) <= set(values) + assert len(values) == len(set(values)) == public['admission_counts']['union'] + anchors = [values.index(c) for c in ' ABC'] + [len(values)] + counts = [b-a-1 for a,b in zip(anchors, anchors[1:])] + assert max(counts) - min(counts) <= 1 + assert public == repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) + + +def test_supplementary_scalar_not_utf16_units(tmp_path): + public = repertoire(('𝟠',), tuple(' A'), ucd_fixture(tmp_path)) + assert public['identities'].count('𝟠') == 1 + assert scalar('𝟠') == '𝟠' + + +def test_no_normalization(tmp_path): + public = repertoire(('é','e','\u0301'), tuple(' A'), ucd_fixture(tmp_path)) + assert all(c in public['identities'] for c in ('é','e','\u0301')) + + +def test_wrong_version_refuses(tmp_path): + root = ucd_fixture(tmp_path) + path = root / 'DerivedCoreProperties.txt' + path.write_text(path.read_text().replace(UNICODE_VERSION, '17.0.0')) + with pytest.raises(ValueError, match='release'): + unicode_admission(root) + + +def test_missing_property_data_refuses(tmp_path): + root = ucd_fixture(tmp_path) + (root / 'UnicodeData.txt').write_text('') + with pytest.raises(ValueError, match='incomplete'): + unicode_admission(root) + + +def test_unclosed_unicode_range_refuses(tmp_path): + root = ucd_fixture(tmp_path) + with (root / 'UnicodeData.txt').open('a') as stream: + stream.write(';'.join(['3000', '', 'No'] + ['']*12) + '\n') + with pytest.raises(ValueError, match='unterminated'): + unicode_admission(root) + + +def test_invalid_scalar_and_anchor_refusal(tmp_path): + root = ucd_fixture(tmp_path) + for bad in ('', 'ab', '\ud800'): + with pytest.raises(ValueError): + repertoire((bad,), tuple(' A'), root) + for bad in (('A',), (' ', 'A', 'A')): + with pytest.raises(ValueError): + repertoire(('A',), bad, root) + + +def test_word_and_recursive_record(tmp_path): + factory = factory_fixture(tmp_path) + word = factory.word(1) + assert word.recover() == tuple('ABA') + assert [word.placement(i).radius() for i in range(3)] == [Fraction(1,8),Fraction(1,4),Fraction(1,2)] + obj = factory.record(1, 'definition', (('word',1),('character',' '),('word',1))) + assert ''.join(obj.recover()) == 'ABA ABA' + assert obj.participants[0].interior is obj.participants[2].interior is word + assert obj.placement(0).turn == factory.word_carrier.turn('ABA') + assert obj.placement(1).turn == factory.glyph_carrier.turn(' ') + higher = Carrier((obj.identity,), 'fixture-higher') + triple = affixiate('higher', (Participant.closed(higher,obj),), + origin='SPACE', relation='declared-nesting', source='fixture') + assert ''.join(triple.recover()) == 'ABA ABA' + + +def test_append_does_not_change_angle(tmp_path): + factory = factory_fixture(tmp_path) + before = factory.record(1,'definition',(('word',1),)) + after = factory.record(2,'definition',(('word',1),('word',2))) + assert after.placement(0).turn == before.placement(0).turn + assert after.placement(0).radius() == before.placement(0).radius()/2 + assert after.placement(1).radius() == Fraction(1,2) + + +def test_sql_materialization_and_independent_replay(tmp_path): + factory = factory_fixture(tmp_path) + chars = {i:c for i,c in enumerate(factory.glyph_carrier.identities)} + ids = {c:i for i,c in chars.items()} + receipts = {} + with sqlite3.connect(':memory:') as db: + db.executescript(SQL) + for wid, text in factory.words.items(): + refs = tuple(('character',ids[c]) for c in text) + obj = factory.word(wid) + _write_frame(db,'word',wid,obj,refs) + expected, positions = _independent_frame('word',wid,text,'ordered-glyphs', + factory.source_receipt,refs,factory,chars,receipts) + assert db.execute('SELECT * FROM frames WHERE kind=? AND id=?',('word',wid)).fetchone() == expected + assert db.execute('SELECT * FROM placements WHERE kind=? AND id=? ORDER BY ordinal',('word',wid)).fetchall() == positions + receipts[wid] = obj.receipt + refs = (('word',1),('character',ids[' ']),('word',2),('word',1)) + obj = factory.record(7,'definition',(('word',1),('character',' '),('word',2),('word',1))) + _write_frame(db,'record',7,obj,refs) + expected, positions = _independent_frame('record',7,'definition:7','ordered-definition', + factory.source_receipt,refs,factory,chars,receipts) + assert db.execute('SELECT * FROM frames WHERE kind=? AND id=?',('record',7)).fetchone() == expected + assert db.execute('SELECT * FROM placements WHERE kind=? AND id=? ORDER BY ordinal',('record',7)).fetchall() == positions + db.execute("UPDATE placements SET exponent=exponent+1 WHERE kind='record' AND ordinal=0") + assert db.execute('SELECT * FROM placements WHERE kind=? AND id=? ORDER BY ordinal',('record',7)).fetchall() != positions + + +def test_unknown_word_refuses(tmp_path): + factory = factory_fixture(tmp_path) + with pytest.raises(KeyError): + factory.word(999) + + +def test_geometry_producer_bytes_are_bound(): + _producer_check() From 2cf9d504680557537276d44f3ce5179ea28d2c56 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 00:37:35 -0700 Subject: [PATCH 02/25] ci: provide the pinned ordinal geometry dependency to the existing English test suite --- .github/workflows/english-gonol.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/english-gonol.yml b/.github/workflows/english-gonol.yml index 296367c..6aa291c 100644 --- a/.github/workflows/english-gonol.yml +++ b/.github/workflows/english-gonol.yml @@ -73,13 +73,21 @@ jobs: path: _deps/ucns-carrier persist-credentials: false + - name: Checkout pinned ordinal geometry producer + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: The-Interdependency/ucns + ref: a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb + path: _deps/ucns-ordinal + persist-credentials: false + - name: Set up Python uses: actions/setup-python@v7.0.0 with: python-version: "3.12" - name: Install construction prerequisites - run: python -m pip install --disable-pip-version-check pytest PyYAML + run: python -m pip install --disable-pip-version-check pytest PyYAML ./_deps/ucns-ordinal - name: Verify all pinned source identities run: | @@ -88,6 +96,7 @@ jobs: test "$(git -C _deps/oewn rev-parse HEAD)" = "dc343f2683279ecbb13fab4e2fd778d7b162d287" test "$(git -C _deps/edcm-metric-origin rev-parse HEAD)" = "0873c105799681ea1f7ccb3e619d1f7aebbd85e0" test "$(git -C _deps/ucns-carrier rev-parse HEAD)" = "4f863ad37096b7baab8f62820ad5cb937b62a3a7" + test "$(git -C _deps/ucns-ordinal rev-parse HEAD)" = "a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb" - name: Preflight full-corpus resources run: | From 0e0ea9ebe64803e810793dd4780253d7d202fecc Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 02:29:06 -0700 Subject: [PATCH 03/25] Select ordinal English construction; retire previous default and expose unresolved laws Operator-authorized replacement. Add a no-fallback package entrypoint and source-owned active selection, nine routing regressions, updated usage, manual full-build dispatch, and prioritized construction questions. Preserve the byte-sealed admission dependency closure and previous geometry receipts as historical support; do not label legacy outputs as new geometry. UCNS #241 merged at 6ebbf970ad13a0d2e1c13bd65c496b671e740185; consume the same exact producer bytes. Local focused regression: 49 passed. Root authority, libs pins, and UCHC release standing unchanged. --- .../workflows/english-ordinal-affixiation.yml | 11 +- .../english-gonol/ACTIVE_CONSTRUCTION.json | 29 +++ research/english-gonol/README.md | 205 ++++++------------ .../docs/ordinal-construction.md | 16 +- .../english-gonol/docs/ordinal-questions.md | 93 ++++++++ .../english-gonol/english_gonol/__main__.py | 88 ++++++++ .../tests/test_active_construction.py | 76 +++++++ 7 files changed, 364 insertions(+), 154 deletions(-) create mode 100644 research/english-gonol/ACTIVE_CONSTRUCTION.json create mode 100644 research/english-gonol/docs/ordinal-questions.md create mode 100644 research/english-gonol/english_gonol/__main__.py create mode 100644 research/english-gonol/tests/test_active_construction.py diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index f4e2a1a..2427575 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -1,8 +1,12 @@ name: English ordinal affixiation on: + workflow_dispatch: pull_request: paths: - 'research/english-gonol/english_gonol/ordinal_construct.py' + - 'research/english-gonol/english_gonol/__main__.py' + - 'research/english-gonol/ACTIVE_CONSTRUCTION.json' + - 'research/english-gonol/tests/test_active_construction.py' - 'research/english-gonol/tests/test_ordinal_construct.py' - 'research/english-gonol/docs/ordinal-*' - '.github/workflows/english-ordinal-affixiation.yml' @@ -17,7 +21,7 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} persist-credentials: false - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: @@ -105,6 +109,7 @@ jobs: _inputs/ucns/.venv/bin/python -m pytest -q \ _inputs/ucns/tests/test_ordinal_affixiation.py \ research/english-gonol/tests/test_ordinal_construct.py \ + research/english-gonol/tests/test_active_construction.py \ | tee _evidence/tests.txt - name: Build complete source admission then the replacement geometry env: @@ -114,7 +119,7 @@ jobs: --source-root _inputs/oewn/src/yaml \ --ucns-source-root _inputs/admission-carrier \ --out-dir _admission 2> _evidence/admission-resources.txt - /usr/bin/time -v _inputs/ucns/.venv/bin/python -m english_gonol.ordinal_construct build \ + /usr/bin/time -v _inputs/ucns/.venv/bin/python -m english_gonol build \ _admission _inputs/ucd _constructed \ 2> _evidence/geometry-resources.txt | tee _evidence/full-verification.json mkdir -p _constructed/licenses @@ -137,7 +142,7 @@ jobs: env: PYTHONPATH: research/english-gonol run: | - _inputs/ucns/.venv/bin/python -m english_gonol.ordinal_construct query \ + _inputs/ucns/.venv/bin/python -m english_gonol query \ _constructed 'the geometry' > _evidence/query.json - name: Retain evidence even after a deterministic failure if: always() diff --git a/research/english-gonol/ACTIVE_CONSTRUCTION.json b/research/english-gonol/ACTIVE_CONSTRUCTION.json new file mode 100644 index 0000000..2f556a2 --- /dev/null +++ b/research/english-gonol/ACTIVE_CONSTRUCTION.json @@ -0,0 +1,29 @@ +{ + "schema": "english.active-construction/1", + "active_profile": "english.ordinal/1", + "status": "selected-for-new-English-construction", + "entrypoint": "python -m english_gonol", + "implementation": "english_gonol.ordinal_construct", + "geometry_authority": "The-Interdependency/ucns", + "geometry_commit": "a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb", + "producer_merge": "6ebbf970ad13a0d2e1c13bd65c496b671e740185", + "input_graph": "docs/ordinal-work-graph.json", + "questions": "docs/ordinal-questions.md", + "deprecated_as_completed_geometry": [ + "english_gonol.full_construct_run", + "english_gonol.structural_construct", + "orthogonal-axis or constituent-overlap substitutes" + ], + "retained_support": { + "english_gonol.structural_construct": "source admission and independent source replay only", + "english_gonol.structural_query": "source structure inspection only", + "historical_source_modules": "sealed admission import closure and explicitly historical replay; not supported new-construction routes" + }, + "fallback": "none", + "selection_scope": "local ordinal geometry and recursive recovery, not semantic quality or independent UCHC release", + "hmmm": [ + "Global frame transport and compound definition-origin attachment remain unresolved.", + "Native Mobius lift, operator actions and inference quality are not established.", + "Historical consumers require explicit migration; a merge is not a deployment." + ] +} diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index 1acd36c..c9321da 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -1,168 +1,85 @@ # English Gonol Construction -## Structural profile v1 — new construction entrypoint +## Active construction: ordinal affixiation -The operator-ratified [structural profile](docs/structural-profile-v1.md) replaces -non-whitespace runs for new structural work. It builds the complete pinned -corpus, keeps punctuation outside word identity, preserves ordered shared -participations, and exposes read-only query/replay through -`english_gonol.structural_query.StructuralField`. Start with the commands in -that document and the [exact input graph](docs/structural-profile-work-graph.json). -The v2 results below remain historical and are not receipts for the new profile. -Stack owns the implementation; UCHC carries the extracted candidate. Geometry, -compound lexical origins and graduation retain their explicit hmmm boundaries. +`english.ordinal/1` is the selected replacement for new English construction. +[ACTIVE_CONSTRUCTION.json](ACTIVE_CONSTRUCTION.json) owns that selection. +Distance follows repeated ordinal halving; angle comes from the expanded public +gonol. Closed interiors, order, multiplicity, whitespace and source provenance +remain recoverable. There is no fallback to previous geometry. - -Stack-local research component for English lexical/gonol construction. - -## Authority - -```text -METAPAT -> affixiation semantics -UCNS -> gonol / Möbius / Public Gonol geometry -English -> text admission and linguistic/semantic construction -EDCM -> measurement/evaluation only -``` - -English construction consumes UCNS geometry; it does not invent geometry or -move English semantics into UCNS. - -## Historical v2 invariants - -```text -every admitted character is a gonol -one exact scalar -> one shared character identity -one exact surface -> one shared word identity - -glyph axes - -> ordered glyph-axis tensor - -> closed word - -> word axis +```bash +export PYTHONPATH=research/english-gonol +python -m english_gonol profile +python -m english_gonol build /path/to/admission /path/to/ucd /path/to/new-output +python -m english_gonol verify /path/to/new-output +python -m english_gonol query /path/to/new-output 'the geometry' ``` -Once closed, a gonol is atomic at an admissible consuming scale. Reuse preserves -identity while order, multiplicity, relation, source position, and provenance -remain recoverable. - -The Stack-forged Hilbert inference candidate treats those already-declared axes -as mathematical basis directions rather than inserting Cartesian coordinates. -A word's ordered glyph-axis construction is preserved when the closed word -becomes its own higher-scale axis. Exact construct identity travels with every -basis axis. See [Hilbert inference candidate](docs/hilbert-inference.md). - -This mathematical use of vector is domain-qualified as `HilbertStateVector`. -It is not METAPAT `Vector` and not a UCNS displacement vector. The canonical -scalar field, cross-origin inner products, amplitudes/phases and inference -operators remain unresolved. - -Corpus occurrences, sense ids, and synset ids are evidence/provenance, not -independent gonols. Definitions are word-anchored constructions: each retains -the shared word origin, exact ordered constituent word/whitespace-character -identities, source ordinal, direct binding, and chain predecessor. - -## Full construct v2 — sealed historical profile +Use the exact UCNS and source identities, dependency setup and admission commands +in [ordinal construction](docs/ordinal-construction.md). The **English ordinal +affixiation** GitHub workflow can also be run manually from Actions. It builds +and independently replays the complete pinned corpus through the supported +entrypoint. An existing output directory is never overwritten. -`english_gonol.full_construct_run` builds the complete pinned OEWN 2025 corpus -without promoting bookkeeping into geometry. +The delivered full construction has 4,698 public scalar positions, 103,053 closed +words, 420,006 frames and 4,792,299 placements. Source and geometry receipts belong +to `english.ordinal/1`; old counts and receipts are not interchangeable with it. +These counts establish constructed scope, not semantic or inference quality. -```text -word origin -> D1 -> D2 -> ... -> Dn # chain topology -word origin -> D1, D2, ... Dn # direct topology +## Authority -ordinal evidence -+ semantic evidence -+ exact sentence-context evidence --> preponderance relative to the rest of the sentence in which the word appears --> hmmm until UCNS derives the displacement geometry -``` +UCNS owns geometric objects and the ordinal operation. Stack owns this English +construction and its source/admission profile. METAPAT owns affixiation semantics; +EDCM may measure completed outputs but does not define them. Selecting this +profile does not graduate UCHC or refresh the root `libs/` snapshots. The exact +work graph in `docs/ordinal-work-graph.json` binds the consumed geometry separately. -Definitions preserve their source exactly: every maximal non-whitespace run -reuses one shared word identity and every whitespace scalar reuses one shared -character identity. No normalization is applied. +## Replaced and retained -The builder does not create sentence/sense/synset/n-gram singleton objects, -occurrence-object ledgers, closure graphs, synthetic relation circles, -tangencies, attention frames, or duplicate JSON copies of the database. It does -not synthesize weights, displacement vectors, Cartesian coordinates, centers, -radii, motion, or tangency. The separate Hilbert candidate constructs -mathematical state vectors from axes already declared by this construction; it -does not supply a displacement law. +The structural-only build is **deprecated as a completed geometric construction**. +`structural_construct` remains the verified source-admission/replay stage consumed +by the replacement, not a competing geometry. `StructuralField` inspects that +source stage only. Its 13-file sealed import closure remains unchanged so existing +source evidence remains independently replayable. -### Verified full-corpus result +Full construct v2, orthogonal-axis placement and constituent-overlap views are +**historical, not supported routes for new construction**. Their old build commands +are removed from this entrypoint and usage path. Retained source modules support +sealed admission and explicitly historical replay; retention grants no current +geometry authority. The supported CLI rejects retired profile commands and does +not silently return an old artifact when the ordinal constructor is unavailable. -Evidence is committed in `experiments/full-construct-v2/`. +Historical documentation and evidence: -- 118 shared character identities -- 164,864 shared word identities -- 1,739,949 ordered word-character references -- 185,155 word-anchored definitions -- 3,535,375 exact ordered definition components -- 866,183 resolved semantic evidence rows -- 0 unresolved semantic evidence rows -- SQLite integrity: `ok` -- logical receipt: `12277b4959c0c72b7af12097b8a77bf91866bbf669e7f4ac07b6a5f1426ebb57` -- generated database: 306,331,648 bytes -- build wall time: 1:34.79 -- peak RSS: 286,692 KiB +- [Full construct v2](docs/full-construct-v2.md) and `experiments/full-construct-v2/`. +- [Four-view audit](docs/hyperspace-views-full-v1.md) and `FULL_VIEW_AUDIT.json`. +- [Hilbert candidate](docs/hilbert-inference.md), a separately declared historical + representation, not the new relational geometry or evidence of inference quality. -The database itself remains generated state; the compact manifest, integrity -receipt, and resource receipt are committed. +The previous active profile's [segmentation contract](docs/structural-profile-v1.md) +remains the source-admission contract. Punctuation is not silently folded into word +identity; raw source, shared words, exact scalars and ordered participation survive. +Any future source-rule alteration needs its own profile and complete replay. -## Run historical v2 +## Tests and migration ```bash -python -m english_gonol.full_construct_run \ - --source-root /path/to/oewn-2025/src/yaml \ - --ucns-source-root /path/to/ucns \ - --out-dir experiments/full-construct-v2 +python -m pytest -q research/english-gonol/tests ``` -Tests: - -```bash -python -m pytest -q tests -``` - -See [`docs/full-construct-v2.md`](docs/full-construct-v2.md). - -## Four-view full-corpus audit +Use the UCNS dependency specified by the work graph. The new default's tests cover +ordinal-only routing, retired-command rejection, selection mismatch and no-compute +profile/help. Geometry tests and full-corpus replay remain separate witnesses. -The [complete view report](docs/hyperspace-views-full-v1.md) covers all **164,864 words**, -all fifteen nonempty view combinations, and three complete address-renumbering controls. -Native and independent evidence agree exactly, including per-word native reconstruction. -The synthesis distinguishes 137,013 values. Removing view 1, 2, or 3 loses 10,267, -20,042, or 125,813 distinctions respectively; removing view 4 loses none. - -View 1 is nullable constituent-overlap metadata, view 2 is the terminal phase/frame, -view 3 carries coarse address/provenance information, and view 4 is a derivable witness. -Their inference usefulness requires a task beyond distinctness. The frozen protocol is -[`FULL_VIEW_AUDIT.json`](FULL_VIEW_AUDIT.json); complete receipts are in -[`experiments/hyperspace-views-full-v1/`](experiments/hyperspace-views-full-v1/). -The report contains the exact source/database bindings and full replay commands. - -## Historical research - -The orthogonal-carrier sweep and earlier definition-affixiation run remain -separate experiments and supply no placement law to v2. The falsified -`full_singleton_run.py` architecture and its UCNS singleton-axis support were -deleted rather than retained as an active precedent. - -## Migration standing - -The current lifecycle record is [`MIGRATION.json`](MIGRATION.json). UCHC is -extracted and has a clean-installed immutable candidate verified in Stack, but -stable publication, released-artifact reconsumption, severance of the local -implementation path and a scoped authority-transition receipt remain incomplete. -Stack therefore remains the implementation forge for this new candidate. +[MIGRATION.json](MIGRATION.json) retains the UCHC extraction/release standing. +Older pinned consumers are not silently upgraded by this source merge. They must +consume the new profile explicitly and replay their own contracts; historical +metrics are not renamed as ordinal measurements. ## hmmm -The exact UCNS law mapping ordinal + semantic + sentence-context evidence to -geometric displacement remains unresolved. No English-layer rule may fill that -boundary with invented weights, directions, distances, displacement vectors, -Cartesian coordinates, centers, radii, tangencies, or motion. - -For the Hilbert candidate, the canonical scalar field (`R` or `C`), -cross-origin inner products/angles, amplitudes/phases, learned inference -operators, sense selection, sentence-axis promotion and completed UCHC -graduation remain unresolved. +[Questions and remaining work](docs/ordinal-questions.md) distinguish missing +construction laws from engineering work. The radius/angle rule is settled; +global frame transport, compound origins, native Mobius lift, operator actions +and downstream inference evidence remain open. diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index 21b9a25..79b61cd 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -1,7 +1,7 @@ # English ordinal construction — replacement profile Operator request: radial distance is repeated halving by occurrence ordinal; -angle is defined by the newly expanded public gonol. This profile constructs +angle is defined by the newly expanded public gonol. This selected replacement profile constructs that law instead of reinterpreting the previous orthogonal or overlap metrics. ## Public gonol @@ -69,10 +69,10 @@ python -m english_gonol.structural_construct build \ --source-root /path/to/pinned-oewn/src/yaml \ --ucns-source-root /path/to/pinned-admission-carrier \ --out-dir /path/to/new-admission -python -m english_gonol.ordinal_construct build \ +python -m english_gonol build \ /path/to/new-admission /path/to/unicode-18-ucd /path/to/new-geometry -python -m english_gonol.ordinal_construct verify /path/to/new-geometry -python -m english_gonol.ordinal_construct query /path/to/new-geometry 'the geometry' +python -m english_gonol verify /path/to/new-geometry +python -m english_gonol query /path/to/new-geometry 'the geometry' ``` Full corpus means the source verifier has replayed the exact 73-file OEWN tree @@ -87,8 +87,9 @@ Unicode file or unit-test success alone is not complete-corpus evidence. artifact verification; UCNS owns the geometric law. `tests/test_ordinal_construct.py` owns fixture/property regressions. The workflow owns explicit input acquisition and full replay. `ordinal-work-graph.json` binds input ownership and exact source -states. No root Stack participant, release pin, UCHC graduation or website is -changed. The candidate source commit is recorded by hosted evidence, avoiding a +states. The supported entrypoint and retirement are declared in `../ACTIVE_CONSTRUCTION.json`. +No root Stack participant, release pin, UCHC graduation or website is +changed. The construction source commit is recorded by hosted evidence, avoiding a self-referential committed head hash. Expected working footprint is below 4 GiB; the hosted runner checks free disk @@ -104,4 +105,5 @@ The layout choices are explicit and replaceable only through a new profile and full rebuild. Native Mobius lift, global transport/definition-origin attachment, operator function semantics, inference quality and UCHC release remain separate questions. Local placement does not manufacture evidence for those questions. -A complete hosted receipt must exist before claiming complete-corpus success. +Complete hosted construction and replay have succeeded. See `ordinal-questions.md` +for unresolved construction laws and the separate downstream migration work. diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md new file mode 100644 index 0000000..36d4e35 --- /dev/null +++ b/research/english-gonol/docs/ordinal-questions.md @@ -0,0 +1,93 @@ +# Ordinal construction: answers still needed + +The selected implementation is `english.ordinal/1`; inspect it with +`PYTHONPATH=research/english-gonol python -m english_gonol profile`. +Run `verify OUTPUT` before using a generated field. These boundaries do not +reopen the specified ordinal-distance/carrier-angle rule or block its use. + +## Already answered and implemented + +For zero-based ordinal i among n participants, radius is R/2**(n-i); the newest +participant is at R/2. Angle is the participant's exact index/arity on its +explicit carrier. Closed interiors survive recursive atomic participation. +The initial equidistant field and its circular placement are distinct stages; +planar placement is not claimed to preserve all initial pairwise distances. + +This selected version uses balanced insertion around inherited scalar anchors, +and orders its word carrier by sequences of public-gonol indexes. These are +explicit implementation choices, not discovered semantic laws. This merge keeps +them fixed; changing either requires a new profile and rebuilt receipts. + +## Construction questions, ordered by dependency + +### 1. How do nested local frames become one geometric construction? + +The current operation retains a closed word and places that participant within +a parent. It does not specify the translation, orientation or scale transporting +the word's interior frame into the parent's frame. What exact relation supplies +that attachment, including which origin and radius are inherited? + +Current behavior: preserve separate local frames and their links. Do not add an +implicit rotation, translation or scale law. Completion witness: an explicit UCNS +transport with nested-order recovery and a tested composition law. This is the +highest-leverage unanswered geometric question. + +### 2. Where does a multiword lexical entry's definition attach? + +The source stage preserves compound entries and definitions with their exact +source ownership; it does not invent a single-word origin for a multiword entry. +Does its closed lexical construction supply that origin, and by what attachment +operation? The ordinal builder can position its participants without pretending +that local positions settle the origin relation. + +Completion witness: every compound definition has a source-bound attachment that +preserves its entry, constituent order and definition succession. + +### 3. How does this visible-circle construction lift into native Mobius state? + +The new local law supplies exact visible turns. The missing operation must state +how those turns carry frame/sheet state and preserve the native distinction +between a 360-degree visible return and a 720-degree complete local return. +No ad-hoc doubled angle supplies that proof. + +Completion witness: native-state transport and return tests, not a rendering. + +### 4. Which admitted operator positions perform which actions? + +A numeral, mathematical sign or logical operator currently receives an exact +scalar identity and angle. Admission does not implement arithmetic, implication, +quantification or any other action. What source-owned operation supplies each +function, and how does applying it change a construction? + +Current behavior: preserve literal position and occurrence only. Completion +witness: declared operations with positive and adversarial behavioral tests. + +### 5. How should previously unseen words and future carrier members enter? + +Current behavior: exact pinned repertoire; queries refuse unknown words and +unadmitted scalars, with no normalization or dynamic carrier mutation. A new +carrier/profile must rebuild all affected placements because changing N or order +changes angles. Supporting open-text word closure requires an explicit composite +carrier admission rule; it must not use a last-glyph angle or an invented hash +angle as a substitute. + +Completion witness: deterministic growth/upgrade policy, old-profile replay, and +no silent reinterpretation of previously constructed objects. + +## Engineering work, not questions to send back to the operator + +- Separate the source-admission helper closure from the historical builder modules + before physically removing those modules. They are retired as new-construction + routes now; deleting dependencies first would break the replacement's verifier. +- Migrate the extracted UCHC candidate and each pinned EDCM/ZFAE/a0 consumer through + its own exact input and replay contract. This source selection is not an + independent release, deployment, or retroactive recertification. +- Publish the complete generated artifact on a durable, versioned distribution + surface; GitHub Actions artifacts have their own retention lifecycle. +- Select a concrete downstream task and predeclared comparison to test utility. + Exact construction and recovery do not establish inference quality. + +## hmmm + +Merge closes source integration and default selection. It does not manufacture +answers to the five construction questions or mark downstream migration complete. diff --git a/research/english-gonol/english_gonol/__main__.py b/research/english-gonol/english_gonol/__main__.py new file mode 100644 index 0000000..de6175d --- /dev/null +++ b/research/english-gonol/english_gonol/__main__.py @@ -0,0 +1,88 @@ +"""Supported English construction entry point; retired profiles have no fallback. + +Usage: python -m english_gonol profile + python -m english_gonol build ADMISSION UCD NEW_OUTPUT + python -m english_gonol verify OUTPUT + python -m english_gonol query OUTPUT 'the geometry' + +Build consumes verified source admission; admission alone is not completed +geometry. Writes and full-corpus replay remain owned by ordinal_construct. +""" +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +# === MODULE_BUILD === +# id: english_active_construction_entrypoint +# module_name: __main__ +# module_kind: adapter +# summary: selects the ordinal constructor without restoring deprecated build routes +# owner: Erin Spencer +# public_surface: main +# internal_surface: active_profile +# tests: tests/test_active_construction.py +# auth_boundary: none +# storage_boundary: write +# network_boundary: none +# user_data_boundary: read +# admin_only: false +# rollout: default package entrypoint selected by ACTIVE_CONSTRUCTION.json +# rollback: revert selection explicitly; never silently substitute historical geometry +# unresolved: historical consumer migration is separate from this source default +# === END MODULE_BUILD === +# === CONTRACTS === +# id: english_active_no_legacy_fallback +# given: a build, verification or query through the supported package entrypoint +# then: only the selected ordinal implementation runs; retired or inconsistent profiles fail closed +# id: english_profile_without_compute +# given: a profile or help request +# then: show selection or usage without loading geometry or replaying the corpus +# === END CONTRACTS === + + +def active_profile() -> dict: + """Read the source-owned selection, independent of installed geometry packages.""" + path = Path(__file__).resolve().parents[1] / 'ACTIVE_CONSTRUCTION.json' + profile = json.loads(path.read_text(encoding='utf-8')) + if (profile.get('schema') != 'english.active-construction/1' + or profile.get('implementation') != 'english_gonol.ordinal_construct' + or profile.get('fallback') != 'none'): + raise ValueError('invalid active construction selection; no legacy fallback') + return profile + + +def main(argv: list[str] | None = None) -> None: + """Run only the current construction; historical commands are not selectable.""" + parser = argparse.ArgumentParser(description=__doc__) + commands = parser.add_subparsers(dest='command', required=True) + commands.add_parser('profile', help='show selection and unresolved boundaries; no compute') + build = commands.add_parser('build', help='complete ordinal geometry from source admission') + for name in ('admission', 'ucd', 'output'): + build.add_argument(name, type=Path) + verify = commands.add_parser('verify', help='independently replay the complete construction') + verify.add_argument('output', type=Path) + query = commands.add_parser('query', help='verify then construct exact admitted text') + query.add_argument('output', type=Path) + query.add_argument('text') + args = parser.parse_args(argv) + profile = active_profile() + if args.command == 'profile': + value = profile + else: + from english_gonol import ordinal_construct as constructor + if (profile['active_profile'] != constructor.PROFILE + or profile['geometry_commit'] != constructor.UCNS_COMMIT): + raise ValueError('active selection differs from constructor; no legacy fallback') + if args.command == 'build': + value = constructor.build(args.admission, args.ucd, args.output) + elif args.command == 'verify': + value = constructor.verify(args.output) + else: + value = constructor.query(args.output, args.text) + print(json.dumps(value, ensure_ascii=False, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py new file mode 100644 index 0000000..2d91875 --- /dev/null +++ b/research/english-gonol/tests/test_active_construction.py @@ -0,0 +1,76 @@ +"""Run with pytest; routing witnesses do not claim complete-corpus replay.""" +# === CHECKS === +# id: english_active_routing_regression +# proves: english_active_no_legacy_fallback +# call: self::test_only_ordinal_routes +# requires: python3, pytest +# timeout: 60 +# mutates: monkeypatched in-memory functions only +# cleanup: pytest monkeypatch +# id: english_active_profile_regression +# proves: english_profile_without_compute +# call: self::test_profile_and_help_do_not_load_constructor +# requires: python3, pytest +# timeout: 60 +# mutates: isolated subprocess only +# cleanup: process exit +# === END CHECKS === +import json +from pathlib import Path +import subprocess +import sys + +import pytest +from english_gonol import __main__ as entry +from english_gonol import ordinal_construct + + +@pytest.mark.parametrize('args,method,expected', [ + (['build', 'admission', 'ucd', 'output'], 'build', (Path('admission'), Path('ucd'), Path('output'))), + (['verify', 'output'], 'verify', (Path('output'),)), + (['query', 'output', 'the geometry'], 'query', (Path('output'), 'the geometry')), +]) +def test_only_ordinal_routes(monkeypatch, capsys, args, method, expected): + calls = [] + def witness(*values): + calls.append(values) + return {'called': method} + monkeypatch.setattr(ordinal_construct, method, witness) + entry.main(args) + assert calls == [expected] + assert json.loads(capsys.readouterr().out) == {'called': method} + + +@pytest.mark.parametrize('command', ['legacy', 'structural', 'full-v2']) +def test_retired_commands_refuse(command): + with pytest.raises(SystemExit) as error: + entry.main([command]) + assert error.value.code == 2 + + +def test_selection_drift_refuses(monkeypatch): + selection = entry.active_profile() + selection['active_profile'] = 'retired-profile' + monkeypatch.setattr(entry, 'active_profile', lambda: selection) + with pytest.raises(ValueError, match='no legacy fallback'): + entry.main(['verify', 'never-opened']) + + +def test_profile_and_help_do_not_load_constructor(): + for args in (['profile'], ['--help']): + script = ("import sys; from english_gonol.__main__ import main\n" + "try: main(" + repr(args) + ")\n" + "except SystemExit as exc: assert exc.code == 0\n" + "assert 'english_gonol.ordinal_construct' not in sys.modules\n") + result = subprocess.run([sys.executable, '-c', script], text=True, capture_output=True) + assert result.returncode == 0, result.stderr + assert result.stdout + + +def test_active_selection_matches_exact_constructor(): + profile = entry.active_profile() + assert profile['active_profile'] == ordinal_construct.PROFILE + assert profile['geometry_commit'] == ordinal_construct.UCNS_COMMIT + assert profile['fallback'] == 'none' + assert profile['deprecated_as_completed_geometry'] + assert profile['hmmm'] From 4c9470d90c3a7632b9a8d14964fbe2f1f3dc6214 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 02:48:50 -0700 Subject: [PATCH 04/25] Bind ordinal replacement in Stack provenance and restore retained language boundaries Register the selected source and six exact input roles in root machine/human projections; update English BASE without rewriting extraction provenance or libs snapshots. Restore identity, recursive scale and EDCM measurement-only clauses caught by unchanged language-authority tests. Add source-registration/digest regression. Local focused rerun: 50 passed. Geometry and the thirteen-file admission closure remain unchanged. --- STACK_MANIFEST.md | 36 ++++++++-- research/english-gonol/BASE.json | 16 ++++- research/english-gonol/README.md | 12 ++++ .../docs/ordinal-construction.md | 5 +- .../tests/test_active_construction.py | 31 +++++++++ stack-manifest.json | 65 ++++++++++++++++++- 6 files changed, 154 insertions(+), 11 deletions(-) diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index d56996f..f329cd0 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -17,7 +17,7 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `f4acf6c40732f486388ed43df896d6e21590f1bf567310a0f45814c56d506268` + `74e65b830160887dd2ea27d84cb6b53b91135339b64acb7d51d0f8c407569297` - Weave workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - Pi radix workspace creation UTC: `2026-10-10`; bounded cross-base computation starts from Stack `ccf707f933a9611d7b7fe13a0417378d8b453a14` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) @@ -53,6 +53,31 @@ meaning used by that repository. | `The-Interdependency/ptcna` | `97abdd1bbda61a68e0aac8595a32a3cb0ce73487` | main | prime tensor circled neural architecture | canon view `libs/ptcna/`; research `research/ptcna/` | | `The-Interdependency/epac` | `949cb1cb304927942966c9fb396caf6227120e7f` | v0.1.0 | independent implementation and public-contract authority for EPAC | immutable release artifact consumer at integration/epac/; historical forge evidence at research/epac/; libs/epac/ remains unpopulated | +## Selected English ordinal construction + +`english.ordinal/1` replaces the previous completed-geometry default in +`research/english-gonol/`. The exact implementation baseline and its inputs are +research participants; no canonical `libs/` pin is refreshed. The earlier v2 +and four-view records below remain historical evidence, not current geometry. +Use `PYTHONPATH=research/english-gonol python -m english_gonol profile` to inspect +selection, and see [the supported build](research/english-gonol/README.md). + +| Participant ID | Repository | Exact commit | Relation | +|---|---|---|---| +| `ordinal-source` | `The-Interdependency/stack` | `0e0ea9ebe64803e810793dd4780253d7d202fecc` | selected ordinal implementation and default route; source baseline is not independent UCHC release authority | +| `ordinal-geometry` | `The-Interdependency/ucns` | `a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb` | merged UCNS #241 producer; exact local radius and carrier angle law, not global transport or semantic authority | +| `ordinal-admission` | `The-Interdependency/stack` | `e3eb83764355b4b760a79323cda6a6d75c3a501a` | unchanged thirteen-file source-reader closure; source admission is not the selected completed geometry | +| `ordinal-admission-carrier` | `The-Interdependency/ucns` | `4f863ad37096b7baab8f62820ad5cb937b62a3a7` | inherited scalar identity admission only; these historical angles do not supply the replacement placement | +| `ordinal-corpus` | `globalwordnet/english-wordnet` | `dc343f2683279ecbb13fab4e2fd778d7b162d287` | all exact pinned source records consumed by the ordinal construction | +| `ordinal-doctrine` | `The-Interdependency/skill-lib` | `e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128` | separately pinned ordinal work graph doctrine; root operational snapshot remains unchanged | + +UCNS #241 merged at `6ebbf970ad13a0d2e1c13bd65c496b671e740185`; +the source consumer remains pinned to the tested producer bytes above. The +source-admission closure remains support, not an alternate completed geometry. +[ACTIVE_CONSTRUCTION.json](research/english-gonol/ACTIVE_CONSTRUCTION.json) owns +default selection and [the question record](research/english-gonol/docs/ordinal-questions.md) +separates unanswered construction laws from remaining engineering work. + ## Research-Only Composition Participants These records bind stack-local research inputs without refreshing `libs/`, @@ -221,9 +246,10 @@ release lock and acceptance evidence. EPAC consumes exact UCNS `6eea1828a34ed8ec Stack's direct `libs/ucns/` and separate research UCNS pins remain unchanged. English Gonol Construction remains stack-local research, not EDCM and not an independent -canonical release. Its v2 full pinned-corpus construction/replay survived with compact -committed evidence; that result establishes the construction/replay only, not semantic -quality, geometry canon, or measurement validity. +canonical release. The selected `english.ordinal/1` local construction is distinct +from the historical v2 and four-view receipts. Complete source and ordinal replay +establish construction/recovery, not semantic quality, general geometry canon or +measurement validity. Python Gonol Construction is also stack-local research. Its Python 3.12 source constructor has no independent repository/release authority, and its successful replay @@ -244,7 +270,7 @@ establish a base-independent generating law. ## hmmm - UCNS has no `LICENSE` file at pinned commit `828c0b8`. -- English Gonol Construction remains stack-local research; independent repository/release authority and the exact UCNS displacement law have not been established. +- English Gonol Construction has selected exact local ordinal geometry; global frame transport, compound origins, native Mobius lift, operator actions and independent release remain unresolved. - Python Gonol Construction remains stack-local research; independent repository/release authority and exact UCNS affixiation geometry remain unresolved. - URPCS is retired for specification divergence; why GPT flattened/substituted the intended construction remains unresolved, and retained evidence is scoped only to the substituted implementation. - Weave now runs one explicit native sequence-cycle profile with corpus normalization and prime-derived splits; cryptographic lifting, authentication/state and full-cipher security remain unresolved. diff --git a/research/english-gonol/BASE.json b/research/english-gonol/BASE.json index e80065f..2928b68 100644 --- a/research/english-gonol/BASE.json +++ b/research/english-gonol/BASE.json @@ -6,8 +6,8 @@ "source_commit": "7951ca32ba0f2494dc68ff9b7f6a80151918a56d", "ucns_prerequisite": { "repository": "The-Interdependency/ucns", - "commit": "1975fe70cf4e0826a8020c2da3047569e277af64", - "relation": "English Gonol Construction consumes UCNS geometry; UCNS owns geometry and representation" + "commit": "a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb", + "relation": "selected English ordinal construction consumes exact UCNS geometry; root libs/ucns and the extraction source remain historical pins" }, "canon_path": "../../libs/edcm", "authority": "stack-local research component (extracted from The-Interdependency/edcm)", @@ -24,5 +24,17 @@ "commit": "0873c105799681ea1f7ccb3e619d1f7aebbd85e0", "relation": "exact EDCM semantic metric-origin producer with canonical O/L split; does not refresh the historical extraction source or libs/edcm pin", "authority_transfer": false + }, + "historical_ucns_prerequisite": { + "repository": "The-Interdependency/ucns", + "commit": "1975fe70cf4e0826a8020c2da3047569e277af64", + "relation": "English Gonol Construction consumes UCNS geometry; UCNS owns geometry and representation" + }, + "active_construction": { + "selection": "ACTIVE_CONSTRUCTION.json", + "source_repository": "The-Interdependency/stack", + "source_commit": "0e0ea9ebe64803e810793dd4780253d7d202fecc", + "work_graph": "../../stack-manifest.json#research_participants[workspace=research/english-gonol/]", + "authority_transfer": false } } diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index c9321da..a29c130 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -35,6 +35,18 @@ EDCM may measure completed outputs but does not define them. Selecting this profile does not graduate UCHC or refresh the root `libs/` snapshots. The exact work graph in `docs/ordinal-work-graph.json` binds the consumed geometry separately. +## Identity and scale + +In this text-domain construction, every admitted character is a gonol: +one exact scalar -> one shared character identity; one exact surface -> one shared word identity. +Once closed, a gonol is atomic at an admissible consuming scale, while its ordered +interior remains recoverable. This does not impose a mandatory adjacent-scale ladder. + +Authority routing remains METAPAT -> affixiation semantics; UCNS -> exact geometry; +English Gonol Construction -> text-domain participants; EDCM -> measurement/evaluation only. +Construction/recovery does not validate EDCM measurement. See +[the language boundary](docs/GONOL_LANGUAGE_BOUNDARY.md). + ## Replaced and retained The structural-only build is **deprecated as a completed geometric construction**. diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index 79b61cd..fd56381 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -88,8 +88,9 @@ artifact verification; UCNS owns the geometric law. `tests/test_ordinal_construc owns fixture/property regressions. The workflow owns explicit input acquisition and full replay. `ordinal-work-graph.json` binds input ownership and exact source states. The supported entrypoint and retirement are declared in `../ACTIVE_CONSTRUCTION.json`. -No root Stack participant, release pin, UCHC graduation or website is -changed. The construction source commit is recorded by hosted evidence, avoiding a +The root research-participant manifest and English BASE explicitly record the +selected source and inputs. Canonical release pins, UCHC graduation and the website +remain unchanged. The construction source commit is recorded by hosted evidence, avoiding a self-referential committed head hash. Expected working footprint is below 4 GiB; the hosted runner checks free disk diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 2d91875..1f4b968 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -74,3 +74,34 @@ def test_active_selection_matches_exact_constructor(): assert profile['fallback'] == 'none' assert profile['deprecated_as_completed_geometry'] assert profile['hmmm'] + + +def test_active_inputs_are_registered_in_root_provenance(): + import hashlib + workspace = Path(entry.__file__).resolve().parents[1] + root = workspace.parents[1] + profile = entry.active_profile() + manifest = json.loads((root / 'stack-manifest.json').read_text()) + base = json.loads((workspace / 'BASE.json').read_text()) + graph = json.loads((workspace / profile['input_graph']).read_text()) + human = (root / 'STACK_MANIFEST.md').read_text() + records = [r for r in manifest['research_participants'] + if r['workspace'] == 'research/english-gonol/'] + keyed = {r['participant_id']: r for r in records} + assert len(keyed) == len(records), 'duplicate source-qualified participant' + source_pairs = {(r['repository'], r['commit']) for r in records} + assert all((r['repository'], r['commit']) in source_pairs + for r in graph['repositories']) + assert keyed['ordinal-geometry']['commit'] == profile['geometry_commit'] + assert base['ucns_prerequisite']['commit'] == profile['geometry_commit'] + assert base['active_construction']['selection'] == 'ACTIVE_CONSTRUCTION.json' + assert base['active_construction']['source_commit'] == keyed['ordinal-source']['commit'] + assert all(r['authority_transfer'] is False for r in records) + payload = {k: manifest[k] for k in ('repositories', 'research_participants', 'boundaries')} + digest = hashlib.sha256(json.dumps(payload, sort_keys=True, separators=(',', ':')).encode()).hexdigest() + assert digest == manifest['work_graph_sha256'] + assert digest in human + for participant_id, record in keyed.items(): + assert record['commit'] in human + if participant_id.startswith('ordinal-'): + assert participant_id in human diff --git a/stack-manifest.json b/stack-manifest.json index a061691..445bab7 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "f4acf6c40732f486388ed43df896d6e21590f1bf567310a0f45814c56d506268", + "work_graph_sha256": "74e65b830160887dd2ea27d84cb6b53b91135339b64acb7d51d0f8c407569297", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -73,7 +73,8 @@ "Weave has an explicit Stack-owned native binary sequence-cycle candidate with exact recovery; other profiles, private/public lifting, authentication/state and full-cipher security remain unresolved.", "Weave native public/private key derivation and source of asymmetry remain unresolved; source-bound key metadata does not establish a native asymmetric law.", "a0 Municipality is specification-first composition research; native semantic-origin/affixiation integration, operational authorities and its fifth workflow remain unresolved; no runtime or six-month proof is established by placement.", - "Pi radix research has measured finite cross-base recurrences; a base-independent segmentation or generating law remains unestablished, and no pi normality or cryptographic security follows from the finite prefixes." + "Pi radix research has measured finite cross-base recurrences; a base-independent segmentation or generating law remains unestablished, and no pi normality or cryptographic security follows from the finite prefixes.", + "English ordinal/1 is the selected local construction; nested frame transport, compound origin attachment, native Mobius lift, operator actions and downstream migration remain unresolved." ] }, "research_participants": [ @@ -472,6 +473,66 @@ "relation": "pinned doctrine for the module, tests, research receipts and Stack transaction; no authority transfer", "authority_transfer": false, "canonical_release": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-source", + "repository": "The-Interdependency/stack", + "commit": "0e0ea9ebe64803e810793dd4780253d7d202fecc", + "authority": "English construction and supported entrypoint", + "relation": "selected ordinal implementation and default route; source baseline is not independent UCHC release authority", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-geometry", + "repository": "The-Interdependency/ucns", + "commit": "a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb", + "authority": "generic exact ordinal geometry", + "relation": "merged UCNS #241 producer; exact local radius and carrier angle law, not global transport or semantic authority", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-admission", + "repository": "The-Interdependency/stack", + "commit": "e3eb83764355b4b760a79323cda6a6d75c3a501a", + "authority": "English source admission and independent replay", + "relation": "unchanged thirteen-file source-reader closure; source admission is not the selected completed geometry", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-admission-carrier", + "repository": "The-Interdependency/ucns", + "commit": "4f863ad37096b7baab8f62820ad5cb937b62a3a7", + "authority": "historical carrier provenance", + "relation": "inherited scalar identity admission only; these historical angles do not supply the replacement placement", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-corpus", + "repository": "globalwordnet/english-wordnet", + "commit": "dc343f2683279ecbb13fab4e2fd778d7b162d287", + "authority": "complete English corpus evidence", + "relation": "all exact pinned source records consumed by the ordinal construction", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-doctrine", + "repository": "The-Interdependency/skill-lib", + "commit": "e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128", + "authority": "build and evidence discipline", + "relation": "separately pinned ordinal work graph doctrine; root operational snapshot remains unchanged", + "canonical_release": false, + "authority_transfer": false } ] } From 4dea37abee6e88325bad137acfdbf9849ca7b7af Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 03:05:38 -0700 Subject: [PATCH 05/25] Bind complete Unicode release and verified manifest claims; cover admission CI inputs Repair the three remaining #88 review findings. Admit only the two complete pinned Unicode 18.0.0 file hashes; synthetic parser/layout fixtures cannot be called the release. Enforce exact manifest schema and fixed uncertainty claims before replay, reject false extra status fields and malformed counts/receipts, and emit source-owned boundary text. Include the entire admission module closure in the full-corpus workflow path filter. Local focused regression: 64 passed. Complete retained UCD bytes passed the new public loader. Full hosted reconstruction is required for this changed verifier implementation; previous manifest receipts are not promoted. --- .../workflows/english-ordinal-affixiation.yml | 3 +- .../english_gonol/ordinal_construct.py | 81 +++++++++--- .../tests/test_active_construction.py | 15 +++ .../tests/test_ordinal_construct.py | 119 ++++++++++++++++-- 4 files changed, 186 insertions(+), 32 deletions(-) diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index 2427575..6745d35 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -3,8 +3,7 @@ on: workflow_dispatch: pull_request: paths: - - 'research/english-gonol/english_gonol/ordinal_construct.py' - - 'research/english-gonol/english_gonol/__main__.py' + - 'research/english-gonol/english_gonol/**' - 'research/english-gonol/ACTIVE_CONSTRUCTION.json' - 'research/english-gonol/tests/test_active_construction.py' - 'research/english-gonol/tests/test_ordinal_construct.py' diff --git a/research/english-gonol/english_gonol/ordinal_construct.py b/research/english-gonol/english_gonol/ordinal_construct.py index cdf94ef..159939a 100644 --- a/research/english-gonol/english_gonol/ordinal_construct.py +++ b/research/english-gonol/english_gonol/ordinal_construct.py @@ -58,6 +58,22 @@ PROFILE = 'english.ordinal/1' UNICODE_VERSION = '18.0.0' UCD_FILES = ('UnicodeData.txt', 'DerivedCoreProperties.txt') +# Exact complete Unicode 18.0.0 release bytes, retained in the full-corpus artifact. +# Admission pins content, not a header, local registry, or minimal ASCII subset. +UCD_RELEASE_SHA256 = { + 'UnicodeData.txt': '0736451de439ae7baf1425136617da495e09ee5afbe6e394374db7009ea08950', + 'DerivedCoreProperties.txt': '09c928886a178fcafd93c29e4bd59073a058e5a100b716d425cb563ab50f68c9', +} +MANIFEST_BOUNDARIES = ( + 'Local frame placement is constructed; global origin attachment is not inferred.', + 'Layout recipes are explicit profile choices, not discovered semantic laws.', + 'Native Mobius lift and inference quality remain untested.', +) +MANIFEST_KEYS = frozenset(( + 'schema', 'source_receipt', 'source', 'ucns_commit', 'implementation_sha256', + 'public_sha256', 'glyph_carrier_receipt', 'word_carrier_receipt', 'counts', + 'geometry_receipt', 'hmmm', +)) LOGIC = tuple('¬∧∨⊻⊼⊽→←↔⇒⇐⇔∀∃∄⊢⊣⊤⊥⊨⊭⊬⊮⊯≡≠=<>≤≥') LAYOUT = 'legacy-anchor-balanced-insertion/1' WORD_LAYOUT = 'lexicographic-public-gonol-index-sequences/1' @@ -112,12 +128,11 @@ def _range(value: str) -> range: return range(first, last + 1) -def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: - """Read numeric categories and the derived Math property, never host Unicode.""" +def _parse_unicode_properties(blobs: dict[str, bytes], version: str): + """Parse supplied property syntax; this helper establishes no release identity.""" numbers: set[str] = set() maths: set[str] = set() pending = None - blobs = {name: (ucd / name).read_bytes() for name in UCD_FILES} if any(len(raw) > 10_000_000 for raw in blobs.values()): raise ValueError('Unicode input exceeds per-file acquisition budget') data = blobs[UCD_FILES[0]].decode('utf-8') @@ -149,7 +164,7 @@ def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: if pending is not None: raise ValueError('unterminated UnicodeData range') derived = blobs[UCD_FILES[1]].decode('utf-8') - if f'DerivedCoreProperties-{UNICODE_VERSION}.txt' not in derived[:4096]: + if f'DerivedCoreProperties-{version}.txt' not in derived[:4096]: raise ValueError('Unicode release header mismatch') for line in derived.splitlines(): body = line.split('#', 1)[0].strip() @@ -163,13 +178,22 @@ def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: return numbers, maths, {name: sha256(blobs[name]).hexdigest() for name in UCD_FILES} -def repertoire(corpus: tuple[str, ...], legacy: tuple[str, ...], ucd: Path) -> dict: - """Expand the repertoire without assigning Unicode categories geometric roles.""" + +def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: + """Admit only the complete pinned release; never trust a self-declared header.""" + blobs = {name: (ucd / name).read_bytes() for name in UCD_FILES} + for name, raw in blobs.items(): + if sha256(raw).hexdigest() != UCD_RELEASE_SHA256[name]: + raise ValueError(f'Unicode release hash mismatch: {name}; complete pinned release required') + return _parse_unicode_properties(blobs, UNICODE_VERSION) + + +def _layout_repertoire(corpus, legacy, numbers, maths, hashes, unicode_version): + """Lay out already admitted identities; fixture callers must label their source.""" for c in (*corpus, *legacy): scalar(c) if len(set(legacy)) != len(legacy) or not legacy or legacy[0] != ' ': raise ValueError('legacy anchors must be unique with SPACE first') - numbers, maths, hashes = unicode_admission(ucd) admitted = set(corpus) | set(legacy) | numbers | maths | set(LOGIC) extras = sorted(admitted - set(legacy), key=ord) order: list[str] = [] @@ -179,7 +203,7 @@ def repertoire(corpus: tuple[str, ...], legacy: tuple[str, ...], ucd: Path) -> d (i + 1) * len(extras) // len(legacy)]) if len(order) != len(admitted) or set(order) != admitted: raise AssertionError('repertoire union lost or duplicated a scalar') - return {'schema': 'english.public-gonol/1', 'unicode_version': UNICODE_VERSION, + return {'schema': 'english.public-gonol/1', 'unicode_version': unicode_version, 'layout': LAYOUT, 'normalization': 'none', 'origin_scalar': ' ', 'corpus_scalars': sorted(corpus, key=ord), 'legacy_anchors': list(legacy), 'unicode_files_sha256': hashes, 'logical_supplement': list(LOGIC), @@ -190,6 +214,12 @@ def repertoire(corpus: tuple[str, ...], legacy: tuple[str, ...], ucd: Path) -> d 'identities': order} +def repertoire(corpus: tuple[str, ...], legacy: tuple[str, ...], ucd: Path) -> dict: + """Expand the repertoire only after authenticating the complete Unicode release.""" + numbers, maths, hashes = unicode_admission(ucd) + return _layout_repertoire(corpus, legacy, numbers, maths, hashes, UNICODE_VERSION) + + class Factory: """Actual recursive constructions; carriers and closed interiors remain available.""" def __init__(self, public: dict, words: dict[int, str], source_receipt: str): @@ -323,9 +353,7 @@ def build(admission: Path, ucd: Path, output: Path) -> dict: 'glyph_carrier_receipt': factory.glyph_carrier.receipt, 'word_carrier_receipt': factory.word_carrier.receipt, 'counts': counts, 'geometry_receipt': _geometry_receipt(geometry), - 'hmmm': ['Local frame placement is constructed; global origin attachment is not inferred.', - 'Layout recipes are explicit profile choices, not discovered semantic laws.', - 'Native Mobius lift and inference quality remain untested.']} + 'hmmm': list(MANIFEST_BOUNDARIES)} _json_write(stage / 'manifest.json', manifest) report = verify(stage) _json_write(stage / 'verification.json', report) @@ -361,15 +389,34 @@ def _independent_frame(kind, frame_id, identity, relation, source_receipt, refs, return (kind, frame_id, identity, 'SPACE', relation, source, receipt, n), stored -def verify(output: Path) -> dict: - """Replay every source and placement; structural bytes alone never prove new geometry.""" - from english_gonol.structural_construct import _verified_connection, open_readonly, _schema - _producer_check() - manifest = _json_read(output / 'manifest.json') +def _validate_manifest(manifest: object) -> None: + """Reject unsupported claims before source replay; this alone proves no geometry.""" + if type(manifest) is not dict or set(manifest) != MANIFEST_KEYS: + raise ValueError('manifest schema keys differ from the exact profile') if manifest['schema'] != PROFILE or manifest['ucns_commit'] != UCNS_COMMIT: raise ValueError('profile/geometry producer mismatch') if manifest['implementation_sha256'] != file_hash(Path(__file__)): raise ValueError('implementation changed; rebuild explicitly') + if manifest['hmmm'] != list(MANIFEST_BOUNDARIES): + raise ValueError('manifest boundary claims differ from the exact profile') + counts = manifest['counts'] + if (type(counts) is not dict or set(counts) != {'frames', 'placements'} + or any(type(v) is not int or v <= 0 for v in counts.values())): + raise ValueError('manifest counts must be positive integer frame/placement counts') + for key in ('source_receipt', 'public_sha256', 'glyph_carrier_receipt', + 'word_carrier_receipt', 'geometry_receipt'): + value = manifest[key] + if (type(value) is not str or len(value) != 64 + or any(c not in '0123456789abcdef' for c in value)): + raise ValueError(f'manifest digest is invalid: {key}') + + +def verify(output: Path) -> dict: + """Replay every source and placement; structural bytes alone never prove new geometry.""" + _producer_check() + manifest = _json_read(output / 'manifest.json') + _validate_manifest(manifest) + from english_gonol.structural_construct import _verified_connection, open_readonly, _schema with _verified_connection(output / 'admission') as verified: source, source_manifest = verified if not source_manifest['metadata']['complete_corpus']: @@ -433,7 +480,7 @@ def check(kind, frame_id, identity, relation, refs): 'scope': 'complete pinned corpus; source recovery plus every local placement', 'public_gonol_size': len(public['identities']), 'words': len(words), **counts, 'manifest_sha256': digest(manifest), - 'source_receipt': manifest['source_receipt'], 'hmmm': manifest['hmmm']} + 'source_receipt': manifest['source_receipt'], 'hmmm': list(MANIFEST_BOUNDARIES)} def query(output: Path, text: str) -> dict: diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 1f4b968..734a1e7 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -105,3 +105,18 @@ def test_active_inputs_are_registered_in_root_provenance(): assert record['commit'] in human if participant_id.startswith('ordinal-'): assert participant_id in human + + +def test_full_workflow_covers_admission_dependencies(): + from fnmatch import fnmatch + import yaml + workspace = Path(entry.__file__).resolve().parents[1] + root = workspace.parents[1] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + filters = workflow['on']['pull_request']['paths'] + closure = {'structural_construct.py', 'structural_rules.py', 'structural_query.py'} + closure.update(p.name for p in (workspace / 'english_gonol').glob('*.py')) + for name in closure: + path = f'research/english-gonol/english_gonol/{name}' + assert any(fnmatch(path, pattern) for pattern in filters), path diff --git a/research/english-gonol/tests/test_ordinal_construct.py b/research/english-gonol/tests/test_ordinal_construct.py index 3d28ea5..d6b5480 100644 --- a/research/english-gonol/tests/test_ordinal_construct.py +++ b/research/english-gonol/tests/test_ordinal_construct.py @@ -83,6 +83,20 @@ # timeout: 60 # mutates: temporary fixture files only # cleanup: pytest tmp_path +# id: english_ordinal_release_hash_binding +# proves: english_expanded_repertoire +# call: self::test_fixture_cannot_claim_production_release +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path +# id: english_ordinal_manifest_claim_binding +# proves: english_complete_geometry_replay +# call: self::test_modified_manifest_refuses_before_source_replay +# requires: python3, pytest +# timeout: 60 +# mutates: temporary fixture files only +# cleanup: pytest tmp_path # === END CHECKS === """Fixture tests are not full Unicode or corpus receipts; hosted build supplies those.""" @@ -90,10 +104,13 @@ import sqlite3 import pytest from english_gonol.ordinal_construct import ( - Factory, LOGIC, SQL, UNICODE_VERSION, repertoire, scalar, unicode_admission, + Factory, LOGIC, SQL, UCD_FILES, scalar, _parse_unicode_properties, _layout_repertoire, _write_frame, _independent_frame, _producer_check, ) from ucns.ordinal_affixiation import Carrier, Participant, affixiate +from english_gonol import ordinal_construct as implementation + +FIXTURE_VERSION = 'fixture-not-a-unicode-release' def ucd_fixture(tmp_path): @@ -104,18 +121,28 @@ def ucd_fixture(tmp_path): ';'.join(['2160', 'ROMAN NUMERAL ONE', 'Nl'] + [''] * 12)]) (tmp_path / 'UnicodeData.txt').write_text('\n'.join(rows) + '\n') (tmp_path / 'DerivedCoreProperties.txt').write_text( - f'# DerivedCoreProperties-{UNICODE_VERSION}.txt\n002B ; Math\n003C..003E ; Math\n2200 ; Math\n') + f'# DerivedCoreProperties-{FIXTURE_VERSION}.txt\n002B ; Math\n003C..003E ; Math\n2200 ; Math\n') return tmp_path +def parse_fixture(path): + return _parse_unicode_properties({name: (path / name).read_bytes() for name in UCD_FILES}, + FIXTURE_VERSION) + + +def fixture_repertoire(corpus, legacy, path): + numbers, maths, hashes = parse_fixture(path) + return _layout_repertoire(corpus, legacy, numbers, maths, hashes, FIXTURE_VERSION) + + def factory_fixture(tmp_path): - public = repertoire(tuple(' ABCé\u0301'), tuple(' ABC'), ucd_fixture(tmp_path)) + public = fixture_repertoire(tuple(' ABCé\u0301'), tuple(' ABC'), ucd_fixture(tmp_path)) return Factory(public, {1: 'ABA', 2: 'C', 3: 'é', 4: 'A\u0301'}, 'fixture-source') def test_union_and_layout(tmp_path): ucd = ucd_fixture(tmp_path) - public = repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) + public = fixture_repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) values = public['identities'] assert values[0] == ' ' assert [c for c in values if c in ' ABC'] == list(' ABC') @@ -124,33 +151,33 @@ def test_union_and_layout(tmp_path): anchors = [values.index(c) for c in ' ABC'] + [len(values)] counts = [b-a-1 for a,b in zip(anchors, anchors[1:])] assert max(counts) - min(counts) <= 1 - assert public == repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) + assert public == fixture_repertoire(tuple(' é\u0301'), tuple(' ABC'), ucd) def test_supplementary_scalar_not_utf16_units(tmp_path): - public = repertoire(('𝟠',), tuple(' A'), ucd_fixture(tmp_path)) + public = fixture_repertoire(('𝟠',), tuple(' A'), ucd_fixture(tmp_path)) assert public['identities'].count('𝟠') == 1 assert scalar('𝟠') == '𝟠' def test_no_normalization(tmp_path): - public = repertoire(('é','e','\u0301'), tuple(' A'), ucd_fixture(tmp_path)) + public = fixture_repertoire(('é','e','\u0301'), tuple(' A'), ucd_fixture(tmp_path)) assert all(c in public['identities'] for c in ('é','e','\u0301')) def test_wrong_version_refuses(tmp_path): root = ucd_fixture(tmp_path) path = root / 'DerivedCoreProperties.txt' - path.write_text(path.read_text().replace(UNICODE_VERSION, '17.0.0')) + path.write_text(path.read_text().replace(FIXTURE_VERSION, '17.0.0')) with pytest.raises(ValueError, match='release'): - unicode_admission(root) + parse_fixture(root) def test_missing_property_data_refuses(tmp_path): root = ucd_fixture(tmp_path) (root / 'UnicodeData.txt').write_text('') with pytest.raises(ValueError, match='incomplete'): - unicode_admission(root) + parse_fixture(root) def test_unclosed_unicode_range_refuses(tmp_path): @@ -158,17 +185,17 @@ def test_unclosed_unicode_range_refuses(tmp_path): with (root / 'UnicodeData.txt').open('a') as stream: stream.write(';'.join(['3000', '', 'No'] + ['']*12) + '\n') with pytest.raises(ValueError, match='unterminated'): - unicode_admission(root) + parse_fixture(root) def test_invalid_scalar_and_anchor_refusal(tmp_path): root = ucd_fixture(tmp_path) for bad in ('', 'ab', '\ud800'): with pytest.raises(ValueError): - repertoire((bad,), tuple(' A'), root) + fixture_repertoire((bad,), tuple(' A'), root) for bad in (('A',), (' ', 'A', 'A')): with pytest.raises(ValueError): - repertoire(('A',), bad, root) + fixture_repertoire(('A',), bad, root) def test_word_and_recursive_record(tmp_path): @@ -231,3 +258,69 @@ def test_unknown_word_refuses(tmp_path): def test_geometry_producer_bytes_are_bound(): _producer_check() + + +def test_fixture_cannot_claim_production_release(tmp_path): + root = ucd_fixture(tmp_path) + # Even the expected production header and minimum ASCII values are insufficient. + path = root / 'DerivedCoreProperties.txt' + path.write_text(path.read_text().replace(FIXTURE_VERSION, implementation.UNICODE_VERSION)) + with pytest.raises(ValueError, match='release hash mismatch'): + implementation.unicode_admission(root) + with pytest.raises(ValueError, match='release hash mismatch'): + implementation.repertoire(('A',), (' ', 'A'), root) + + +def test_fixture_layout_is_not_labelled_as_unicode_release(tmp_path): + assert factory_fixture(tmp_path).public['unicode_version'] == FIXTURE_VERSION + + +def manifest_fixture(): + from pathlib import Path + return { + 'schema': implementation.PROFILE, 'source_receipt': 'a' * 64, + 'source': {'fixture': True}, 'ucns_commit': implementation.UCNS_COMMIT, + 'implementation_sha256': implementation.file_hash(Path(implementation.__file__)), + 'public_sha256': 'b' * 64, 'glyph_carrier_receipt': 'c' * 64, + 'word_carrier_receipt': 'd' * 64, 'counts': {'frames': 1, 'placements': 1}, + 'geometry_receipt': 'e' * 64, 'hmmm': list(implementation.MANIFEST_BOUNDARIES), + } + + +def test_manifest_shape_check_is_not_full_verification(): + # This checks only the schema. No source or geometry survival claim is emitted. + assert implementation._validate_manifest(manifest_fixture()) is None + + +@pytest.mark.parametrize('mutation', [ + lambda m: m.pop('hmmm'), + lambda m: m.update(hmmm=[]), + lambda m: m.update(hmmm=['everything is proven']), + lambda m: m.update(canonical=True), + lambda m: m.update(proof_status='SURVIVED'), + lambda m: m.update(counts={'frames': True, 'placements': 1}), + lambda m: m.update(counts={'frames': 1, 'placements': 1, 'extra': 1}), + lambda m: m.update(source_receipt='not a digest'), +]) +def test_modified_manifest_refuses_before_source_replay(tmp_path, mutation): + value = manifest_fixture() + mutation(value) + implementation._json_write(tmp_path / 'manifest.json', value) + with pytest.raises(ValueError, match='manifest'): + implementation.verify(tmp_path) + + +def test_nonobject_manifest_refuses(tmp_path): + implementation._json_write(tmp_path / 'manifest.json', []) + with pytest.raises(ValueError, match='manifest schema'): + implementation.verify(tmp_path) + + +def test_second_unicode_file_is_independently_hash_bound(tmp_path, monkeypatch): + from hashlib import sha256 + root = ucd_fixture(tmp_path) + # Allow only the first synthetic file, then prove the second still refuses. + monkeypatch.setitem(implementation.UCD_RELEASE_SHA256, 'UnicodeData.txt', + sha256((root / 'UnicodeData.txt').read_bytes()).hexdigest()) + with pytest.raises(ValueError, match='DerivedCoreProperties.txt'): + implementation.unicode_admission(root) From 37adccb4c079199d915a49e475af0f426fed0943 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 03:28:13 -0700 Subject: [PATCH 06/25] Bound Unicode acquisition before reading or copying release inputs Snapshot only regular nonsymlink UCD files, reject oversize inputs before open, retain at most the limit plus one byte, detect file replacement/growth, and authenticate the bounded snapshot before building or copying. Ordinal placement, public layout and SPACE-first behavior are unchanged. Runtime source checkpoint for the following atomic provenance/test/CI update; no branch ref moves at this checkpoint. --- .../english_gonol/ordinal_construct.py | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/research/english-gonol/english_gonol/ordinal_construct.py b/research/english-gonol/english_gonol/ordinal_construct.py index 159939a..d06fd1c 100644 --- a/research/english-gonol/english_gonol/ordinal_construct.py +++ b/research/english-gonol/english_gonol/ordinal_construct.py @@ -18,9 +18,11 @@ from hashlib import sha256 from itertools import groupby import json +import os from pathlib import Path import shutil import sqlite3 +import stat import tempfile from ucns.ordinal_affixiation import Carrier, Participant, affixiate @@ -46,7 +48,7 @@ # === CONTRACTS === # id: english_expanded_repertoire # given: complete corpus scalars, exact inherited carrier, pinned Unicode properties -# then: every required scalar is admitted once; SPACE stays first; registry is reproducible +# then: every required scalar is admitted once; registry is reproducible # id: english_recursive_ordinal_geometry # given: closed words and exact source components # then: UCNS places by ordinal radius and declared carrier angle while interiors remain recoverable @@ -58,6 +60,7 @@ PROFILE = 'english.ordinal/1' UNICODE_VERSION = '18.0.0' UCD_FILES = ('UnicodeData.txt', 'DerivedCoreProperties.txt') +UCD_MAX_BYTES = 10_000_000 # Exact complete Unicode 18.0.0 release bytes, retained in the full-corpus artifact. # Admission pins content, not a header, local registry, or minimal ASCII subset. UCD_RELEASE_SHA256 = { @@ -133,7 +136,7 @@ def _parse_unicode_properties(blobs: dict[str, bytes], version: str): numbers: set[str] = set() maths: set[str] = set() pending = None - if any(len(raw) > 10_000_000 for raw in blobs.values()): + if any(len(raw) > UCD_MAX_BYTES for raw in blobs.values()): raise ValueError('Unicode input exceeds per-file acquisition budget') data = blobs[UCD_FILES[0]].decode('utf-8') for line in data.splitlines(): @@ -179,13 +182,47 @@ def _parse_unicode_properties(blobs: dict[str, bytes], version: str): -def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: - """Admit only the complete pinned release; never trust a self-declared header.""" - blobs = {name: (ucd / name).read_bytes() for name in UCD_FILES} +def _read_unicode_file(path: Path) -> bytes: + """Snapshot a bounded regular file; do not follow symlinks or block on FIFOs.""" + before = path.lstat() + if not stat.S_ISREG(before.st_mode): + raise ValueError(f'Unicode input must be a regular nonsymlink file: {path.name}') + if before.st_size > UCD_MAX_BYTES: + raise ValueError(f'Unicode input exceeds acquisition budget: {path.name}') + flags = os.O_RDONLY | getattr(os, 'O_NOFOLLOW', 0) | getattr(os, 'O_NONBLOCK', 0) + try: + fd = os.open(path, flags) + except OSError as error: + raise ValueError(f'Unicode input changed or cannot be opened: {path.name}') from error + with os.fdopen(fd, 'rb') as stream: + opened = os.fstat(stream.fileno()) + if (not stat.S_ISREG(opened.st_mode) + or (opened.st_dev, opened.st_ino) != (before.st_dev, before.st_ino)): + raise ValueError(f'Unicode input changed or is not regular: {path.name}') + if opened.st_size > UCD_MAX_BYTES: + raise ValueError(f'Unicode input exceeds acquisition budget: {path.name}') + raw = stream.read(UCD_MAX_BYTES + 1) + after = os.fstat(stream.fileno()) + if len(raw) > UCD_MAX_BYTES: + raise ValueError(f'Unicode input exceeds acquisition budget: {path.name}') + if (len(raw) != opened.st_size + or (after.st_size, after.st_mtime_ns) != (opened.st_size, opened.st_mtime_ns)): + raise ValueError(f'Unicode input changed during bounded read: {path.name}') + return raw + + +def _verified_unicode_blobs(ucd: Path) -> dict[str, bytes]: + """Acquire and authenticate a bounded snapshot before any artifact copying.""" + blobs = {name: _read_unicode_file(ucd / name) for name in UCD_FILES} for name, raw in blobs.items(): if sha256(raw).hexdigest() != UCD_RELEASE_SHA256[name]: raise ValueError(f'Unicode release hash mismatch: {name}; complete pinned release required') - return _parse_unicode_properties(blobs, UNICODE_VERSION) + return blobs + + +def unicode_admission(ucd: Path) -> tuple[set[str], set[str], dict]: + """Admit only the complete pinned release; never trust a self-declared header.""" + return _parse_unicode_properties(_verified_unicode_blobs(ucd), UNICODE_VERSION) def _layout_repertoire(corpus, legacy, numbers, maths, hashes, unicode_version): @@ -299,10 +336,11 @@ def _json_read(path): def build(admission: Path, ucd: Path, output: Path) -> dict: """Consume complete source admission, create a fresh self-contained geometry bundle.""" - from english_gonol.structural_construct import _verified_connection _producer_check() if output.exists(): raise ValueError('output exists; select a new directory') + unicode_blobs = _verified_unicode_blobs(ucd) + from english_gonol.structural_construct import _verified_connection output.parent.mkdir(parents=True, exist_ok=True) stage = Path(tempfile.mkdtemp(prefix='.ordinal-', dir=output.parent)) try: @@ -316,7 +354,7 @@ def build(admission: Path, ucd: Path, output: Path) -> dict: _json_write(stage / 'admission' / 'manifest.json', source_manifest) (stage / 'ucd').mkdir() for name in UCD_FILES: - shutil.copyfile(ucd / name, stage / 'ucd' / name) + (stage / 'ucd' / name).write_bytes(unicode_blobs[name]) chars, words = _inventory(source_db) legacy = tuple(source_manifest['metadata']['producer']['carrier']) public = repertoire(tuple(chars.values()), legacy, stage / 'ucd') From 174f96a7247a1ffc39b7fd2061f5f302c078cdfb Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 03:38:31 -0700 Subject: [PATCH 07/25] Bind final ordinal source bytes and test the actual merge tree Close the four further #88 findings in one source-plus-metadata transaction. Select exact runtime checkpoint 37adccb4c079199d915a49e475af0f426fed0943 in BASE and root projections, recompute the work graph, compare selected module bytes in CI, retain separate source-head and tested-merge evidence, and scope prior corpus claims to their original implementation. Add bounded-read/special-file/race and workflow proof regressions. Local focused suite: 73 passed. Runtime implementation SHA-256 a1933daabd2ae9323588c99f395441c7711e082ea03c97797a81051b1430aa2d. Full final-head construction and merge-tree replay required before merge; previous artifacts are not relabeled. --- .../workflows/english-ordinal-affixiation.yml | 13 ++- STACK_MANIFEST.md | 4 +- research/english-gonol/BASE.json | 2 +- research/english-gonol/README.md | 5 +- .../docs/ordinal-construction.md | 9 +- .../tests/test_active_construction.py | 20 +++++ .../tests/test_ordinal_construct.py | 84 +++++++++++++++++++ stack-manifest.json | 6 +- 8 files changed, 131 insertions(+), 12 deletions(-) diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index 6745d35..b09783c 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -20,7 +20,6 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} persist-credentials: false - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: @@ -83,12 +82,21 @@ jobs: for item in graph['repositories']: if item['repository'] in roots: assert subprocess.check_output(['git','-C',roots[item['repository']],'rev-parse','HEAD'],text=True).strip()==item['commit'] + active_base=json.loads(pathlib.Path('research/english-gonol/BASE.json').read_text()) + selected=active_base['active_construction']['source_commit'] + assert len(selected)==40 and all(c in '0123456789abcdef' for c in selected) + subprocess.run(['git','fetch','--no-tags','--depth=1','origin',selected],check=True) + for name in ('ordinal_construct.py','__main__.py'): + path='research/english-gonol/english_gonol/'+name + assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',selected+':'+path]),path base=next(r['commit'] for r in graph['repositories'] if r['repository']=='The-Interdependency/stack') for name in IMPLEMENTATION_FILES: path='research/english-gonol/english_gonol/'+name assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',base+':'+path]),path PY - name: Acquire declared Unicode release and license + env: + SOURCE_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} run: | mkdir -p _inputs/ucd _evidence for name in UnicodeData.txt DerivedCoreProperties.txt ReadMe.txt; do @@ -98,7 +106,8 @@ jobs: curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ https://www.unicode.org/license.txt -o _inputs/ucd/LICENSE-Unicode.txt sha256sum _inputs/ucd/* | tee _evidence/unicode-acquisition.sha256 - git rev-parse HEAD > _evidence/stack-head.txt + git rev-parse HEAD > _evidence/stack-tested-merge.txt + printf '%s\n' "$SOURCE_HEAD" > _evidence/stack-head.txt git -C _inputs/ucns rev-parse HEAD > _evidence/ucns-head.txt git -C _inputs/oewn rev-parse HEAD > _evidence/corpus-head.txt - name: Unit and cross-repository geometry tests diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index f329cd0..caf09d4 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -17,7 +17,7 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `74e65b830160887dd2ea27d84cb6b53b91135339b64acb7d51d0f8c407569297` + `70578d9ee468b21165b7bc7fedaf799fb6e84245246302ff25cbc7139deb0635` - Weave workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - Pi radix workspace creation UTC: `2026-10-10`; bounded cross-base computation starts from Stack `ccf707f933a9611d7b7fe13a0417378d8b453a14` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) @@ -64,7 +64,7 @@ selection, and see [the supported build](research/english-gonol/README.md). | Participant ID | Repository | Exact commit | Relation | |---|---|---|---| -| `ordinal-source` | `The-Interdependency/stack` | `0e0ea9ebe64803e810793dd4780253d7d202fecc` | selected ordinal implementation and default route; source baseline is not independent UCHC release authority | +| `ordinal-source` | `The-Interdependency/stack` | `37adccb4c079199d915a49e475af0f426fed0943` | exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority | | `ordinal-geometry` | `The-Interdependency/ucns` | `a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb` | merged UCNS #241 producer; exact local radius and carrier angle law, not global transport or semantic authority | | `ordinal-admission` | `The-Interdependency/stack` | `e3eb83764355b4b760a79323cda6a6d75c3a501a` | unchanged thirteen-file source-reader closure; source admission is not the selected completed geometry | | `ordinal-admission-carrier` | `The-Interdependency/ucns` | `4f863ad37096b7baab8f62820ad5cb937b62a3a7` | inherited scalar identity admission only; these historical angles do not supply the replacement placement | diff --git a/research/english-gonol/BASE.json b/research/english-gonol/BASE.json index 2928b68..9fc8470 100644 --- a/research/english-gonol/BASE.json +++ b/research/english-gonol/BASE.json @@ -33,7 +33,7 @@ "active_construction": { "selection": "ACTIVE_CONSTRUCTION.json", "source_repository": "The-Interdependency/stack", - "source_commit": "0e0ea9ebe64803e810793dd4780253d7d202fecc", + "source_commit": "37adccb4c079199d915a49e475af0f426fed0943", "work_graph": "../../stack-manifest.json#research_participants[workspace=research/english-gonol/]", "authority_transfer": false } diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index a29c130..62956b6 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -22,8 +22,9 @@ affixiation** GitHub workflow can also be run manually from Actions. It builds and independently replays the complete pinned corpus through the supported entrypoint. An existing output directory is never overwritten. -The delivered full construction has 4,698 public scalar positions, 103,053 closed -words, 420,006 frames and 4,792,299 placements. Source and geometry receipts belong +The prior full construction recorded 4,698 public scalar positions, 103,053 closed +words, 420,006 frames and 4,792,299 placements. A changed implementation requires +a new exact-source build and replay; prior receipts do not certify current bytes. Source and geometry receipts belong to `english.ordinal/1`; old counts and receipts are not interchangeable with it. These counts establish constructed scope, not semantic or inference quality. diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index fd56381..8e92f83 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -106,5 +106,10 @@ The layout choices are explicit and replaceable only through a new profile and full rebuild. Native Mobius lift, global transport/definition-origin attachment, operator function semantics, inference quality and UCHC release remain separate questions. Local placement does not manufacture evidence for those questions. -Complete hosted construction and replay have succeeded. See `ordinal-questions.md` -for unresolved construction laws and the separate downstream migration work. +Earlier complete-corpus receipts establish only their recorded implementation. +Every implementation change requires its own hosted construction and replay; +inspect the exact run, tested merge tree and generated manifest before assigning +that standing. CI compares the selected source pin with the actual module bytes. +Unicode inputs are regular nonsymlink files, read within the acquisition budget +and matched to both pinned complete-release hashes before parsing or copying. +See `ordinal-questions.md` for unresolved construction laws and migration work. diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 734a1e7..69bbfb9 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -120,3 +120,23 @@ def test_full_workflow_covers_admission_dependencies(): for name in closure: path = f'research/english-gonol/english_gonol/{name}' assert any(fnmatch(path, pattern) for pattern in filters), path + + +def test_workflow_tests_merge_tree_and_binds_selected_source_bytes(): + import yaml + workspace = Path(entry.__file__).resolve().parents[1] + root = workspace.parents[1] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + steps = workflow['jobs']['full-corpus']['steps'] + checkout = next(step for step in steps if step.get('uses', '').startswith('actions/checkout@')) + assert 'ref' not in checkout.get('with', {}), 'PR tests must use the generated merge tree' + graph_check = next(step['run'] for step in steps + if step.get('name') == 'Verify exact participant graph and unchanged source reader') + assert "['active_construction']['source_commit']" in graph_check + assert "['git','show',selected+':'+path]" in graph_check + assert "pathlib.Path(path).read_bytes()==subprocess.check_output" in graph_check + acquisition = next(step for step in steps + if step.get('name') == 'Acquire declared Unicode release and license') + assert 'stack-tested-merge.txt' in acquisition['run'] + assert 'SOURCE_HEAD' in acquisition['env'] diff --git a/research/english-gonol/tests/test_ordinal_construct.py b/research/english-gonol/tests/test_ordinal_construct.py index d6b5480..4f59ba3 100644 --- a/research/english-gonol/tests/test_ordinal_construct.py +++ b/research/english-gonol/tests/test_ordinal_construct.py @@ -324,3 +324,87 @@ def test_second_unicode_file_is_independently_hash_bound(tmp_path, monkeypatch): sha256((root / 'UnicodeData.txt').read_bytes()).hexdigest()) with pytest.raises(ValueError, match='DerivedCoreProperties.txt'): implementation.unicode_admission(root) + + +def test_unicode_read_refuses_oversize_before_open(tmp_path, monkeypatch): + path = tmp_path / 'oversize.txt' + with path.open('wb') as stream: + stream.truncate(implementation.UCD_MAX_BYTES + 1) + def forbidden_open(*args, **kwargs): + raise AssertionError('oversize file was opened') + monkeypatch.setattr(implementation.os, 'open', forbidden_open) + with pytest.raises(ValueError, match='acquisition budget'): + implementation._read_unicode_file(path) + + +@pytest.mark.parametrize('kind', ['symlink', 'directory', 'fifo']) +def test_unicode_read_refuses_nonregular_inputs(tmp_path, kind): + path = tmp_path / 'input' + if kind == 'symlink': + target = tmp_path / 'target' + target.write_bytes(b'not a release') + path.symlink_to(target) + elif kind == 'directory': + path.mkdir() + else: + if not hasattr(implementation.os, 'mkfifo'): + pytest.skip('platform has no FIFO filesystem objects') + implementation.os.mkfifo(path) + with pytest.raises(ValueError, match='regular nonsymlink'): + implementation._read_unicode_file(path) + + +def test_unicode_stream_read_is_capped_even_when_file_grows(tmp_path, monkeypatch): + from contextlib import contextmanager + path = tmp_path / 'growing.txt' + path.write_bytes(b'x') + monkeypatch.setattr(implementation, 'UCD_MAX_BYTES', 32) + fdopen = implementation.os.fdopen + requested = [] + @contextmanager + def tracked_open(fd, mode): + with fdopen(fd, mode) as stream: + class Tracked: + def fileno(self): + return stream.fileno() + def read(self, count): + requested.append(count) + with path.open('ab') as writer: + writer.write(b'x' * 64) + return stream.read(count) + yield Tracked() + monkeypatch.setattr(implementation.os, 'fdopen', tracked_open) + with pytest.raises(ValueError, match='acquisition budget'): + implementation._read_unicode_file(path) + assert requested == [33] + + +def test_unicode_input_replacement_during_open_refuses(tmp_path, monkeypatch): + path = tmp_path / 'swapped.txt' + path.write_bytes(b'first') + replacement = tmp_path / 'replacement' + replacement.write_bytes(b'second') + original_open = implementation.os.open + def replacing_open(name, flags): + replacement.replace(path) + return original_open(name, flags) + monkeypatch.setattr(implementation.os, 'open', replacing_open) + with pytest.raises(ValueError, match='changed'): + implementation._read_unicode_file(path) + + +def test_bounded_unicode_snapshot_preserves_exact_bytes(tmp_path): + path = tmp_path / 'regular.txt' + path.write_bytes(b'exact\x00bytes\n') + assert implementation._read_unicode_file(path) == b'exact\x00bytes\n' + + +def test_build_refuses_oversize_ucd_before_source_or_copy(tmp_path): + path = tmp_path / 'ucd' + path.mkdir() + with (path / 'UnicodeData.txt').open('wb') as stream: + stream.truncate(implementation.UCD_MAX_BYTES + 1) + output = tmp_path / 'must-not-be-created' / 'output' + with pytest.raises(ValueError, match='acquisition budget'): + implementation.build(tmp_path / 'missing-admission', path, output) + assert not output.parent.exists() diff --git a/stack-manifest.json b/stack-manifest.json index 445bab7..c451706 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "74e65b830160887dd2ea27d84cb6b53b91135339b64acb7d51d0f8c407569297", + "work_graph_sha256": "70578d9ee468b21165b7bc7fedaf799fb6e84245246302ff25cbc7139deb0635", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -478,9 +478,9 @@ "workspace": "research/english-gonol/", "participant_id": "ordinal-source", "repository": "The-Interdependency/stack", - "commit": "0e0ea9ebe64803e810793dd4780253d7d202fecc", + "commit": "37adccb4c079199d915a49e475af0f426fed0943", "authority": "English construction and supported entrypoint", - "relation": "selected ordinal implementation and default route; source baseline is not independent UCHC release authority", + "relation": "exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority", "canonical_release": false, "authority_transfer": false }, From 68d6fe2bb7616b8b50353809b19c483dd9f0ee36 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 03:55:46 -0700 Subject: [PATCH 08/25] Close selection and repin CI boundaries; separate auxiliary work graph from geometry data Byte-bind ACTIVE_CONSTRUCTION.json and the local source work graph alongside both runtime modules to the selected source checkpoint. Trigger the full gate on BASE and root-manifest changes. Keep the work graph as explicitly separate source CI evidence, not an unverified authority record inside the construction artifact. Add three regressions and document the verification boundary. Local focused suite: 76 passed. Runtime bytes and selected source 37adccb4c079199d915a49e475af0f426fed0943 remain unchanged; final merge-tree CI still required. --- .../workflows/english-ordinal-affixiation.yml | 11 +++-- .../docs/ordinal-construction.md | 6 +++ .../tests/test_active_construction.py | 48 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index b09783c..91f53b1 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -5,6 +5,9 @@ on: paths: - 'research/english-gonol/english_gonol/**' - 'research/english-gonol/ACTIVE_CONSTRUCTION.json' + - 'research/english-gonol/BASE.json' + - 'stack-manifest.json' + - 'STACK_MANIFEST.md' - 'research/english-gonol/tests/test_active_construction.py' - 'research/english-gonol/tests/test_ordinal_construct.py' - 'research/english-gonol/docs/ordinal-*' @@ -86,8 +89,9 @@ jobs: selected=active_base['active_construction']['source_commit'] assert len(selected)==40 and all(c in '0123456789abcdef' for c in selected) subprocess.run(['git','fetch','--no-tags','--depth=1','origin',selected],check=True) - for name in ('ordinal_construct.py','__main__.py'): - path='research/english-gonol/english_gonol/'+name + for relative in ('english_gonol/ordinal_construct.py','english_gonol/__main__.py', + 'ACTIVE_CONSTRUCTION.json','docs/ordinal-work-graph.json'): + path='research/english-gonol/'+relative assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',selected+':'+path]),path base=next(r['commit'] for r in graph['repositories'] if r['repository']=='The-Interdependency/stack') for name in IMPLEMENTATION_FILES: @@ -110,6 +114,8 @@ jobs: printf '%s\n' "$SOURCE_HEAD" > _evidence/stack-head.txt git -C _inputs/ucns rev-parse HEAD > _evidence/ucns-head.txt git -C _inputs/oewn rev-parse HEAD > _evidence/corpus-head.txt + # CI source provenance is separate from the artifact verifier's data contract. + cp research/english-gonol/docs/ordinal-work-graph.json _evidence/source-work-graph.json - name: Unit and cross-repository geometry tests env: PYTHONPATH: research/english-gonol @@ -135,7 +141,6 @@ jobs: cp _inputs/oewn/README.md _constructed/licenses/OEWN-README.md cp _inputs/ucd/LICENSE-Unicode.txt _constructed/licenses/ cp _inputs/ucd/ReadMe.txt _constructed/licenses/Unicode-ReadMe.txt - cp research/english-gonol/docs/ordinal-work-graph.json _constructed/ cp _constructed/public-gonol.json _constructed/manifest.json _constructed/verification.json _evidence/ python - <<'PY' import json,pathlib diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index 8e92f83..33e5f46 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -56,6 +56,12 @@ A SPACE occurrence is not silently placed at radius zero or discarded. The hosted workflow also retains source licenses, an exact angular TSV, query output and resource receipts. It writes no repository files and does not merge. Old structural receipts are never presented as receipts for this geometry. +The source work graph is CI provenance, retained separately as +`source-work-graph.json` in the evidence archive and bound to the selected source +commit by CI. It is not packaged as construction data or covered by the artifact +verifier's `SURVIVED` result. The construction verifier covers its declared +manifest, carrier registries, Unicode inputs, source admission and geometry; +auxiliary licensing text is not a geometry or authority claim. ## Execute diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 69bbfb9..9fbab51 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -140,3 +140,51 @@ def test_workflow_tests_merge_tree_and_binds_selected_source_bytes(): if step.get('name') == 'Acquire declared Unicode release and license') assert 'stack-tested-merge.txt' in acquisition['run'] assert 'SOURCE_HEAD' in acquisition['env'] + + +def test_provenance_repins_trigger_exact_source_gate(): + from fnmatch import fnmatch + import yaml + root = Path(entry.__file__).resolve().parents[3] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + filters = workflow['on']['pull_request']['paths'] + for path in ('research/english-gonol/BASE.json', 'stack-manifest.json', + 'STACK_MANIFEST.md', 'research/english-gonol/ACTIVE_CONSTRUCTION.json', + 'research/english-gonol/docs/ordinal-work-graph.json'): + assert any(fnmatch(path, pattern) for pattern in filters), path + + +def test_selection_and_source_graph_are_exact_pinned_inputs(): + import ast + import yaml + root = Path(entry.__file__).resolve().parents[3] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + steps = workflow['jobs']['full-corpus']['steps'] + command = next(step['run'] for step in steps + if step.get('name') == 'Verify exact participant graph and unchanged source reader') + python = command.split("<<'PY'\n", 1)[1].rsplit('\nPY', 1)[0] + tree = ast.parse(python) + loop = next(node for node in ast.walk(tree) if isinstance(node, ast.For) + and isinstance(node.target, ast.Name) and node.target.id == 'relative') + inputs = ast.literal_eval(loop.iter) + assert set(inputs) == {'english_gonol/ordinal_construct.py', 'english_gonol/__main__.py', + 'ACTIVE_CONSTRUCTION.json', 'docs/ordinal-work-graph.json'} + assert any(isinstance(node, ast.Assert) for node in loop.body) + + +def test_auxiliary_source_graph_is_outside_verified_construction(): + import shlex + import yaml + root = Path(entry.__file__).resolve().parents[3] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + copies = [] + for step in workflow['jobs']['full-corpus']['steps']: + for line in step.get('run', '').splitlines(): + if line.strip().startswith('cp '): + words = shlex.split(line) + if 'research/english-gonol/docs/ordinal-work-graph.json' in words: + copies.append(words[-1]) + assert copies == ['_evidence/source-work-graph.json'] From b7f8672e159ab7a504bffd0033f7152c64400eed Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 04:15:07 -0700 Subject: [PATCH 09/25] docs(english-gonol): record SPACE attachment answer and separate transport proof --- .../english-gonol/docs/ordinal-questions.md | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md index 36d4e35..af1b6c8 100644 --- a/research/english-gonol/docs/ordinal-questions.md +++ b/research/english-gonol/docs/ordinal-questions.md @@ -1,4 +1,4 @@ -# Ordinal construction: answers still needed +# Ordinal construction: answers and remaining work The selected implementation is `english.ordinal/1`; inspect it with `PYTHONPATH=research/english-gonol python -m english_gonol profile`. @@ -18,19 +18,27 @@ and orders its word carrier by sequences of public-gonol indexes. These are explicit implementation choices, not discovered semantic laws. This merge keeps them fixed; changing either requires a new profile and rebuilt receipts. -## Construction questions, ordered by dependency +## Construction answers and questions, ordered by dependency -### 1. How do nested local frames become one geometric construction? +### 1. Nested attachment: SPACE — specified; transport unverified -The current operation retains a closed word and places that participant within -a parent. It does not specify the translation, orientation or scale transporting -the word's interior frame into the parent's frame. What exact relation supplies -that attachment, including which origin and radius are inherited? +Operator answer to the nested-frame attachment question: `1. space`. +SPACE supplies the attachment reference between a closed construction's local +frame and its consuming frame. Do not ask the operator to select that reference +again. The already-specified ordinal-distance and carrier-angle laws remain in +force; this answer does not authorize substituting a different construction. -Current behavior: preserve separate local frames and their links. Do not add an -implicit rotation, translation or scale law. Completion witness: an explicit UCNS -transport with nested-order recovery and a tested composition law. This is the -highest-leverage unanswered geometric question. +In `../english_gonol/ordinal_construct.py`, both `Factory.word` and +`Factory.record` already declare `origin='SPACE'`; `_independent_frame` checks +the same origin in frame rows and closure receipts. That existing declaration +is not an evaluated transport between frames. + +Current behavior: preserve separate local frames and their links. Remaining +implementation/evidence boundary: an explicit UCNS transport using the specified +SPACE attachment, with nested-order recovery and a tested composition law. +Do not invent an implicit rotation, translation or scale law to turn the stored +origin name into a completion claim. Record the implemented transport and its +evidence here when available; keep specification and implementation distinct. ### 2. Where does a multiword lexical entry's definition attach? @@ -89,5 +97,7 @@ no silent reinterpretation of previously constructed objects. ## hmmm -Merge closes source integration and default selection. It does not manufacture -answers to the five construction questions or mark downstream migration complete. +SPACE is the specified nested attachment reference; its cross-frame transport +witness remains outstanding. Questions 2–5 remain open. Merge closes source +integration and default selection, not these implementation/evidence boundaries +or downstream migration. From 69559d3c90406367533a1979e81976739a904814 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 04:35:03 -0700 Subject: [PATCH 10/25] docs(english-gonol): record SPACE compound definition attachment answer --- .../english-gonol/docs/ordinal-questions.md | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md index af1b6c8..2e372a2 100644 --- a/research/english-gonol/docs/ordinal-questions.md +++ b/research/english-gonol/docs/ordinal-questions.md @@ -40,16 +40,22 @@ Do not invent an implicit rotation, translation or scale law to turn the stored origin name into a completion claim. Record the implemented transport and its evidence here when available; keep specification and implementation distinct. -### 2. Where does a multiword lexical entry's definition attach? +### 2. Compound definition attachment: SPACE — specified; witness outstanding -The source stage preserves compound entries and definitions with their exact -source ownership; it does not invent a single-word origin for a multiword entry. -Does its closed lexical construction supply that origin, and by what attachment -operation? The ordinal builder can position its participants without pretending -that local positions settle the origin relation. +Operator answer to the compound definition-origin question: `2. space`. +SPACE supplies the attachment reference for a multiword lexical entry's +definition, as it does for nested frames in answer 1. Do not ask the operator +to select that reference again or substitute a constituent word as the origin. -Completion witness: every compound definition has a source-bound attachment that -preserves its entry, constituent order and definition succession. +Preserve the compound entry's exact source ownership, constituent order and +definition succession. Apply the specified SPACE reference when implementing +its attachment; naming the reference does not establish evaluated transport. + +Completion witness: every compound definition has a source-bound SPACE +attachment that preserves its entry, constituent order and definition +succession. Record the implemented attachment and independent verification here +when available; the reference is specified, while that witness remains +outstanding. ### 3. How does this visible-circle construction lift into native Mobius state? @@ -97,7 +103,7 @@ no silent reinterpretation of previously constructed objects. ## hmmm -SPACE is the specified nested attachment reference; its cross-frame transport -witness remains outstanding. Questions 2–5 remain open. Merge closes source -integration and default selection, not these implementation/evidence boundaries -or downstream migration. +SPACE is the specified attachment reference for both nested frames and compound +definitions. Their transport/attachment witnesses remain outstanding. Questions +3–5 remain open. Merge closes source integration and default selection, not +these implementation/evidence boundaries or downstream migration. From ee130be77537419040973a665bd47fbb833328e2 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 04:47:39 -0700 Subject: [PATCH 11/25] docs(english-gonol): exclude native Mobius lift from ordinal requirements Record operator answer 3: not required. Preserve SPACE attachment answers and outstanding witnesses; leave questions 4 and 5 open. Align README and construction guide without changing runtime, source pins, or UCNS native geometry. Applies skill-lib gonol-build scope preservation and the-interdependency workflow. --- research/english-gonol/README.md | 9 +++++---- .../docs/ordinal-construction.md | 7 ++++--- .../english-gonol/docs/ordinal-questions.md | 20 +++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index 62956b6..7167a28 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -92,7 +92,8 @@ metrics are not renamed as ordinal measurements. ## hmmm -[Questions and remaining work](docs/ordinal-questions.md) distinguish missing -construction laws from engineering work. The radius/angle rule is settled; -global frame transport, compound origins, native Mobius lift, operator actions -and downstream inference evidence remain open. +[Answers and remaining work](docs/ordinal-questions.md) separate the settled +radius/angle rule and SPACE references from outstanding implementation witnesses. +Native Mobius integration is not required by this profile. Questions 4 and 5 +concern operator actions and vocabulary growth; attachment verification and +downstream inference evidence remain engineering/evidence boundaries. diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index 33e5f46..10593f0 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -109,9 +109,10 @@ small local fixture the full construct. ## hmmm The layout choices are explicit and replaceable only through a new profile and -full rebuild. Native Mobius lift, global transport/definition-origin attachment, -operator function semantics, inference quality and UCHC release remain separate -questions. Local placement does not manufacture evidence for those questions. +full rebuild. The [answers and remaining work](ordinal-questions.md) record the +specified SPACE attachments, excluded native Mobius integration, remaining +operator/admission questions and engineering witnesses. Local placement does not +establish attachment transport, operator behavior, inference quality or UCHC release. Earlier complete-corpus receipts establish only their recorded implementation. Every implementation change requires its own hosted construction and replay; inspect the exact run, tested merge tree and generated manifest before assigning diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md index 2e372a2..3d26178 100644 --- a/research/english-gonol/docs/ordinal-questions.md +++ b/research/english-gonol/docs/ordinal-questions.md @@ -57,14 +57,14 @@ succession. Record the implemented attachment and independent verification here when available; the reference is specified, while that witness remains outstanding. -### 3. How does this visible-circle construction lift into native Mobius state? +### 3. Native Mobius integration: not required -The new local law supplies exact visible turns. The missing operation must state -how those turns carry frame/sheet state and preserve the native distinction -between a 360-degree visible return and a 720-degree complete local return. -No ad-hoc doubled angle supplies that proof. - -Completion witness: native-state transport and return tests, not a rendering. +Operator answer to the native Mobius integration question: `3. not required`. +Native Mobius lifting, sheet-state transport and 360/720-degree return tests are +outside the required scope of `english.ordinal/1`. They are neither outstanding +construction questions nor completion or merge prerequisites for this profile. +This scope decision does not claim a verified lift, retire UCNS native Mobius +work, or remove the SPACE attachment obligations in answers 1 and 2. ### 4. Which admitted operator positions perform which actions? @@ -104,6 +104,6 @@ no silent reinterpretation of previously constructed objects. ## hmmm SPACE is the specified attachment reference for both nested frames and compound -definitions. Their transport/attachment witnesses remain outstanding. Questions -3–5 remain open. Merge closes source integration and default selection, not -these implementation/evidence boundaries or downstream migration. +definitions. Their transport/attachment witnesses remain outstanding. Only +questions 4 and 5 remain open. Merge closes source integration and default +selection, not these implementation/evidence boundaries or downstream migration. From 14341800a6a0389c9abd2bddeb0263b505e23ec8 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 04:55:59 -0700 Subject: [PATCH 12/25] docs(english-gonol): inherit operator definitions on the ordinal base Record answer 4: reuse the previous definition method and applicable functions; reconstruct over the expanded carrier rather than redesign semantics. Bind the inspected prior definition sources, preserve overlapping roles and honest unknowns, and specify old/new preservation and no-fallback witnesses. Only vocabulary growth remains a construction question. Documentation only: no runtime, source-pin, test, workflow or generated-artifact changes. Applies gonol-build structure preservation, the-interdependency source-first inheritance, and WDLL evidence separation. --- research/english-gonol/README.md | 14 +++-- .../docs/ordinal-construction.md | 16 ++++- .../english-gonol/docs/ordinal-questions.md | 62 +++++++++++++++---- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index 7167a28..f3542d7 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -63,6 +63,11 @@ sealed admission and explicitly historical replay; retention grants no current geometry authority. The supported CLI rejects retired profile commands and does not silently return an old artifact when the ordinal constructor is unavailable. +The prior definition method and applicable functions remain required: reconstruct +them over the new base rather than discard their meanings or restore their old +geometry. [Answer 4](docs/ordinal-questions.md) owns this inheritance instruction, +its inspected source bindings and the outstanding preservation/replay witnesses. + Historical documentation and evidence: - [Full construct v2](docs/full-construct-v2.md) and `experiments/full-construct-v2/`. @@ -93,7 +98,8 @@ metrics are not renamed as ordinal measurements. ## hmmm [Answers and remaining work](docs/ordinal-questions.md) separate the settled -radius/angle rule and SPACE references from outstanding implementation witnesses. -Native Mobius integration is not required by this profile. Questions 4 and 5 -concern operator actions and vocabulary growth; attachment verification and -downstream inference evidence remain engineering/evidence boundaries. +radius/angle rule, SPACE references and inherited definition method from +outstanding implementation witnesses. Native Mobius integration is not required +by this profile. Only question 5, vocabulary growth, remains a construction +question; attachment verification, definition reconstruction/replay and downstream +inference evidence remain engineering/evidence boundaries. diff --git a/research/english-gonol/docs/ordinal-construction.md b/research/english-gonol/docs/ordinal-construction.md index 10593f0..3df61c0 100644 --- a/research/english-gonol/docs/ordinal-construction.md +++ b/research/english-gonol/docs/ordinal-construction.md @@ -38,6 +38,15 @@ Arbitrary circular placement is not an isometry of a high-dimensional simplex. SPACE's scalar angle is zero; the local frame center is the radial reference. A SPACE occurrence is not silently placed at radius zero or discarded. +## Inherited definitions + +[Answer 4](ordinal-questions.md) specifies reuse of the prior definition method +and applicable functions, reconstructed over the new base. Preserve meaning, +source associations and ordered interiors; replace the old carrier/geometry +bindings. The source audit and required preservation/replay witnesses live in +that answer. This instruction is settled; reconstruction verification remains +engineering work, not a request for new operator semantics. + ## Artifact `build` creates a new directory only: @@ -110,9 +119,10 @@ small local fixture the full construct. The layout choices are explicit and replaceable only through a new profile and full rebuild. The [answers and remaining work](ordinal-questions.md) record the -specified SPACE attachments, excluded native Mobius integration, remaining -operator/admission questions and engineering witnesses. Local placement does not -establish attachment transport, operator behavior, inference quality or UCHC release. +specified SPACE attachments, excluded native Mobius integration, inherited +definition method, remaining admission question and engineering witnesses. +Local placement does not establish attachment transport, inherited-definition +reconstruction, operator behavior, inference quality or UCHC release. Earlier complete-corpus receipts establish only their recorded implementation. Every implementation change requires its own hosted construction and replay; inspect the exact run, tested merge tree and generated manifest before assigning diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md index 3d26178..cfc2074 100644 --- a/research/english-gonol/docs/ordinal-questions.md +++ b/research/english-gonol/docs/ordinal-questions.md @@ -66,15 +66,49 @@ construction questions nor completion or merge prerequisites for this profile. This scope decision does not claim a verified lift, retire UCNS native Mobius work, or remove the SPACE attachment obligations in answers 1 and 2. -### 4. Which admitted operator positions perform which actions? - -A numeral, mathematical sign or logical operator currently receives an exact -scalar identity and angle. Admission does not implement arithmetic, implication, -quantification or any other action. What source-owned operation supplies each -function, and how does applying it change a construction? - -Current behavior: preserve literal position and occurrence only. Completion -witness: declared operations with positive and adversarial behavioral tests. +### 4. Operator definitions: inherit and reconstruct on the new base — specified; replay outstanding + +Operator answer: "define them the same way the previous iteration did. most of +that part of the previous implementation should still apply, just requires +iteration over the new base." + +Preserve the previous definition content, source-backed glyph/function +associations, constitutive relations and implemented behavior wherever compatible +with the replacement. Reconstruct those definitions and their ordered interiors +through the expanded public gonol and ordinal law. Changed carrier positions, +arity, placement and receipts are not changes of meaning. Retain exact scalar +identity, multiple applicable definitions, order, multiplicity and provenance. +Do not ask the operator to redesign this layer or introduce a separate arithmetic +or logical evaluator as a prerequisite for the requested inheritance. + +Inspected inheritance sources at Stack commit +`ee130be77537419040973a665bd47fbb833328e2`: + +- `../english_gonol/language/data/character_definitions_v1.json` owns the curated + character-definition payload, explicitly marked candidate evidence rather than + linguistic or cultural canon. Its `-` has both operator and punctuation roles; + digit number-name links and the other declared definition fields are retained. +- `../english_gonol/language/character_definitions.py` loads those definitions, + retains overlapping roles, fills uncovered legacy carrier members with explicit + `hmmm`, and constructs character/definition closures. Its `PUBLIC_GONOL_157` + coverage loop and imported historical `construct_gonol` are old-base bindings, + not supported geometry for the replacement. General arithmetic or logical + evaluation is not established merely by this table's operator-class labels. + +Implementation work: separate reusable definition inputs and applicable behavior +from the retired carrier/constructor binding, enumerate the actual expanded +carrier, and reconstruct with the selected constructor. For additional scalars, +apply the prior source-backed definition/admission method wherever it resolves an +entry; leave genuinely unavailable definitions explicitly `hmmm`. Neither copy +an old index as a new address nor invent meanings from a symbol's appearance. + +Completion witness: complete new-carrier coverage; comparison showing unchanged +inherited definition content, roles, source associations and applicable behavior; +new-profile angles/radii and receipts; exact recovery of definition interiors; +and explicit unresolved entries. Regressions must detect a lost role of `-`, +changed digit number-name linkage, stale 157-position coverage, old-constructor +fallback and claimed resolution of an inherited `hmmm`. This record resolves the +instruction; it does not claim that reconstruction or its replay has run. ### 5. How should previously unseen words and future carrier members enter? @@ -90,6 +124,8 @@ no silent reinterpretation of previously constructed objects. ## Engineering work, not questions to send back to the operator +- Reconstruct inherited definitions/functions over the new base and verify their + preservation as specified in answer 4; this is not a new operator-design question. - Separate the source-admission helper closure from the historical builder modules before physically removing those modules. They are retired as new-construction routes now; deleting dependencies first would break the replacement's verifier. @@ -104,6 +140,8 @@ no silent reinterpretation of previously constructed objects. ## hmmm SPACE is the specified attachment reference for both nested frames and compound -definitions. Their transport/attachment witnesses remain outstanding. Only -questions 4 and 5 remain open. Merge closes source integration and default -selection, not these implementation/evidence boundaries or downstream migration. +definitions. Native Mobius integration is excluded; prior operator definitions +are inherited and reconstructed on the new base. Only question 5 remains open. +SPACE attachment and inherited-definition reconstruction/replay witnesses remain +outstanding. Merge closes source integration and default selection, not these +implementation/evidence boundaries or downstream migration. From 7c91215275f4496c8b2f6a6ce7918ea2250b3a5e Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:24:03 -0700 Subject: [PATCH 13/25] fix(english): bound artifact JSON reads --- .../english_gonol/ordinal_construct.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/research/english-gonol/english_gonol/ordinal_construct.py b/research/english-gonol/english_gonol/ordinal_construct.py index d06fd1c..165ecc1 100644 --- a/research/english-gonol/english_gonol/ordinal_construct.py +++ b/research/english-gonol/english_gonol/ordinal_construct.py @@ -61,6 +61,7 @@ UNICODE_VERSION = '18.0.0' UCD_FILES = ('UnicodeData.txt', 'DerivedCoreProperties.txt') UCD_MAX_BYTES = 10_000_000 +JSON_MAX_BYTES = 64_000_000 # Exact complete Unicode 18.0.0 release bytes, retained in the full-corpus artifact. # Admission pins content, not a header, local registry, or minimal ASCII subset. UCD_RELEASE_SHA256 = { @@ -326,8 +327,37 @@ def _json_write(path, value): Path(path).write_bytes(canonical(value) + b'\n') +def _read_bounded_regular(path: Path, limit: int, label: str) -> bytes: + """Snapshot one bounded regular file without following links or blocking on special files.""" + before = path.lstat() + if not stat.S_ISREG(before.st_mode): + raise ValueError(f'{label} must be a regular nonsymlink file: {path.name}') + if before.st_size > limit: + raise ValueError(f'{label} exceeds read budget: {path.name}') + flags = os.O_RDONLY | getattr(os, 'O_NOFOLLOW', 0) | getattr(os, 'O_NONBLOCK', 0) + try: + fd = os.open(path, flags) + except OSError as error: + raise ValueError(f'{label} changed or cannot be opened: {path.name}') from error + with os.fdopen(fd, 'rb') as stream: + opened = os.fstat(stream.fileno()) + if (not stat.S_ISREG(opened.st_mode) + or (opened.st_dev, opened.st_ino) != (before.st_dev, before.st_ino)): + raise ValueError(f'{label} changed or is not regular: {path.name}') + if opened.st_size > limit: + raise ValueError(f'{label} exceeds read budget: {path.name}') + raw = stream.read(limit + 1) + after = os.fstat(stream.fileno()) + if len(raw) > limit: + raise ValueError(f'{label} exceeds read budget: {path.name}') + if (len(raw) != opened.st_size + or (after.st_size, after.st_mtime_ns) != (opened.st_size, opened.st_mtime_ns)): + raise ValueError(f'{label} changed during bounded read: {path.name}') + return raw + + def _json_read(path): - raw = Path(path).read_bytes() + raw = _read_bounded_regular(Path(path), JSON_MAX_BYTES, 'JSON artifact') value = json.loads(raw) if raw != canonical(value) + b'\n': raise ValueError('noncanonical JSON artifact') From f44e9f02e925e80dccbba422a8ef99974d305d76 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:24:06 -0700 Subject: [PATCH 14/25] fix(english): isolate ordinal UCNS test environment --- .github/workflows/english-gonol.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/english-gonol.yml b/.github/workflows/english-gonol.yml index 6aa291c..d4aeae8 100644 --- a/.github/workflows/english-gonol.yml +++ b/.github/workflows/english-gonol.yml @@ -87,7 +87,10 @@ jobs: python-version: "3.12" - name: Install construction prerequisites - run: python -m pip install --disable-pip-version-check pytest PyYAML ./_deps/ucns-ordinal + run: | + python -m pip install --disable-pip-version-check pytest PyYAML + python -m venv _deps/ordinal-venv + _deps/ordinal-venv/bin/python -m pip install --disable-pip-version-check pytest PyYAML ./_deps/ucns-ordinal - name: Verify all pinned source identities run: | @@ -114,9 +117,16 @@ jobs: --ucns-source-root "$GITHUB_WORKSPACE/_deps/ucns-carrier" \ --out-dir "$ENGLISH_GONOL_FULL_CONSTRUCT_ROOT" - - name: English Gonol construction tests + - name: Historical English Gonol tests + working-directory: research/english-gonol + run: | + python -m pytest -q tests \ + --ignore=tests/test_ordinal_construct.py \ + --ignore=tests/test_active_construction.py + + - name: Isolated ordinal construction tests working-directory: research/english-gonol - run: python -m pytest -q tests + run: ../../_deps/ordinal-venv/bin/python -m pytest -q tests/test_ordinal_construct.py tests/test_active_construction.py - name: Retain full-corpus metric-origin evidence uses: actions/upload-artifact@v7.0.1 From 06bf3e4f210c19165c451bfa1163b87b9933545b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:24:35 -0700 Subject: [PATCH 15/25] fix(english): bind admission closure to pinned baseline --- .../workflows/english-ordinal-affixiation.yml | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index 91f53b1..b08168c 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -76,15 +76,27 @@ jobs: run: | git fetch --no-tags --depth=1 origin e3eb83764355b4b760a79323cda6a6d75c3a501a _inputs/ucns/.venv/bin/python - <<'PY' - import hashlib,json,pathlib,subprocess - from english_gonol.structural_construct import IMPLEMENTATION_FILES + import ast,hashlib,json,pathlib,subprocess graph=json.loads(pathlib.Path('research/english-gonol/docs/ordinal-work-graph.json').read_text()) body={k:graph[k] for k in ('repositories','boundaries')} assert hashlib.sha256(json.dumps(body,sort_keys=True,separators=(',',':')).encode()).hexdigest()==graph['work_graph_sha256'] - roots={'The-Interdependency/ucns':'_inputs/ucns','globalwordnet/english-wordnet':'_inputs/oewn','The-Interdependency/skill-lib':'_inputs/skill-lib'} + git_roots={ + ('The-Interdependency/ucns','a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb'):'_inputs/ucns', + ('The-Interdependency/ucns','4f863ad37096b7baab8f62820ad5cb937b62a3a7'):'_inputs/admission-carrier', + ('globalwordnet/english-wordnet','dc343f2683279ecbb13fab4e2fd778d7b162d287'):'_inputs/oewn', + ('The-Interdependency/skill-lib','e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128'):'_inputs/skill-lib', + } + artifact_roots={ + 'unicode.org/Public/18.0.0/ucd/UnicodeData.txt':'_inputs/ucd/UnicodeData.txt', + 'unicode.org/Public/18.0.0/ucd/DerivedCoreProperties.txt':'_inputs/ucd/DerivedCoreProperties.txt', + } for item in graph['repositories']: - if item['repository'] in roots: - assert subprocess.check_output(['git','-C',roots[item['repository']],'rev-parse','HEAD'],text=True).strip()==item['commit'] + key=(item['repository'],item.get('commit')) + if key in git_roots: + assert subprocess.check_output(['git','-C',git_roots[key],'rev-parse','HEAD'],text=True).strip()==item['commit'] + elif item['repository'] in artifact_roots: + raw=pathlib.Path(artifact_roots[item['repository']]).read_bytes() + assert hashlib.sha256(raw).hexdigest()==item['artifact_sha256'] active_base=json.loads(pathlib.Path('research/english-gonol/BASE.json').read_text()) selected=active_base['active_construction']['source_commit'] assert len(selected)==40 and all(c in '0123456789abcdef' for c in selected) @@ -94,6 +106,14 @@ jobs: path='research/english-gonol/'+relative assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',selected+':'+path]),path base=next(r['commit'] for r in graph['repositories'] if r['repository']=='The-Interdependency/stack') + baseline_path='research/english-gonol/english_gonol/structural_construct.py' + baseline_source=subprocess.check_output(['git','show',base+':'+baseline_path],text=True) + tree=ast.parse(baseline_source) + assignment=next(node for node in tree.body if isinstance(node,(ast.Assign,ast.AnnAssign)) + and ((isinstance(node,ast.Assign) and any(isinstance(t,ast.Name) and t.id=='IMPLEMENTATION_FILES' for t in node.targets)) + or (isinstance(node,ast.AnnAssign) and isinstance(node.target,ast.Name) and node.target.id=='IMPLEMENTATION_FILES'))) + IMPLEMENTATION_FILES=tuple(ast.literal_eval(assignment.value)) + assert IMPLEMENTATION_FILES, 'pinned admission closure must be nonempty' for name in IMPLEMENTATION_FILES: path='research/english-gonol/english_gonol/'+name assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',base+':'+path]),path From 878428ab5f1a4a3613d6ba2d483c1f814e8c4b77 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:24:53 -0700 Subject: [PATCH 16/25] test(english): cover bounded JSON artifact reads --- .../tests/test_ordinal_construct.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/research/english-gonol/tests/test_ordinal_construct.py b/research/english-gonol/tests/test_ordinal_construct.py index 4f59ba3..bb33ccf 100644 --- a/research/english-gonol/tests/test_ordinal_construct.py +++ b/research/english-gonol/tests/test_ordinal_construct.py @@ -408,3 +408,57 @@ def test_build_refuses_oversize_ucd_before_source_or_copy(tmp_path): with pytest.raises(ValueError, match='acquisition budget'): implementation.build(tmp_path / 'missing-admission', path, output) assert not output.parent.exists() + + +@pytest.mark.parametrize('kind', ['symlink', 'directory', 'fifo']) +def test_json_read_refuses_nonregular_inputs(tmp_path, kind): + path = tmp_path / 'manifest.json' + if kind == 'symlink': + target = tmp_path / 'target.json' + target.write_bytes(b'{}\n') + path.symlink_to(target) + elif kind == 'directory': + path.mkdir() + else: + if not hasattr(implementation.os, 'mkfifo'): + pytest.skip('platform has no FIFO filesystem objects') + implementation.os.mkfifo(path) + with pytest.raises(ValueError, match='regular nonsymlink'): + implementation._json_read(path) + + +def test_json_read_refuses_oversize_before_open(tmp_path, monkeypatch): + path = tmp_path / 'manifest.json' + with path.open('wb') as stream: + stream.truncate(65) + monkeypatch.setattr(implementation, 'JSON_MAX_BYTES', 64) + def forbidden_open(*args, **kwargs): + raise AssertionError('oversize JSON artifact was opened') + monkeypatch.setattr(implementation.os, 'open', forbidden_open) + with pytest.raises(ValueError, match='read budget'): + implementation._json_read(path) + + +def test_json_stream_read_is_capped_if_file_grows(tmp_path, monkeypatch): + from contextlib import contextmanager + path = tmp_path / 'manifest.json' + path.write_bytes(b'{}\n') + monkeypatch.setattr(implementation, 'JSON_MAX_BYTES', 32) + fdopen = implementation.os.fdopen + requested = [] + @contextmanager + def tracked_open(fd, mode): + with fdopen(fd, mode) as stream: + class Tracked: + def fileno(self): + return stream.fileno() + def read(self, count): + requested.append(count) + with path.open('ab') as writer: + writer.write(b'x' * 64) + return stream.read(count) + yield Tracked() + monkeypatch.setattr(implementation.os, 'fdopen', tracked_open) + with pytest.raises(ValueError, match='read budget'): + implementation._json_read(path) + assert requested == [33] From 315370010c80680c6c8fad99a2d9bcdb3d592802 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:24:57 -0700 Subject: [PATCH 17/25] test(english): pin workflow isolation and baseline closure --- .../tests/test_active_construction.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 9fbab51..69c62bf 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -188,3 +188,32 @@ def test_auxiliary_source_graph_is_outside_verified_construction(): if 'research/english-gonol/docs/ordinal-work-graph.json' in words: copies.append(words[-1]) assert copies == ['_evidence/source-work-graph.json'] + + +def test_full_workflow_uses_baseline_owned_admission_inventory(): + import yaml + root = Path(entry.__file__).resolve().parents[3] + workflow = yaml.load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text(), + Loader=yaml.BaseLoader) + steps = workflow['jobs']['full-corpus']['steps'] + command = next(step['run'] for step in steps + if step.get('name') == 'Verify exact participant graph and unchanged source reader') + assert "git','show',base+':'+baseline_path" in command + assert "ast.literal_eval(assignment.value)" in command + assert "from english_gonol.structural_construct import IMPLEMENTATION_FILES" not in command + + +def test_general_workflow_isolates_ordinal_ucns_package(): + import yaml + root = Path(entry.__file__).resolve().parents[3] + workflow = yaml.load((root / '.github/workflows/english-gonol.yml').read_text(), + Loader=yaml.BaseLoader) + steps = workflow['jobs']['english-gonol-tests']['steps'] + install = next(step['run'] for step in steps if step.get('name') == 'Install construction prerequisites') + historical = next(step['run'] for step in steps if step.get('name') == 'Historical English Gonol tests') + ordinal = next(step['run'] for step in steps if step.get('name') == 'Isolated ordinal construction tests') + assert './_deps/ucns-ordinal' not in install.splitlines()[0] + assert '_deps/ordinal-venv' in install + assert '--ignore=tests/test_ordinal_construct.py' in historical + assert '--ignore=tests/test_active_construction.py' in historical + assert '../../_deps/ordinal-venv/bin/python' in ordinal From f1ae89a39d90f0e54ddd3e9407a2bc4506fd8d83 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:25:37 -0700 Subject: [PATCH 18/25] fix(stack): admit immutable artifact identities in research graph --- tools/check_stack_consistency.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/check_stack_consistency.py b/tools/check_stack_consistency.py index 1f1db15..ebd3344 100644 --- a/tools/check_stack_consistency.py +++ b/tools/check_stack_consistency.py @@ -120,9 +120,14 @@ def check_manifest_shape(manifest: dict[str, Any], findings: list[str]) -> None: if not HEX40.fullmatch(commit): error(findings, "repository.commit", f"{entry.get('repository')}: invalid commit {commit!r}") for entry in manifest.get("research_participants", []): - commit = entry.get("commit", "") - if not HEX40.fullmatch(commit): + commit = entry.get("commit") + artifact_sha256 = entry.get("artifact_sha256") + if (commit is None) == (artifact_sha256 is None): + error(findings, "research.identity", f"{entry.get('workspace')}:{entry.get('participant_id')}: exactly one of commit or artifact_sha256 is required") + elif commit is not None and not HEX40.fullmatch(str(commit)): error(findings, "research.commit", f"{entry.get('workspace')}:{entry.get('participant_id')}: invalid commit {commit!r}") + elif artifact_sha256 is not None and re.fullmatch(r"[0-9a-f]{64}", str(artifact_sha256)) is None: + error(findings, "research.artifact_sha256", f"{entry.get('workspace')}:{entry.get('participant_id')}: invalid artifact_sha256 {artifact_sha256!r}") if entry.get("authority_transfer") is not False: error(findings, "research.authority_transfer", f"{entry.get('workspace')}:{entry.get('participant_id')} must keep authority_transfer=false") @@ -166,15 +171,18 @@ def check_research_participants( participant_id = str(entry.get("participant_id", "")) repository = str(entry.get("repository", "")) commit = str(entry.get("commit", "")) + artifact_sha256 = str(entry.get("artifact_sha256", "")) key = (workspace, participant_id) if key in keys: error(findings, "research.duplicate", f"duplicate research participant {key!r}") keys.add(key) - sources.add((workspace, repository, commit)) + if commit: + sources.add((workspace, repository, commit)) if workspace and workspace not in human: error(findings, "research.human_drift", f"STACK_MANIFEST.md does not mention workspace {workspace!r}") - if commit and commit not in human: - error(findings, "research.human_drift", f"STACK_MANIFEST.md does not mention research commit {commit!r}") + identity = commit or artifact_sha256 + if identity and identity not in human: + error(findings, "research.human_drift", f"STACK_MANIFEST.md does not mention research identity {identity!r}") return keys, sources From 2bca0cb9a97b7f521b6d4a4fdd6b198b48c76d52 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:25:58 -0700 Subject: [PATCH 19/25] fix(english): bind carrier and Unicode inputs in source graph --- .../docs/ordinal-work-graph.json | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/research/english-gonol/docs/ordinal-work-graph.json b/research/english-gonol/docs/ordinal-work-graph.json index cd30f14..5521ec3 100644 --- a/research/english-gonol/docs/ordinal-work-graph.json +++ b/research/english-gonol/docs/ordinal-work-graph.json @@ -8,6 +8,12 @@ "authority": "generic exact ordinal geometry", "relation": "new producer; no English semantic authority" }, + { + "repository": "The-Interdependency/ucns", + "commit": "4f863ad37096b7baab8f62820ad5cb937b62a3a7", + "authority": "historical scalar-admission carrier", + "relation": "retained source-admission carrier only; historical angles are not consumed by the replacement constructor" + }, { "repository": "The-Interdependency/stack", "commit": "e3eb83764355b4b760a79323cda6a6d75c3a501a", @@ -20,6 +26,18 @@ "authority": "complete English corpus evidence", "relation": "all exact pinned source records" }, + { + "repository": "unicode.org/Public/18.0.0/ucd/UnicodeData.txt", + "artifact_sha256": "0736451de439ae7baf1425136617da495e09ee5afbe6e394374db7009ea08950", + "authority": "Unicode 18.0.0 numeric-category source", + "relation": "immutable release file identity consumed by public-gonol admission" + }, + { + "repository": "unicode.org/Public/18.0.0/ucd/DerivedCoreProperties.txt", + "artifact_sha256": "09c928886a178fcafd93c29e4bd59073a058e5a100b716d425cb563ab50f68c9", + "authority": "Unicode 18.0.0 Math-property source", + "relation": "immutable release file identity consumed by public-gonol admission" + }, { "repository": "The-Interdependency/skill-lib", "commit": "e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128", @@ -39,5 +57,5 @@ "The historical admission carrier is pinned separately in preserved source metadata; its angles are not consumed by the new constructor." ] }, - "work_graph_sha256": "7d0ec15d06ed32c29f8352afb63b3b73be340f1dace935f1da4e43b207a483b0" + "work_graph_sha256": "5d92bd50ce35e27ea81b815f3b90cead901fcf6eb275c56ec3e451ce7ba3d219" } From 8a048fd6e0cfd63de60e6c28cf0da148d4fb0937 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:26:17 -0700 Subject: [PATCH 20/25] fix(stack): record Unicode artifact identities --- stack-manifest.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/stack-manifest.json b/stack-manifest.json index c451706..de7aed2 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "70578d9ee468b21165b7bc7fedaf799fb6e84245246302ff25cbc7139deb0635", + "work_graph_sha256": "21c6c86927a1d8bf29b965af4d2ade83f1e085c1f9857062895e687e00b5ec7b", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -524,6 +524,26 @@ "canonical_release": false, "authority_transfer": false }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-unicode-data", + "repository": "unicode.org/Public/18.0.0/ucd/UnicodeData.txt", + "artifact_sha256": "0736451de439ae7baf1425136617da495e09ee5afbe6e394374db7009ea08950", + "authority": "Unicode 18.0.0 numeric-category source", + "relation": "exact immutable release file consumed by expanded public-gonol admission", + "canonical_release": false, + "authority_transfer": false + }, + { + "workspace": "research/english-gonol/", + "participant_id": "ordinal-unicode-math", + "repository": "unicode.org/Public/18.0.0/ucd/DerivedCoreProperties.txt", + "artifact_sha256": "09c928886a178fcafd93c29e4bd59073a058e5a100b716d425cb563ab50f68c9", + "authority": "Unicode 18.0.0 Math-property source", + "relation": "exact immutable release file consumed by expanded public-gonol admission", + "canonical_release": false, + "authority_transfer": false + }, { "workspace": "research/english-gonol/", "participant_id": "ordinal-doctrine", From 2ebf1497e8f6c4ac93a3d99e5dde05bec8ac46c5 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:26:28 -0700 Subject: [PATCH 21/25] docs(stack): project Unicode artifact provenance --- STACK_MANIFEST.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index caf09d4..602b6a8 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -17,7 +17,7 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `70578d9ee468b21165b7bc7fedaf799fb6e84245246302ff25cbc7139deb0635` + `21c6c86927a1d8bf29b965af4d2ade83f1e085c1f9857062895e687e00b5ec7b` - Weave workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - Pi radix workspace creation UTC: `2026-10-10`; bounded cross-base computation starts from Stack `ccf707f933a9611d7b7fe13a0417378d8b453a14` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) @@ -62,13 +62,15 @@ and four-view records below remain historical evidence, not current geometry. Use `PYTHONPATH=research/english-gonol python -m english_gonol profile` to inspect selection, and see [the supported build](research/english-gonol/README.md). -| Participant ID | Repository | Exact commit | Relation | +| Participant ID | Source | Exact identity | Relation | |---|---|---|---| | `ordinal-source` | `The-Interdependency/stack` | `37adccb4c079199d915a49e475af0f426fed0943` | exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority | | `ordinal-geometry` | `The-Interdependency/ucns` | `a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb` | merged UCNS #241 producer; exact local radius and carrier angle law, not global transport or semantic authority | | `ordinal-admission` | `The-Interdependency/stack` | `e3eb83764355b4b760a79323cda6a6d75c3a501a` | unchanged thirteen-file source-reader closure; source admission is not the selected completed geometry | | `ordinal-admission-carrier` | `The-Interdependency/ucns` | `4f863ad37096b7baab8f62820ad5cb937b62a3a7` | inherited scalar identity admission only; these historical angles do not supply the replacement placement | | `ordinal-corpus` | `globalwordnet/english-wordnet` | `dc343f2683279ecbb13fab4e2fd778d7b162d287` | all exact pinned source records consumed by the ordinal construction | +| `ordinal-unicode-data` | `unicode.org/Public/18.0.0/ucd/UnicodeData.txt` | `0736451de439ae7baf1425136617da495e09ee5afbe6e394374db7009ea08950` | exact immutable Unicode 18.0.0 numeric-category release file consumed by public-gonol admission | +| `ordinal-unicode-math` | `unicode.org/Public/18.0.0/ucd/DerivedCoreProperties.txt` | `09c928886a178fcafd93c29e4bd59073a058e5a100b716d425cb563ab50f68c9` | exact immutable Unicode 18.0.0 Math-property release file consumed by public-gonol admission | | `ordinal-doctrine` | `The-Interdependency/skill-lib` | `e74ce1ee8a2cea50b0a6acce7697a6d3d9b2e128` | separately pinned ordinal work graph doctrine; root operational snapshot remains unchanged | UCNS #241 merged at `6ebbf970ad13a0d2e1c13bd65c496b671e740185`; From 34fdda574f4084da554af97b8e308b4ca177ed08 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:26:43 -0700 Subject: [PATCH 22/25] test(stack): cover artifact provenance identities --- research/english-gonol/tests/test_active_construction.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/research/english-gonol/tests/test_active_construction.py b/research/english-gonol/tests/test_active_construction.py index 69c62bf..999b72a 100644 --- a/research/english-gonol/tests/test_active_construction.py +++ b/research/english-gonol/tests/test_active_construction.py @@ -89,8 +89,9 @@ def test_active_inputs_are_registered_in_root_provenance(): if r['workspace'] == 'research/english-gonol/'] keyed = {r['participant_id']: r for r in records} assert len(keyed) == len(records), 'duplicate source-qualified participant' - source_pairs = {(r['repository'], r['commit']) for r in records} - assert all((r['repository'], r['commit']) in source_pairs + exact_identity = lambda r: r.get('commit') or r.get('artifact_sha256') + source_pairs = {(r['repository'], exact_identity(r)) for r in records} + assert all((r['repository'], exact_identity(r)) in source_pairs for r in graph['repositories']) assert keyed['ordinal-geometry']['commit'] == profile['geometry_commit'] assert base['ucns_prerequisite']['commit'] == profile['geometry_commit'] @@ -102,9 +103,11 @@ def test_active_inputs_are_registered_in_root_provenance(): assert digest == manifest['work_graph_sha256'] assert digest in human for participant_id, record in keyed.items(): - assert record['commit'] in human + assert exact_identity(record) in human if participant_id.startswith('ordinal-'): assert participant_id in human + assert keyed['ordinal-unicode-data']['artifact_sha256'] == implementation.UCD_RELEASE_SHA256['UnicodeData.txt'] + assert keyed['ordinal-unicode-math']['artifact_sha256'] == implementation.UCD_RELEASE_SHA256['DerivedCoreProperties.txt'] def test_full_workflow_covers_admission_dependencies(): From 2ba7131c5931cccbd779ed08b59f8a2a356729d4 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 05:51:13 -0700 Subject: [PATCH 23/25] feat(english): reconstruct inherited definitions over the ordinal base Apply operator answer 4 in executable build and independent verification: preserve the unchanged definition table and final-y behavior, expand carrier coverage, and require source-bound character-definitions.json with no historical geometry fallback. Add 19 definition/integration cases; update manifest fixture and isolated CI coverage. Preserve concurrent baseline-owned admission and package-isolation repairs. Acquire Unicode before verifying artifact identities. Local focused suite: 85 passed with the unused historical constructor import poisoned. Complete supplied-field definition replay: 4698 characters, 4757 definition closures, ten number-name interiors matching corpus word receipts, 4643 explicit unknowns. This is not current-head hosted/full-admission evidence. Applies wdll, gonol-build, msdmd, meta-module-build and stack-update. Source repinning follows in the same guarded branch transaction. --- .github/workflows/english-gonol.yml | 3 +- .../workflows/english-ordinal-affixiation.yml | 41 ++-- research/english-gonol/README.md | 21 +- .../english-gonol/docs/ordinal-questions.md | 202 ++++++---------- .../english_gonol/ordinal_construct.py | 20 +- .../english_gonol/ordinal_definitions.py | 216 ++++++++++++++++++ .../migration-witness.json | 31 +++ .../tests/test_ordinal_construct.py | 3 +- .../tests/test_ordinal_definitions.py | 158 +++++++++++++ 9 files changed, 533 insertions(+), 162 deletions(-) create mode 100644 research/english-gonol/english_gonol/ordinal_definitions.py create mode 100644 research/english-gonol/experiments/ordinal-definitions/migration-witness.json create mode 100644 research/english-gonol/tests/test_ordinal_definitions.py diff --git a/.github/workflows/english-gonol.yml b/.github/workflows/english-gonol.yml index d4aeae8..d597ff4 100644 --- a/.github/workflows/english-gonol.yml +++ b/.github/workflows/english-gonol.yml @@ -122,11 +122,12 @@ jobs: run: | python -m pytest -q tests \ --ignore=tests/test_ordinal_construct.py \ + --ignore=tests/test_ordinal_definitions.py \ --ignore=tests/test_active_construction.py - name: Isolated ordinal construction tests working-directory: research/english-gonol - run: ../../_deps/ordinal-venv/bin/python -m pytest -q tests/test_ordinal_construct.py tests/test_active_construction.py + run: ../../_deps/ordinal-venv/bin/python -m pytest -q tests/test_ordinal_construct.py tests/test_ordinal_definitions.py tests/test_active_construction.py - name: Retain full-corpus metric-origin evidence uses: actions/upload-artifact@v7.0.1 diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index b08168c..556f887 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -10,6 +10,7 @@ on: - 'STACK_MANIFEST.md' - 'research/english-gonol/tests/test_active_construction.py' - 'research/english-gonol/tests/test_ordinal_construct.py' + - 'research/english-gonol/tests/test_ordinal_definitions.py' - 'research/english-gonol/docs/ordinal-*' - '.github/workflows/english-ordinal-affixiation.yml' permissions: @@ -70,6 +71,24 @@ jobs: python -m pip install uv==0.11.18 PyYAML==6.0.2 uv sync --project _inputs/ucns --locked --python python --extra test uv pip install --python _inputs/ucns/.venv/bin/python PyYAML==6.0.2 + - name: Acquire declared Unicode release and license + env: + SOURCE_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + mkdir -p _inputs/ucd _evidence + for name in UnicodeData.txt DerivedCoreProperties.txt ReadMe.txt; do + curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ + "https://www.unicode.org/Public/18.0.0/ucd/$name" -o "_inputs/ucd/$name" + done + curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ + https://www.unicode.org/license.txt -o _inputs/ucd/LICENSE-Unicode.txt + sha256sum _inputs/ucd/* | tee _evidence/unicode-acquisition.sha256 + git rev-parse HEAD > _evidence/stack-tested-merge.txt + printf '%s\n' "$SOURCE_HEAD" > _evidence/stack-head.txt + git -C _inputs/ucns rev-parse HEAD > _evidence/ucns-head.txt + git -C _inputs/oewn rev-parse HEAD > _evidence/corpus-head.txt + # CI source provenance is separate from the artifact verifier's data contract. + cp research/english-gonol/docs/ordinal-work-graph.json _evidence/source-work-graph.json - name: Verify exact participant graph and unchanged source reader env: PYTHONPATH: research/english-gonol @@ -102,6 +121,9 @@ jobs: assert len(selected)==40 and all(c in '0123456789abcdef' for c in selected) subprocess.run(['git','fetch','--no-tags','--depth=1','origin',selected],check=True) for relative in ('english_gonol/ordinal_construct.py','english_gonol/__main__.py', + 'english_gonol/ordinal_definitions.py', + 'english_gonol/language/character_definitions.py', + 'english_gonol/language/data/character_definitions_v1.json', 'ACTIVE_CONSTRUCTION.json','docs/ordinal-work-graph.json'): path='research/english-gonol/'+relative assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',selected+':'+path]),path @@ -118,24 +140,6 @@ jobs: path='research/english-gonol/english_gonol/'+name assert pathlib.Path(path).read_bytes()==subprocess.check_output(['git','show',base+':'+path]),path PY - - name: Acquire declared Unicode release and license - env: - SOURCE_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} - run: | - mkdir -p _inputs/ucd _evidence - for name in UnicodeData.txt DerivedCoreProperties.txt ReadMe.txt; do - curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ - "https://www.unicode.org/Public/18.0.0/ucd/$name" -o "_inputs/ucd/$name" - done - curl --fail --location --retry 3 --proto '=https' --tlsv1.2 \ - https://www.unicode.org/license.txt -o _inputs/ucd/LICENSE-Unicode.txt - sha256sum _inputs/ucd/* | tee _evidence/unicode-acquisition.sha256 - git rev-parse HEAD > _evidence/stack-tested-merge.txt - printf '%s\n' "$SOURCE_HEAD" > _evidence/stack-head.txt - git -C _inputs/ucns rev-parse HEAD > _evidence/ucns-head.txt - git -C _inputs/oewn rev-parse HEAD > _evidence/corpus-head.txt - # CI source provenance is separate from the artifact verifier's data contract. - cp research/english-gonol/docs/ordinal-work-graph.json _evidence/source-work-graph.json - name: Unit and cross-repository geometry tests env: PYTHONPATH: research/english-gonol @@ -143,6 +147,7 @@ jobs: _inputs/ucns/.venv/bin/python -m pytest -q \ _inputs/ucns/tests/test_ordinal_affixiation.py \ research/english-gonol/tests/test_ordinal_construct.py \ + research/english-gonol/tests/test_ordinal_definitions.py \ research/english-gonol/tests/test_active_construction.py \ | tee _evidence/tests.txt - name: Build complete source admission then the replacement geometry diff --git a/research/english-gonol/README.md b/research/english-gonol/README.md index f3542d7..c3bcd10 100644 --- a/research/english-gonol/README.md +++ b/research/english-gonol/README.md @@ -63,10 +63,12 @@ sealed admission and explicitly historical replay; retention grants no current geometry authority. The supported CLI rejects retired profile commands and does not silently return an old artifact when the ordinal constructor is unavailable. -The prior definition method and applicable functions remain required: reconstruct -them over the new base rather than discard their meanings or restore their old -geometry. [Answer 4](docs/ordinal-questions.md) owns this inheritance instruction, -its inspected source bindings and the outstanding preservation/replay witnesses. +The selected build reconstructs the inherited definition layer over the expanded +carrier in required `character-definitions.json`, bound by its manifest digest. +Independent replay checks every entry, relation, placement and closed interior; +verified entries reuse the previous final-y behavior. The historical constructor +is never used for these closures. [Answer 4](docs/ordinal-questions.md) owns the +source bindings, preservation tests, complete-carrier witness and remaining unknowns. Historical documentation and evidence: @@ -97,9 +99,8 @@ metrics are not renamed as ordinal measurements. ## hmmm -[Answers and remaining work](docs/ordinal-questions.md) separate the settled -radius/angle rule, SPACE references and inherited definition method from -outstanding implementation witnesses. Native Mobius integration is not required -by this profile. Only question 5, vocabulary growth, remains a construction -question; attachment verification, definition reconstruction/replay and downstream -inference evidence remain engineering/evidence boundaries. +[Answers and remaining work](docs/ordinal-questions.md) distinguish the implemented +inherited definitions from current-head full-corpus and downstream evidence. +SPACE is the specified attachment reference; global transport still needs its +witness. Native Mobius integration is not required. Vocabulary growth is the +remaining construction question; source-uncovered definitions remain explicit. diff --git a/research/english-gonol/docs/ordinal-questions.md b/research/english-gonol/docs/ordinal-questions.md index cfc2074..928fe17 100644 --- a/research/english-gonol/docs/ordinal-questions.md +++ b/research/english-gonol/docs/ordinal-questions.md @@ -1,147 +1,95 @@ # Ordinal construction: answers and remaining work -The selected implementation is `english.ordinal/1`; inspect it with +`english.ordinal/1` is the selected construction. Inspect it with `PYTHONPATH=research/english-gonol python -m english_gonol profile`. -Run `verify OUTPUT` before using a generated field. These boundaries do not -reopen the specified ordinal-distance/carrier-angle rule or block its use. +Run `verify OUTPUT` before consuming an artifact. These boundaries do not reopen +the specified construction or turn engineering work into operator questions. -## Already answered and implemented +## Construction law -For zero-based ordinal i among n participants, radius is R/2**(n-i); the newest -participant is at R/2. Angle is the participant's exact index/arity on its -explicit carrier. Closed interiors survive recursive atomic participation. -The initial equidistant field and its circular placement are distinct stages; -planar placement is not claimed to preserve all initial pairwise distances. +For zero-based occurrence i among n participants, radius is R/2**(n-i); the newest +is at R/2. Angle is the participant's exact index/arity on its declared carrier. +Closed interiors remain recoverable through recursive atomic participation. +The initial equidistant field and subsequent circular placement are distinct; +the latter is not claimed to preserve every initial pairwise distance. -This selected version uses balanced insertion around inherited scalar anchors, -and orders its word carrier by sequences of public-gonol indexes. These are -explicit implementation choices, not discovered semantic laws. This merge keeps -them fixed; changing either requires a new profile and rebuilt receipts. +This profile uses balanced insertion around inherited scalar anchors and orders +its word carrier by public-gonol-index sequences. These are explicit versioned +layout choices, not discovered semantic laws. Changing them requires rebuilding. -## Construction answers and questions, ordered by dependency +## Operator answers -### 1. Nested attachment: SPACE — specified; transport unverified +### 1. Nested attachment: SPACE -Operator answer to the nested-frame attachment question: `1. space`. -SPACE supplies the attachment reference between a closed construction's local -frame and its consuming frame. Do not ask the operator to select that reference -again. The already-specified ordinal-distance and carrier-angle laws remain in -force; this answer does not authorize substituting a different construction. +Operator answer: `1. space`. SPACE supplies the attachment reference between a +closed construction and its consuming frame. Do not ask for this choice again. +`Factory.word`, `Factory.record` and independent frame replay preserve the SPACE +origin. Stored origins and closure links do not alone establish evaluated global +transport. Implementing and testing that transport remains engineering work, +without substituting an implicit rotation, translation or scale law. -In `../english_gonol/ordinal_construct.py`, both `Factory.word` and -`Factory.record` already declare `origin='SPACE'`; `_independent_frame` checks -the same origin in frame rows and closure receipts. That existing declaration -is not an evaluated transport between frames. +### 2. Compound definition attachment: SPACE -Current behavior: preserve separate local frames and their links. Remaining -implementation/evidence boundary: an explicit UCNS transport using the specified -SPACE attachment, with nested-order recovery and a tested composition law. -Do not invent an implicit rotation, translation or scale law to turn the stored -origin name into a completion claim. Record the implemented transport and its -evidence here when available; keep specification and implementation distinct. - -### 2. Compound definition attachment: SPACE — specified; witness outstanding - -Operator answer to the compound definition-origin question: `2. space`. -SPACE supplies the attachment reference for a multiword lexical entry's -definition, as it does for nested frames in answer 1. Do not ask the operator -to select that reference again or substitute a constituent word as the origin. - -Preserve the compound entry's exact source ownership, constituent order and -definition succession. Apply the specified SPACE reference when implementing -its attachment; naming the reference does not establish evaluated transport. - -Completion witness: every compound definition has a source-bound SPACE -attachment that preserves its entry, constituent order and definition -succession. Record the implemented attachment and independent verification here -when available; the reference is specified, while that witness remains -outstanding. +Operator answer: `2. space`. A multiword lexical entry's definition attaches at +SPACE, not an arbitrarily chosen constituent word. Preserve exact entry ownership, +constituent order and definition succession. A source-bound attachment witness is +still required; the reference itself is settled. ### 3. Native Mobius integration: not required -Operator answer to the native Mobius integration question: `3. not required`. -Native Mobius lifting, sheet-state transport and 360/720-degree return tests are -outside the required scope of `english.ordinal/1`. They are neither outstanding -construction questions nor completion or merge prerequisites for this profile. -This scope decision does not claim a verified lift, retire UCNS native Mobius -work, or remove the SPACE attachment obligations in answers 1 and 2. +Operator answer: `3. not required`. Native lifting, sheet-state transport and +360/720-degree return tests are outside this profile's requirements, not open +questions or completion/merge prerequisites. This does not retire UCNS native +Mobius work or remove the SPACE attachment obligations. -### 4. Operator definitions: inherit and reconstruct on the new base — specified; replay outstanding +### 4. Prior definitions and applicable functions: reconstructed on the new base -Operator answer: "define them the same way the previous iteration did. most of +Operator answer: `define them the same way the previous iteration did. most of that part of the previous implementation should still apply, just requires -iteration over the new base." - -Preserve the previous definition content, source-backed glyph/function -associations, constitutive relations and implemented behavior wherever compatible -with the replacement. Reconstruct those definitions and their ordered interiors -through the expanded public gonol and ordinal law. Changed carrier positions, -arity, placement and receipts are not changes of meaning. Retain exact scalar -identity, multiple applicable definitions, order, multiplicity and provenance. -Do not ask the operator to redesign this layer or introduce a separate arithmetic -or logical evaluator as a prerequisite for the requested inheritance. - -Inspected inheritance sources at Stack commit -`ee130be77537419040973a665bd47fbb833328e2`: - -- `../english_gonol/language/data/character_definitions_v1.json` owns the curated - character-definition payload, explicitly marked candidate evidence rather than - linguistic or cultural canon. Its `-` has both operator and punctuation roles; - digit number-name links and the other declared definition fields are retained. -- `../english_gonol/language/character_definitions.py` loads those definitions, - retains overlapping roles, fills uncovered legacy carrier members with explicit - `hmmm`, and constructs character/definition closures. Its `PUBLIC_GONOL_157` - coverage loop and imported historical `construct_gonol` are old-base bindings, - not supported geometry for the replacement. General arithmetic or logical - evaluation is not established merely by this table's operator-class labels. - -Implementation work: separate reusable definition inputs and applicable behavior -from the retired carrier/constructor binding, enumerate the actual expanded -carrier, and reconstruct with the selected constructor. For additional scalars, -apply the prior source-backed definition/admission method wherever it resolves an -entry; leave genuinely unavailable definitions explicitly `hmmm`. Neither copy -an old index as a new address nor invent meanings from a symbol's appearance. - -Completion witness: complete new-carrier coverage; comparison showing unchanged -inherited definition content, roles, source associations and applicable behavior; -new-profile angles/radii and receipts; exact recovery of definition interiors; -and explicit unresolved entries. Regressions must detect a lost role of `-`, -changed digit number-name linkage, stale 157-position coverage, old-constructor -fallback and claimed resolution of an inherited `hmmm`. This record resolves the -instruction; it does not claim that reconstruction or its replay has run. - -### 5. How should previously unseen words and future carrier members enter? - -Current behavior: exact pinned repertoire; queries refuse unknown words and -unadmitted scalars, with no normalization or dynamic carrier mutation. A new -carrier/profile must rebuild all affected placements because changing N or order -changes angles. Supporting open-text word closure requires an explicit composite -carrier admission rule; it must not use a last-glyph angle or an invented hash -angle as a substitute. - -Completion witness: deterministic growth/upgrade policy, old-profile replay, and -no silent reinterpretation of previously constructed objects. - -## Engineering work, not questions to send back to the operator - -- Reconstruct inherited definitions/functions over the new base and verify their - preservation as specified in answer 4; this is not a new operator-design question. -- Separate the source-admission helper closure from the historical builder modules - before physically removing those modules. They are retired as new-construction - routes now; deleting dependencies first would break the replacement's verifier. -- Migrate the extracted UCHC candidate and each pinned EDCM/ZFAE/a0 consumer through - its own exact input and replay contract. This source selection is not an - independent release, deployment, or retroactive recertification. -- Publish the complete generated artifact on a durable, versioned distribution - surface; GitHub Actions artifacts have their own retention lifecycle. -- Select a concrete downstream task and predeclared comparison to test utility. - Exact construction and recovery do not establish inference quality. +iteration over the new base.` + +`../english_gonol/language/character_definitions.py` and its +`data/character_definitions_v1.json` remain the unchanged definition/behavior +sources. The replacement `../english_gonol/ordinal_definitions.py` iterates the +expanded carrier, retaining every inherited entry, overlapping role, pronunciation, +orthographic rule, number-name link, numerology entry and explicit unknown. +It calls UCNS ordinal affixiation, never the historical constructor. Verified +entries reuse the prior final-y behavior rather than duplicate its law. + +The supported `build` now requires `character-definitions.json`. Its digest is +mandatory in the geometry manifest; `verify` replays every definition placement, +ordered interior, source binding and carrier index by an independent formula. +Missing, extra, reordered or altered data fail. Existing artifacts must be rebuilt; +old receipts are not rebranded as evidence for the changed implementation. + +The committed `../experiments/ordinal-definitions/migration-witness.json` records +reconstruction over all 4,698 scalars from the supplied complete field: 4,757 +definition closures and ten number-name interiors matching existing corpus word +receipts. The inherited source leaves 4,643 scalar definitions explicitly unknown. +This is full definition-layer coverage, not a new complete-corpus admission replay +or current-head hosted CI. `../tests/test_ordinal_definitions.py` supplies +preservation, no-old-constructor, independent-replay and corruption tests. + +### 5. Vocabulary growth: open + +Current behavior is an exact pinned repertoire. Queries reject unknown words and +unadmitted scalars, without normalization or dynamic carrier mutation. Changing +carrier order or arity requires a new profile and rebuilding affected placements. +An open-text admission policy must preserve old-profile replay and avoid silent +reinterpretation; neither last-glyph angles nor invented hash angles substitute +for that policy. This question does not block the existing pinned construction. + +## Engineering, not further questions for the operator + +SPACE transport/compound-attachment verification; separating the sealed admission +helper closure before physically removing retired modules; exact downstream +UCHC/EDCM/ZFAE/a0 migration; durable artifact publication; and utility testing +against a predeclared downstream comparison remain distinct work. Source selection +is neither independent UCHC release nor semantic or measurement validation. ## hmmm -SPACE is the specified attachment reference for both nested frames and compound -definitions. Native Mobius integration is excluded; prior operator definitions -are inherited and reconstructed on the new base. Only question 5 remains open. -SPACE attachment and inherited-definition reconstruction/replay witnesses remain -outstanding. Merge closes source integration and default selection, not these -implementation/evidence boundaries or downstream migration. +Only question 5 remains a construction choice. The inherited definition migration +is executable and locally tested; current-head full-corpus build/replay and review +must establish their own evidence. SPACE reference choices are settled while their +global transport witnesses remain outstanding. Native Mobius integration is excluded. diff --git a/research/english-gonol/english_gonol/ordinal_construct.py b/research/english-gonol/english_gonol/ordinal_construct.py index 165ecc1..58069e1 100644 --- a/research/english-gonol/english_gonol/ordinal_construct.py +++ b/research/english-gonol/english_gonol/ordinal_construct.py @@ -43,7 +43,7 @@ # tests: tests/test_ordinal_construct.py # rollout: explicit replacement profile english.ordinal/1; legacy receipts remain historical # rollback: remove candidate import/output; no silent profile downgrade -# unresolved: native Mobius lift, global frame attachment, semantic interpretation +# unresolved: global SPACE-frame transport, source-uncovered definitions, semantic interpretation # === END MODULE_BUILD === # === CONTRACTS === # id: english_expanded_repertoire @@ -71,12 +71,12 @@ MANIFEST_BOUNDARIES = ( 'Local frame placement is constructed; global origin attachment is not inferred.', 'Layout recipes are explicit profile choices, not discovered semantic laws.', - 'Native Mobius lift and inference quality remain untested.', + 'Native Mobius lift is not required; inference quality remains untested.', ) MANIFEST_KEYS = frozenset(( 'schema', 'source_receipt', 'source', 'ucns_commit', 'implementation_sha256', 'public_sha256', 'glyph_carrier_receipt', 'word_carrier_receipt', 'counts', - 'geometry_receipt', 'hmmm', + 'geometry_receipt', 'character_definitions_receipt', 'hmmm', )) LOGIC = tuple('¬∧∨⊻⊼⊽→←↔⇒⇐⇔∀∃∄⊢⊣⊤⊥⊨⊭⊬⊮⊯≡≠=<>≤≥') LAYOUT = 'legacy-anchor-balanced-insertion/1' @@ -389,6 +389,9 @@ def build(admission: Path, ucd: Path, output: Path) -> dict: legacy = tuple(source_manifest['metadata']['producer']['carrier']) public = repertoire(tuple(chars.values()), legacy, stage / 'ucd') factory = Factory(public, words, source_manifest['receipt_sha256']) + from english_gonol.ordinal_definitions import build_definitions + definitions = build_definitions(factory) + _json_write(stage / 'character-definitions.json', definitions) _json_write(stage / 'public-gonol.json', public) _json_write(stage / 'word-carrier.json', { 'layout': WORD_LAYOUT, 'identities': list(factory.word_carrier.identities), @@ -421,6 +424,7 @@ def build(admission: Path, ucd: Path, output: Path) -> dict: 'glyph_carrier_receipt': factory.glyph_carrier.receipt, 'word_carrier_receipt': factory.word_carrier.receipt, 'counts': counts, 'geometry_receipt': _geometry_receipt(geometry), + 'character_definitions_receipt': digest(definitions), 'hmmm': list(MANIFEST_BOUNDARIES)} _json_write(stage / 'manifest.json', manifest) report = verify(stage) @@ -472,7 +476,7 @@ def _validate_manifest(manifest: object) -> None: or any(type(v) is not int or v <= 0 for v in counts.values())): raise ValueError('manifest counts must be positive integer frame/placement counts') for key in ('source_receipt', 'public_sha256', 'glyph_carrier_receipt', - 'word_carrier_receipt', 'geometry_receipt'): + 'word_carrier_receipt', 'geometry_receipt', 'character_definitions_receipt'): value = manifest[key] if (type(value) is not str or len(value) != 64 or any(c not in '0123456789abcdef' for c in value)): @@ -505,6 +509,11 @@ def verify(output: Path) -> dict: if (factory.glyph_carrier.receipt != manifest['glyph_carrier_receipt'] or factory.word_carrier.receipt != manifest['word_carrier_receipt']): raise ValueError('carrier receipt mismatch') + from english_gonol.ordinal_definitions import verify_definitions + definitions = _json_read(output / 'character-definitions.json') + if digest(definitions) != manifest['character_definitions_receipt']: + raise ValueError('character definition receipt mismatch') + definition_layer = verify_definitions(factory, definitions) word_receipts = {} character_ids = {c: cid for cid, c in chars.items()} with closing(open_readonly(output / 'geometry.db')) as db: @@ -547,7 +556,8 @@ def check(kind, frame_id, identity, relation, refs): return {'schema': 'english.ordinal-verification/1', 'status': 'SURVIVED', 'scope': 'complete pinned corpus; source recovery plus every local placement', 'public_gonol_size': len(public['identities']), 'words': len(words), - **counts, 'manifest_sha256': digest(manifest), + **counts, 'character_definitions': dict(definition_layer.counts), + 'manifest_sha256': digest(manifest), 'source_receipt': manifest['source_receipt'], 'hmmm': list(MANIFEST_BOUNDARIES)} diff --git a/research/english-gonol/english_gonol/ordinal_definitions.py b/research/english-gonol/english_gonol/ordinal_definitions.py new file mode 100644 index 0000000..2f12f69 --- /dev/null +++ b/research/english-gonol/english_gonol/ordinal_definitions.py @@ -0,0 +1,216 @@ +"""Reconstruct inherited character definitions on the selected ordinal base. + +The existing character table and final-y implementation remain their owners. +Only data/behavior is consumed from that historical module; its constructor is +never called. Every admitted scalar receives its prior entry or explicit hmmm. + +Usage with an ordinal_construct.Factory: + payload = build_definitions(factory) + layer = verify_definitions(factory, payload) + assert layer.final_y_realization('y', 'r', 'ing', True) == 'preserve-y' + +The main ordinal build owns persistence. This file neither mutates a carrier nor +admits a missing number-name word. Pronunciation/numerology remain source-owned +candidate definition content, not added identity rules or validated science. +""" +from __future__ import annotations + +from dataclasses import asdict, dataclass +from fractions import Fraction +from hashlib import sha256 +import json +from pathlib import Path +from types import MappingProxyType +from typing import Mapping + +from ucns.ordinal_affixiation import Participant, affixiate +from .language import character_definitions as inherited + +# === MODULE_BUILD === +# id: english_ordinal_inherited_definitions +# module_name: ordinal_definitions +# module_kind: engine +# summary: reuse inherited definitions and behavior, reconstruct with UCNS ordinal geometry +# owner: Erin Spencer +# public_surface: build_definitions, verify_definitions, VerifiedDefinitions +# internal_surface: inherited source admission, relation iteration, independent placement replay +# auth_boundary: read +# user_data_boundary: none +# admin_only: false +# network_boundary: none +# storage_boundary: read +# tests: tests/test_ordinal_definitions.py +# rollout: constitutive required component of the selected ordinal artifact +# rollback: rebuild explicitly; no historical constructor fallback +# unresolved: source-uncovered definitions remain hmmm; global attachment transport is separate +# === END MODULE_BUILD === +# === CONTRACTS === +# id: ordinal_inherited_definition_preservation +# given: the existing character definition source and the expanded public carrier +# then: retain entries, overlapping roles, word links, order, provenance and explicit unknowns +# id: ordinal_definition_replay +# given: serialized character and definition closures on the selected carriers +# then: independently replay every placement and interior without invoking affixiate +# === END CONTRACTS === + +SCHEMA = 'english.ordinal-character-definitions/1' +SOURCE_PATH = 'english_gonol/language/data/character_definitions_v1.json' + + +def _canonical(value): + return json.dumps(value, ensure_ascii=False, sort_keys=True, + separators=(',', ':'), allow_nan=False).encode('utf-8') + + +def _digest(value): + return sha256(_canonical(value)).hexdigest() + + +def _inputs(factory): + path = Path(inherited.__file__).parent / 'data' / 'character_definitions_v1.json' + raw = path.read_bytes() + entries = inherited.load_character_definition_table(path) + # Source is local repository input, not an artifact's self-declared authority. + if path.read_bytes() != raw: + raise ValueError('definition source changed while loading') + admitted = factory.glyph_carrier.identities + if any(c not in admitted for c, e in entries.items() if not e.hmmm): + raise ValueError('curated definition scalar is not admitted by this carrier') + current = {c: entries.get(c, inherited.CharacterDefinitionEntry( + c, (), None, (), None, (), True)) for c in admitted} + missing = {e.number_name for e in current.values() + if e.number_name and e.number_name not in factory.word_ids} + if missing: + raise ValueError('definition number-name words are not admitted: ' + + ', '.join(sorted(missing))) + return current, { + 'path': SOURCE_PATH, 'sha256': sha256(raw).hexdigest(), + 'text': raw.decode('utf-8'), + 'loader_sha256': sha256(Path(inherited.__file__).read_bytes()).hexdigest(), + } + + +def _relations(char, entry): + """Preserve the prior builder's relation order and source identifiers.""" + for role in entry.classes: + yield f'char-def:{char}:{role}', f'char-class:{role}', None + if entry.pronunciation: + yield (f'char-def:{char}:letter-pronunciation', + f'letter-pronunciation:{entry.pronunciation}', None) + for behavior in entry.orthographic: + yield (f'char-def:{char}:orthographic:{behavior}', + f'orthographic-behavior:{behavior}', None) + if entry.number_name: + yield f'char-def:{char}:number-name', 'digit-number-name', entry.number_name + for index, meaning in enumerate(entry.numerology): + yield f'char-def:{char}:numerology:{index}', f'numerology:{meaning}', None + if entry.hmmm: + yield f'char-def:{char}:hmmm', 'definition:hmmm', None + + +def _reference_frame(identity, participants, relation, source): + """Independent exact formula; never calls affixiate, Placement or record.""" + placements = [] + for i, (carrier, name, interior) in enumerate(participants): + index = carrier.index(name) + turn = Fraction(index, len(carrier.identities)) + placements.append({ + 'identity': name, 'carrier_receipt': carrier.receipt, + 'index': index, 'arity': len(carrier.identities), + 'turn': [turn.numerator, turn.denominator], + 'radius': {'numerator': 1, + 'power_of_two_denominator': len(participants) - i}, + 'interior_receipt': None if interior is None else interior['receipt'], + }) + record = {'schema': 'ucns.ordinal-affixiation.v1', 'identity': identity, + 'origin': 'SPACE', 'relation': relation, 'source': source, + 'placements': placements} + return {'receipt': _digest(record), 'construction': record} + + +def _construct(factory, *, reference): + entries, source = _inputs(factory) + prefix = f'{factory.source_receipt}:definitions:{source["sha256"]}' + objects = {} + + def frame(identity, participants, relation, source_id): + if reference: + return _reference_frame(identity, participants, relation, source_id) + actual = tuple(Participant.atom(carrier, name) if interior is None else + Participant.closed(carrier, objects[interior['receipt']]) + for carrier, name, interior in participants) + closed = affixiate(identity, actual, origin='SPACE', relation=relation, + source=source_id) + objects[closed.receipt] = closed + return {'receipt': closed.receipt, 'construction': closed.record()} + + characters, words, definitions, registry = {}, {}, [], [] + for char, entry in entries.items(): + character = frame(char, ((factory.glyph_carrier, char, None),), + 'character', f'{prefix}:char:{char}') + characters[char] = character + owned = [] + for source_id, relation, name in _relations(char, entry): + participants = [(factory.glyph_carrier, char, character)] + if name is not None: + if name not in words: + # Use the existing closed word's exact identity and source. + wid = factory.word_ids[name] + words[name] = frame(name, tuple( + (factory.glyph_carrier, c, None) for c in name), + 'ordered-glyphs', f'{factory.source_receipt}:word:{wid}') + participants.append((factory.word_carrier, name, words[name])) + definition = frame(source_id, tuple(participants), relation, + f'{prefix}:{source_id}') + owned.append(definition['receipt']) + definitions.append({'owner': char, 'source_id': source_id, **definition}) + registry.append({'scalar': char, 'entry': asdict(entry), + 'character_receipt': character['receipt'], + 'definition_receipts': owned}) + payload = { + 'schema': SCHEMA, 'profile': 'english.ordinal/1', + 'source_receipt': factory.source_receipt, 'source': source, + 'implementation_sha256': sha256(Path(__file__).read_bytes()).hexdigest(), + 'glyph_carrier_receipt': factory.glyph_carrier.receipt, + 'word_carrier_receipt': factory.word_carrier.receipt, + 'entries': registry, 'characters': characters, + 'number_names': words, 'definitions': definitions, + 'counts': {'characters': len(characters), 'definitions': len(definitions), + 'number_names': len(words), + 'unresolved': sum(e.hmmm for e in entries.values())}, + 'hmmm': ['Uncovered scalar definitions remain explicit hmmm.', + 'Local SPACE frames do not prove global attachment transport.', + 'Inherited table content remains candidate evidence, not linguistic or cultural canon.'], + } + # Normalize dataclass tuples once to the actual JSON representation. + return json.loads(_canonical(payload)), entries + + +def build_definitions(factory): + """Construct every current-carrier definition; no old geometry fallback.""" + return _construct(factory, reference=False)[0] + + +@dataclass(frozen=True) +class VerifiedDefinitions: + """Verified immutable entries retain the prior implementation's behavior.""" + entries: Mapping[str, inherited.CharacterDefinitionEntry] + receipt: str + counts: Mapping[str, int] + + def final_y_realization(self, final_character_surface, + preceding_character_surface, suffix_bare, + suffix_vowel_initial): + return inherited.CharacterDefinitionLayer.final_y_realization( + self, final_character_surface, preceding_character_surface, + suffix_bare, suffix_vowel_initial) + + +def verify_definitions(factory, payload): + """Check complete coverage, content, receipts, all local placements and links.""" + expected, entries = _construct(factory, reference=True) + # Canonical bytes distinguish booleans from integer placement/count fields. + if _canonical(payload) != _canonical(expected): + raise ValueError('ordinal inherited-definition replay mismatch') + return VerifiedDefinitions(MappingProxyType(entries), _digest(expected), + MappingProxyType(expected['counts'])) diff --git a/research/english-gonol/experiments/ordinal-definitions/migration-witness.json b/research/english-gonol/experiments/ordinal-definitions/migration-witness.json new file mode 100644 index 0000000..f22ff54 --- /dev/null +++ b/research/english-gonol/experiments/ordinal-definitions/migration-witness.json @@ -0,0 +1,31 @@ +{ + "schema": "english.ordinal-definition-migration-witness/1", + "status": "SURVIVED", + "scope": "Every expanded-carrier character and inherited definition; all ten number-name interiors match prior complete corpus word receipts", + "public_gonol_size": 4698, + "source_words": 103053, + "source_receipt": "26ab095f73306ff4fbd9f67d1c282c1df79f926bb75cc081c879db8a6989b58a", + "public_gonol_sha256": "dc8740a258b95688882b70d4faaa8b96b8f903990f459f4804e779879fca043d", + "definition_receipt": "4889437942cbbc9b9c6d7cb85f466b753669ac2169f6eda3da621ba96c4ed80e", + "counts": { + "characters": 4698, + "definitions": 4757, + "number_names": 10, + "unresolved": 4643 + }, + "behavior": { + "hyphen_roles": ["operator", "punctuation"], + "3_number_name": "three", + "try_ing": "preserve-y", + "try_ed": "y-to-i" + }, + "source_table_sha256": "ba431162c065a033d60f66bfb84d62d93f55ca6ca954ec59756c4bacc854827d", + "source_loader_sha256": "0fe9c8a0ee263c008e530e3df2b521ad4ccb08c50c59939872d7b6fcb9f8e67c", + "implementation_sha256": "8fac12851ab018ccc6355dddf8bf67b52e70706a21c9020ad8dc555a9395d8f9", + "local_checks": {"passed": 85, "failed": 0, "scope": "new definition tests, current ordinal tests, packaged pinned UCNS ordinal tests; unused historical constructor import poisoned in local harness"}, + "hmmm": [ + "Uses supplied complete source/geometry databases, not current whole-repository CI or a new full-corpus admission replay.", + "New scalar definitions absent from the inherited source remain explicitly unresolved.", + "SPACE local-frame and definition-source links are preserved; global geometric transport is not established." + ] +} diff --git a/research/english-gonol/tests/test_ordinal_construct.py b/research/english-gonol/tests/test_ordinal_construct.py index bb33ccf..cdb588d 100644 --- a/research/english-gonol/tests/test_ordinal_construct.py +++ b/research/english-gonol/tests/test_ordinal_construct.py @@ -283,7 +283,8 @@ def manifest_fixture(): 'implementation_sha256': implementation.file_hash(Path(implementation.__file__)), 'public_sha256': 'b' * 64, 'glyph_carrier_receipt': 'c' * 64, 'word_carrier_receipt': 'd' * 64, 'counts': {'frames': 1, 'placements': 1}, - 'geometry_receipt': 'e' * 64, 'hmmm': list(implementation.MANIFEST_BOUNDARIES), + 'geometry_receipt': 'e' * 64, 'character_definitions_receipt': 'f' * 64, + 'hmmm': list(implementation.MANIFEST_BOUNDARIES), } diff --git a/research/english-gonol/tests/test_ordinal_definitions.py b/research/english-gonol/tests/test_ordinal_definitions.py new file mode 100644 index 0000000..ddcbf63 --- /dev/null +++ b/research/english-gonol/tests/test_ordinal_definitions.py @@ -0,0 +1,158 @@ +"""Run with the pinned UCNS: pytest -q tests/test_ordinal_definitions.py. + +These adversarial fixtures verify inheritance and placement, not full-corpus +admission. The hosted complete build remains the full-source witness. +""" +# === CHECKS === +# id: inherited_definitions_match_prior_source +# proves: ordinal_inherited_definition_preservation +# call: self::test_inherited_entries_and_behavior_are_unchanged +# id: definition_geometry_has_no_historical_fallback +# proves: ordinal_definition_replay +# call: self::test_no_old_constructor_and_independent_checker +# id: definition_corruption_is_rejected +# proves: ordinal_definition_replay +# call: self::test_tampering_refuses +# === END CHECKS === +from copy import deepcopy +from dataclasses import asdict +from fractions import Fraction +import json +from types import SimpleNamespace + +import pytest +from english_gonol import ordinal_definitions as definitions +from english_gonol.ordinal_construct import Factory +from english_gonol.language import character_definitions as prior + + +@pytest.fixture +def factory(): + names = ('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine') + public = {'identities': list(prior.PUBLIC_GONOL_157) + ['𝟠'], 'fixture': True} + return Factory(public, dict(enumerate(names)), 'fixture-source') + + +def test_inherited_entries_and_behavior_are_unchanged(factory): + payload = definitions.build_definitions(factory) + layer = definitions.verify_definitions(factory, payload) + old = prior.load_character_definition_table() + assert len(layer.entries) == 158 + assert list(layer.entries) == list(factory.glyph_carrier.identities) + for char, entry in old.items(): + assert asdict(layer.entries[char]) == asdict(entry) + assert layer.entries['-'].classes == ('operator', 'punctuation') + assert layer.entries['y'].classes == ('vowel', 'consonant') + assert layer.entries['3'].number_name == 'three' + assert layer.entries['A'].hmmm and layer.entries['𝟠'].hmmm + for final in ('y', 'Y', 'a'): + for preceding in ('r', 'a', None, '𝟠'): + for suffix, initial in (('ing', True), ('ed', True), ('s', False)): + expected = prior.CharacterDefinitionLayer.final_y_realization( + SimpleNamespace(entries=old), final, preceding, suffix, initial) + assert layer.final_y_realization(final, preceding, suffix, initial) == expected + with pytest.raises(TypeError): + layer.entries['x'] = layer.entries['y'] + + +def test_relation_plan_matches_previous_builder(factory, monkeypatch): + calls = [] + def capture(**kwargs): + calls.append(kwargs) + return SimpleNamespace(gonol=SimpleNamespace(receipt_digest=kwargs['source_id']), + receipt_digest=kwargs['source_id']) + monkeypatch.setattr(prior, 'construct_gonol', capture) + prior.build_character_definition_layer() + observed = {c['source_id']: c.get('relation') for c in calls if c['scale'] == 'definition'} + payload = definitions.build_definitions(factory) + reconstructed = {d['source_id']: d['construction']['relation'] + for d in payload['definitions'] if d['owner'] in prior.PUBLIC_GONOL_157} + assert reconstructed == observed + + +def test_no_old_constructor_and_independent_checker(factory, monkeypatch): + def forbidden(*args, **kwargs): + raise AssertionError('forbidden constructor called') + monkeypatch.setattr(prior, 'construct_gonol', forbidden) + payload = definitions.build_definitions(factory) + monkeypatch.setattr(definitions, 'affixiate', forbidden) + monkeypatch.setattr(factory, 'word', forbidden) + definitions.verify_definitions(factory, payload) + + +def test_new_angles_and_recursive_number_name_recovery(factory): + payload = definitions.build_definitions(factory) + d = next(d for d in payload['definitions'] if d['source_id'] == 'char-def:3:number-name') + positions = d['construction']['placements'] + assert d['construction']['origin'] == 'SPACE' + assert [p['radius']['power_of_two_denominator'] for p in positions] == [2, 1] + assert positions[0]['arity'] == 158 + assert Fraction(*positions[0]['turn']) == factory.glyph_carrier.turn('3') + assert Fraction(*positions[1]['turn']) == factory.word_carrier.turn('three') + assert positions[0]['interior_receipt'] == payload['characters']['3']['receipt'] + assert positions[1]['interior_receipt'] == payload['number_names']['three']['receipt'] + word = payload['number_names']['three']['construction']['placements'] + assert [p['identity'] for p in word] == list('three') + assert [p['radius']['power_of_two_denominator'] for p in word] == [5, 4, 3, 2, 1] + assert payload['number_names']['three']['receipt'] == factory.word(factory.word_ids['three']).receipt + + +@pytest.mark.parametrize('mutate', [ + lambda p: p['entries'].pop(), + lambda p: p['entries'].reverse(), + lambda p: p['definitions'].pop(), + lambda p: p['definitions'][0]['construction']['placements'][0].update(arity=157), + lambda p: p['definitions'][0]['construction']['placements'][0]['radius'].update(power_of_two_denominator=2), + lambda p: p['definitions'][0]['construction']['placements'][0].update(interior_receipt=None), + lambda p: p['counts'].update(characters=True), + lambda p: p['characters']['A']['construction'].update(origin='A'), + lambda p: p['entries'][-1]['entry'].update(hmmm=False), + lambda p: p['source'].update(text='invented table'), + lambda p: p.update(hmmm=[]), +]) +def test_tampering_refuses(factory, mutate): + payload = definitions.build_definitions(factory) + mutate(payload) + with pytest.raises(ValueError, match='replay mismatch'): + definitions.verify_definitions(factory, payload) + + +def test_json_roundtrip_preserves_every_entry_and_closure(factory): + payload = definitions.build_definitions(factory) + restored = json.loads(json.dumps(payload, ensure_ascii=False)) + assert definitions.verify_definitions(factory, payload).receipt == definitions.verify_definitions(factory, restored).receipt + + +def test_missing_number_name_refuses_without_carrier_mutation(factory): + words = {i: word for i, word in factory.words.items() if word != 'three'} + narrowed = Factory(factory.public, words, factory.source_receipt) + before = narrowed.word_carrier.receipt + with pytest.raises(ValueError, match='not admitted: three'): + definitions.build_definitions(narrowed) + assert narrowed.word_carrier.receipt == before + + +def test_default_manifest_requires_definition_receipt(): + from english_gonol import ordinal_construct as implementation + from test_ordinal_construct import manifest_fixture + manifest = manifest_fixture() + assert implementation._validate_manifest(manifest) is None + manifest.pop('character_definitions_receipt') + with pytest.raises(ValueError, match='manifest schema'): + implementation._validate_manifest(manifest) + + +def test_default_build_and_verifier_consume_definition_component(): + import ast + import inspect + from english_gonol import ordinal_construct as implementation + producer = ast.parse(inspect.getsource(implementation.build)) + checker = ast.parse(inspect.getsource(implementation.verify)) + def names(tree): + return {n.func.id for n in ast.walk(tree) + if isinstance(n, ast.Call) and isinstance(n.func, ast.Name)} + assert 'build_definitions' in names(producer) + assert 'verify_definitions' in names(checker) + for tree in (producer, checker): + assert any(isinstance(n, ast.Constant) and n.value == 'character-definitions.json' + for n in ast.walk(tree)) From 3c8e405edcb960ac80e6630609b82d62c301d885 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 06:01:18 -0700 Subject: [PATCH 24/25] chore(stack): bind selected English definition migration source Pin active runtime to 2ba7131c5931cccbd779ed08b59f8a2a356729d4 in BASE and both root projections. Recompute the work-graph digest and correct stale native Mobius/operator boundaries. Preserve canonical libs pins and all unrelated participants. The parent contains executable definition migration and local witnesses; this provenance-only commit adds no hosted CI or full-corpus certification. --- STACK_MANIFEST.md | 6 +++--- research/english-gonol/BASE.json | 2 +- stack-manifest.json | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index 602b6a8..4620c36 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -17,7 +17,7 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `21c6c86927a1d8bf29b965af4d2ade83f1e085c1f9857062895e687e00b5ec7b` + `a28ff770ccb5c7cdae017272dd47e3bacb0b7054b07ebe7086fe26d534aaebb6` - Weave workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - Pi radix workspace creation UTC: `2026-10-10`; bounded cross-base computation starts from Stack `ccf707f933a9611d7b7fe13a0417378d8b453a14` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) @@ -64,7 +64,7 @@ selection, and see [the supported build](research/english-gonol/README.md). | Participant ID | Source | Exact identity | Relation | |---|---|---|---| -| `ordinal-source` | `The-Interdependency/stack` | `37adccb4c079199d915a49e475af0f426fed0943` | exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority | +| `ordinal-source` | `The-Interdependency/stack` | `2ba7131c5931cccbd779ed08b59f8a2a356729d4` | exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority | | `ordinal-geometry` | `The-Interdependency/ucns` | `a7bfa0c96daca1f7445ba57c39fa6d8fd62e51eb` | merged UCNS #241 producer; exact local radius and carrier angle law, not global transport or semantic authority | | `ordinal-admission` | `The-Interdependency/stack` | `e3eb83764355b4b760a79323cda6a6d75c3a501a` | unchanged thirteen-file source-reader closure; source admission is not the selected completed geometry | | `ordinal-admission-carrier` | `The-Interdependency/ucns` | `4f863ad37096b7baab8f62820ad5cb937b62a3a7` | inherited scalar identity admission only; these historical angles do not supply the replacement placement | @@ -272,7 +272,7 @@ establish a base-independent generating law. ## hmmm - UCNS has no `LICENSE` file at pinned commit `828c0b8`. -- English Gonol Construction has selected exact local ordinal geometry; global frame transport, compound origins, native Mobius lift, operator actions and independent release remain unresolved. +- English Gonol Construction has selected exact ordinal geometry with inherited definitions reconstructed on the expanded base. SPACE references are specified; global transport, vocabulary growth, source-uncovered definitions, downstream migration and independent release still need their own evidence. Native Mobius integration is not required. - Python Gonol Construction remains stack-local research; independent repository/release authority and exact UCNS affixiation geometry remain unresolved. - URPCS is retired for specification divergence; why GPT flattened/substituted the intended construction remains unresolved, and retained evidence is scoped only to the substituted implementation. - Weave now runs one explicit native sequence-cycle profile with corpus normalization and prime-derived splits; cryptographic lifting, authentication/state and full-cipher security remain unresolved. diff --git a/research/english-gonol/BASE.json b/research/english-gonol/BASE.json index 9fc8470..bfe300e 100644 --- a/research/english-gonol/BASE.json +++ b/research/english-gonol/BASE.json @@ -33,7 +33,7 @@ "active_construction": { "selection": "ACTIVE_CONSTRUCTION.json", "source_repository": "The-Interdependency/stack", - "source_commit": "37adccb4c079199d915a49e475af0f426fed0943", + "source_commit": "2ba7131c5931cccbd779ed08b59f8a2a356729d4", "work_graph": "../../stack-manifest.json#research_participants[workspace=research/english-gonol/]", "authority_transfer": false } diff --git a/stack-manifest.json b/stack-manifest.json index de7aed2..b7da596 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "21c6c86927a1d8bf29b965af4d2ade83f1e085c1f9857062895e687e00b5ec7b", + "work_graph_sha256": "a28ff770ccb5c7cdae017272dd47e3bacb0b7054b07ebe7086fe26d534aaebb6", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -74,7 +74,7 @@ "Weave native public/private key derivation and source of asymmetry remain unresolved; source-bound key metadata does not establish a native asymmetric law.", "a0 Municipality is specification-first composition research; native semantic-origin/affixiation integration, operational authorities and its fifth workflow remain unresolved; no runtime or six-month proof is established by placement.", "Pi radix research has measured finite cross-base recurrences; a base-independent segmentation or generating law remains unestablished, and no pi normality or cryptographic security follows from the finite prefixes.", - "English ordinal/1 is the selected local construction; nested frame transport, compound origin attachment, native Mobius lift, operator actions and downstream migration remain unresolved." + "English ordinal/1 is selected with inherited definitions reconstructed on its expanded base. SPACE attachment references are specified; global transport, vocabulary growth, source-uncovered definitions and downstream migration remain unresolved. Native Mobius integration is not required." ] }, "research_participants": [ @@ -478,7 +478,7 @@ "workspace": "research/english-gonol/", "participant_id": "ordinal-source", "repository": "The-Interdependency/stack", - "commit": "37adccb4c079199d915a49e475af0f426fed0943", + "commit": "2ba7131c5931cccbd779ed08b59f8a2a356729d4", "authority": "English construction and supported entrypoint", "relation": "exact selected ordinal runtime source and supported entrypoint; no independent UCHC release authority", "canonical_release": false, From 08ccfe65a34bd13cd700604cf7398dce4f27b024 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 14 Oct 2026 06:06:55 -0700 Subject: [PATCH 25/25] fix(ci): reject unmatched ordinal input identities Address PR #88 review 4270796319: every declared participant must map exactly once to an acquired input or the baseline whose sealed closure is checked. Reject unknown, repinned, duplicate and omitted identities; explicitly verify the fetched Stack baseline commit. Five local positive/adversarial cases passed against the exact participant-loop excerpt; committed tests extract the real workflow loop in repository CI. No runtime, selection, work-graph or canonical source-pin bytes change. Complete current-head hosted evidence remains required. --- .../workflows/english-ordinal-affixiation.yml | 13 +++++ .../tests/test_ordinal_source_inputs.py | 55 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 research/english-gonol/tests/test_ordinal_source_inputs.py diff --git a/.github/workflows/english-ordinal-affixiation.yml b/.github/workflows/english-ordinal-affixiation.yml index 556f887..8080132 100644 --- a/.github/workflows/english-ordinal-affixiation.yml +++ b/.github/workflows/english-ordinal-affixiation.yml @@ -11,6 +11,7 @@ on: - 'research/english-gonol/tests/test_active_construction.py' - 'research/english-gonol/tests/test_ordinal_construct.py' - 'research/english-gonol/tests/test_ordinal_definitions.py' + - 'research/english-gonol/tests/test_ordinal_source_inputs.py' - 'research/english-gonol/docs/ordinal-*' - '.github/workflows/english-ordinal-affixiation.yml' permissions: @@ -109,13 +110,24 @@ jobs: 'unicode.org/Public/18.0.0/ucd/UnicodeData.txt':'_inputs/ucd/UnicodeData.txt', 'unicode.org/Public/18.0.0/ucd/DerivedCoreProperties.txt':'_inputs/ucd/DerivedCoreProperties.txt', } + baseline_key=('The-Interdependency/stack','e3eb83764355b4b760a79323cda6a6d75c3a501a') + expected=set(git_roots) | {(name,None) for name in artifact_roots} | {baseline_key} + seen=set() for item in graph['repositories']: key=(item['repository'],item.get('commit')) + assert key in expected and key not in seen, f'unmapped or duplicate participant: {key}' + seen.add(key) if key in git_roots: assert subprocess.check_output(['git','-C',git_roots[key],'rev-parse','HEAD'],text=True).strip()==item['commit'] elif item['repository'] in artifact_roots: raw=pathlib.Path(artifact_roots[item['repository']]).read_bytes() assert hashlib.sha256(raw).hexdigest()==item['artifact_sha256'] + elif key==baseline_key: + # The actual consumed files are byte-compared to this commit below. + assert subprocess.check_output(['git','rev-parse',item['commit']+'^{commit}'],text=True).strip()==item['commit'] + else: + raise AssertionError(f'unverified participant: {key}') + assert seen==expected, 'participant graph omits acquired inputs' active_base=json.loads(pathlib.Path('research/english-gonol/BASE.json').read_text()) selected=active_base['active_construction']['source_commit'] assert len(selected)==40 and all(c in '0123456789abcdef' for c in selected) @@ -148,6 +160,7 @@ jobs: _inputs/ucns/tests/test_ordinal_affixiation.py \ research/english-gonol/tests/test_ordinal_construct.py \ research/english-gonol/tests/test_ordinal_definitions.py \ + research/english-gonol/tests/test_ordinal_source_inputs.py \ research/english-gonol/tests/test_active_construction.py \ | tee _evidence/tests.txt - name: Build complete source admission then the replacement geometry diff --git a/research/english-gonol/tests/test_ordinal_source_inputs.py b/research/english-gonol/tests/test_ordinal_source_inputs.py new file mode 100644 index 0000000..c3eca76 --- /dev/null +++ b/research/english-gonol/tests/test_ordinal_source_inputs.py @@ -0,0 +1,55 @@ +"""Exercise the workflow's actual participant admission loop, without network.""" +import ast +from pathlib import Path +from types import SimpleNamespace +import pytest +import yaml + +# === CHECKS === +# id: ordinal_workflow_complete_input_mapping +# proves: english_expanded_repertoire +# call: self::test_participant_mapping_refuses_changes +# === END CHECKS === + + +def _program(): + root = Path(__file__).resolve().parents[3] + workflow = yaml.safe_load((root / '.github/workflows/english-ordinal-affixiation.yml').read_text()) + step = next(s for s in workflow['jobs']['full-corpus']['steps'] + if s.get('name') == 'Verify exact participant graph and unchanged source reader') + source = step['run'].split("<<'PY'\n", 1)[1].rsplit('\nPY', 1)[0] + tree = ast.parse(source) + first = next(i for i, n in enumerate(tree.body) if isinstance(n, ast.Assign) + and any(isinstance(t, ast.Name) and t.id == 'baseline_key' for t in n.targets)) + last = next(i for i, n in enumerate(tree.body) if isinstance(n, ast.Assign) + and any(isinstance(t, ast.Name) and t.id == 'active_base' for t in n.targets)) + return compile(ast.Module(body=tree.body[first:last], type_ignores=[]), '', 'exec') + + +def _run(change): + baseline = 'e3eb83764355b4b760a79323cda6a6d75c3a501a' + actual = 'a' * 40 + entries = [{'repository': 'fixture/repo', 'commit': actual}, + {'repository': 'The-Interdependency/stack', 'commit': baseline}] + change(entries) + def git(args, text): + return actual + '\n' if '-C' in args else baseline + '\n' + env = {'git_roots': {('fixture/repo', actual): 'fixture-checkout'}, + 'artifact_roots': {}, 'graph': {'repositories': entries}, + 'subprocess': SimpleNamespace(check_output=git)} + exec(_program(), env) + + +def test_participant_mapping_accepts_complete_inventory(): + _run(lambda rows: None) + + +@pytest.mark.parametrize('change', [ + lambda rows: rows.append({'repository': 'unmapped/repo', 'commit': 'b' * 40}), + lambda rows: rows[0].update(commit='b' * 40), + lambda rows: rows.pop(), + lambda rows: rows.append(dict(rows[0])), +]) +def test_participant_mapping_refuses_changes(change): + with pytest.raises(AssertionError): + _run(change)