Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: tests-and-distribution

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python: ['3.10', '3.14']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
with:
python-version: ${{ matrix.python }}
- run: python -m pip install -e ".[dev,web]"
- run: python -m normal_forms.catalog
- run: python -m pytest tests web/test_api_smoke.py -q

distribution:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
with:
python-version: '3.14'
- run: python -m pip install build
# By default build creates an sdist, then builds the wheel from that sdist.
- run: python -m build
- name: Install and exercise wheel outside the checkout
shell: bash
run: |
python -m venv "$RUNNER_TEMP/wheel-env"
wheel=("$GITHUB_WORKSPACE"/dist/*.whl)
"$RUNNER_TEMP/wheel-env/bin/python" -m pip install "${wheel[0]}[web]"
cd "$RUNNER_TEMP"
"$RUNNER_TEMP/wheel-env/bin/python" -I "$GITHUB_WORKSPACE/scripts/installed_smoke.py"
"$RUNNER_TEMP/wheel-env/bin/python" -I -m normal_forms.catalog
13 changes: 12 additions & 1 deletion IMPORT_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ This guide provides external software engineers, database architects, and distri

### 2.1 Clone and Install in Development Mode

The core evaluation engines depend on the Python Standard Library and `pyyaml`. Optional web dependencies (`fastapi`, `uvicorn`) are provided for the companion workbench interface:
The core evaluation engines depend on the Python Standard Library, `pyyaml`, and
Pydantic 2. Optional web dependencies are provided through the `web` extra.
Wheels include the contract resources and Studio templates/static assets.

```bash
# 1. Clone the repository
Expand Down Expand Up @@ -58,6 +60,11 @@ pytest tests/ -v

## 3. Four Concrete Integration Blueprints

For the bounded streaming profile and Python/SQLite input semantics, read
[Executable scope and regression evidence](docs/CORRECTNESS_SCOPE.md).
For source-distribution and isolated wheel checks, read
[Distribution verification](docs/DISTRIBUTION.md).

Below are four complete, syntax-checked, runnable Python blueprints demonstrating how to integrate `simplex-normal-forms` into production application architectures.

---
Expand Down Expand Up @@ -406,6 +413,10 @@ if __name__ == "__main__":

This blueprint demonstrates wrapping AI retrieval-augmented generation (RAG) context compression and Model Context Protocol (MCP) tool pipelines with `@coda_mur_projection`. It enforces that prompt context truncation and attribute erasure emit a cryptographic SHA-256 Merkle `LossLedger`, verifies exact additive token conservation ($\text{retained\_tokens} + \text{truncated\_tokens} == \text{source\_tokens}$), and asserts the epistemic authority firewall (`certified_implies_authorized: false`).

Here, tokens are deterministic whitespace-separated units from
`tokenize_whitespace`, not provider/model tokenizer counts. The budget alone
does not establish that a prompt fits a particular model's context window.

```python
"""Blueprint 4: AI Agent LossLedger in LangChain / LlamaIndex / MCP Workflows."""
from typing import Any, List, Mapping
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ simplex-normal-forms/
│ └── research_forum/ # 6-document Research Forum & Commercial Strategy Dossier (SimpleCache vs IVM)
├── images/ # 112 per-contract visual SVG diagrams + architectural overview SVGs
├── wiki/ # Complete mirror of the GitHub Wiki (one markdown page per normal form)
├── tests/ # Automated verification suite (136 passing unit, property, and API tests)
├── tests/ # Unit, replay, scalar-equivalence, and API verification
├── pyproject.toml # Standard PEP 517/518 build definition for zero-friction pip install
├── render.yaml # Infrastructure-as-code blueprint for smplxnf.anomalon.com
├── IMPORT_GUIDE.md # Developer adoption guide with 4 runnable integration blueprints
Expand Down Expand Up @@ -156,14 +156,21 @@ Explore the **[GitHub Wiki](https://github.com/dbccpage/simplex-normal-forms/wik
- **[Relational Geometrodynamics & Physics Substrate](https://github.com/dbccpage/simplex-normal-forms/wiki/Relational-Geometrodynamics-and-Physics-Substrate)** ([local](wiki/Relational-Geometrodynamics-and-Physics-Substrate.md))
- **[MVP Selection & Architecture Specification](docs/MVP_SELECTION.md)** (Render deployment and workbench design)
- **[External Developer Adoption & System Import Guide](IMPORT_GUIDE.md)** (4 runnable production integration blueprints)
- **[Executable Scope & Regression Evidence](docs/CORRECTNESS_SCOPE.md)** (streaming profile and Python/SQLite semantics)
- **[Distribution Verification](docs/DISTRIBUTION.md)** (bundled resources, isolated installation, and CI)
- **[Master Plan of Plans (NF-IR Architecture)](docs/plans/plan_of_plans.md)** ([Plan 1: Micro-Kernel](docs/plans/plan_01_wdp_obnf_micro_kernel.md) • [Plan 2: Subsumption & DCE](docs/plans/plan_02_subsumption_lattice.md) • [Plan 3: Operadic Wiring](docs/plans/plan_03_operadic_wiring_compiler.md) • [Plan 4: Multi-Target Lowering](docs/plans/plan_04_multi_target_lowering.md))
- **[SimpleCache Research Forum & Commercial Strategy Dossier](docs/research_forum/README.md)** ([Executive Whitepaper](docs/research_forum/01_executive_whitepaper.md) • [Competitive Analysis](docs/research_forum/02_competitive_analysis.md) • [5 Commercial Upgrades](docs/research_forum/03_commercial_upgrades.md) • [Cross-Program Foundations](docs/research_forum/04_cross_program_foundations.md) • [Forum Proceedings](docs/research_forum/05_research_forum_proceedings.md))

---

## 6. Complete Normal Form Contract Register (112 Contracts)

112 contract files (`index.yaml` lists 25 active and 86 draft contracts). Every contract includes a dedicated Wiki page and visual SVG diagram:
112 contract files. The index lists 25 active and 87 draft entries, with
`nf.cohomology.acnf` also listed as deprecated. These lifecycle labels are
distinct from executable verification: contract metadata currently labels 35
executable, 75 verification-absent, and two unspecified. Catalog validation
checks document structure. Every contract includes a dedicated Wiki page and
visual SVG diagram.

| Contract YAML | Short Name | Full Name | Family | Status | Theory | Verification | Wiki & SVG Diagram |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
Expand Down
1 change: 1 addition & 0 deletions contracts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Contract resources, installed as normal_forms.resources without moving sources."""
38 changes: 38 additions & 0 deletions docs/DISTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Distribution verification

`contracts/` remains the source owner for YAML, SQL, and JSON resources. The
package-directory mapping installs these files under `normal_forms/resources/`.
The library resolves this installed directory first and uses the checkout's
`contracts/` directory during source development. `web` ships templates and
static assets; install the `web` extra to run Studio. Changes to the package
list or runtime resource extensions must also update `pyproject.toml`.

Build a source distribution and then a wheel from that source distribution:

```sh
python -m pip install build
python -m build
```

Install the generated wheel with its web extra into a new virtual environment.
From a directory outside this checkout, run that environment's interpreter:

```sh
python -I /absolute/path/to/simplex-normal-forms/scripts/installed_smoke.py
python -I -m normal_forms.catalog
```

The smoke check requires a virtual environment and asserts that the library,
web app, and contract resources resolve inside its installed package. It
validates all 112 contracts, loads JSON fixtures, installs the SQL schema, serves
the HTML/JS/CSS assets, and exercises the four API workbenches. This prevents a
checkout or editable install from concealing missing distribution files.

`.github/workflows/ci.yml` runs the suite and catalog on Linux and Windows with
Python 3.10 and 3.14, and runs the isolated distribution check on Linux. The
workflow has read-only repository permissions and contains no deployment or
publication step. Build checks establish installation behavior; they do not
establish live service availability or general mathematical correctness.

The original NF-IR plan documents record historical design intentions. Current
implementation boundaries are documented in [CORRECTNESS_SCOPE.md](CORRECTNESS_SCOPE.md).
6 changes: 4 additions & 2 deletions normal_forms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

Executable validators, schema inventory, evaluators, and examples live here.
Their YAML contracts, SQL schemas, and JSON example data remain in
`../yaml/nf`; `contract_paths.py` declares that resource home.
`../contracts` in the checkout and ship as `normal_forms.resources` in a wheel.
`contract_paths.py` selects that resource home without depending on the current
working directory.

The four descriptive `*_example.py` modules are executable examples. Exact
mathematical predicates live in the canonical `domain.normal_forms` modules;
mathematical predicates live in the `normal_forms.domain` modules;
infrastructure modules provide only filesystem, SQLite, and YAML adapters.

AuthorityEffect: None.
7 changes: 6 additions & 1 deletion normal_forms/contract_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@

from pathlib import Path

NORMAL_FORMS_DIR = Path(__file__).resolve().parent.parent / "contracts"
_PACKAGE_DIR = Path(__file__).resolve().parent
_BUNDLED_CONTRACTS = _PACKAGE_DIR / "resources"
NORMAL_FORMS_DIR = (
_BUNDLED_CONTRACTS if _BUNDLED_CONTRACTS.is_dir()
else _PACKAGE_DIR.parent / "contracts"
)
CONTRACTS_DIR = NORMAL_FORMS_DIR
INDEX_PATH = CONTRACTS_DIR / "index.yaml"
_GOLDEN = NORMAL_FORMS_DIR / "_golden_nfs"
Expand Down
32 changes: 22 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools>=61.0"]
requires = ["setuptools>=77.0"]
build-backend = "setuptools.build_meta"

[project]
Expand All @@ -8,15 +8,14 @@ version = "0.1.0"
description = "Boundary-Certified Data Architecture, Relational Normalization, Cochain Retraction & NF-IR Compiler"
readme = "README.md"
requires-python = ">=3.10"
license = { text = "MIT" }
license = "MIT"
authors = [
{ name = "Simplex Normal Forms Authors" }
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -28,17 +27,15 @@ classifiers = [
]
dependencies = [
"pyyaml>=6.0",
"fastapi>=0.100.0",
"uvicorn>=0.23.0",
"jinja2>=3.1.2",
"httpx>=0.24.0",
"pydantic>=2.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"hypothesis>=6.0.0",
"httpx>=0.24.0",
"build>=1.2",
]
web = [
"fastapi>=0.100.0",
Expand All @@ -47,6 +44,21 @@ web = [
"httpx>=0.24.0",
]

[tool.setuptools.packages.find]
where = ["."]
include = ["normal_forms*"]
[tool.setuptools]
packages = [
"normal_forms", "normal_forms.bqnf", "normal_forms.domain",
"normal_forms.rop", "normal_forms.tower", "normal_forms._golden_nfs",
"normal_forms.resources", "web",
]

# Keep contracts/ as the source owner; install its bytes inside the library.
[tool.setuptools.package-dir]
"normal_forms.resources" = "contracts"

[tool.setuptools.package-data]
"normal_forms.resources" = [
"*.yaml", "*.sql", "*.json", "*.md",
"_golden_nfs/*.yaml", "_golden_nfs/*.sql", "bqnf/*.yaml", "data/*.json",
]
"normal_forms.domain" = ["*.yaml"]
web = ["templates/*.html", "static/*.js", "static/*.css"]
57 changes: 57 additions & 0 deletions scripts/installed_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Run with a wheel-installed virtualenv Python using -I, outside the checkout."""

from pathlib import Path
import json
import sqlite3
import sys

from fastapi.testclient import TestClient

import normal_forms
import web
from normal_forms.catalog import check_catalog, _contract_paths
from normal_forms.contract_paths import CONTRACTS_DIR
from normal_forms.schema_sql import install_schema
from web.app import app, PRESETS, BQNF_PRESETS, COMPILER_PRESETS, AI_PRESETS


def main():
assert sys.prefix != sys.base_prefix, "Use a separate virtualenv to verify the installed wheel."
for module in (normal_forms, web):
assert Path(module.__file__).resolve().is_relative_to(Path(sys.prefix).resolve()), module.__file__
assert CONTRACTS_DIR.is_relative_to(Path(normal_forms.__file__).resolve().parent)
assert len(_contract_paths(CONTRACTS_DIR)) == 112
assert check_catalog() == []
for fixture in (CONTRACTS_DIR / "data").glob("*.json"):
json.loads(fixture.read_text(encoding="utf-8"))
assert (CONTRACTS_DIR / "data" / "cdc_events.json").is_file()
with sqlite3.connect(":memory:") as conn:
install_schema(conn)
assert conn.execute("SELECT count(*) FROM sqlite_master WHERE type='table'").fetchone()[0] > 0
with TestClient(app) as client:
for path in ("/healthz", "/", "/static/app.js", "/static/style.css"):
assert client.get(path).status_code == 200, path
for endpoint, preset in (
("relational/normalize", PRESETS["ecommerce"]),
("bqnf/simulate", BQNF_PRESETS["financial_ledger"]),
("compiler/lower", COMPILER_PRESETS["employee_bcnf"]),
("ai/lossledger", AI_PRESETS["rag_research_context"]),
):
result = client.post("/api/" + endpoint, json=preset)
assert result.status_code == 200, result.text
data = result.json()
if endpoint == "relational/normalize":
assert data["chase"]["is_implied"]
elif endpoint == "bqnf/simulate":
assert data["final_cache"]["North"]["total_sales"] == 280
assert data["final_cache"]["North"]["sale_count"] == 4
elif endpoint == "compiler/lower":
assert data["sqlite_verification"]["verified"]
else:
assert data["token_accounting"]["token_conservation_commutes"]
assert data["loss_ledger_integrity_verified"]
print("Installed wheel: 112 contracts, fixtures, SQL schema, assets, and four API workbenches passed.")


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions web/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Optional Simplex Normal Forms Studio web application."""
Loading