Metadata-Version: 2.4
Name: curvature
Version: 0.4.3
Summary: A web framework for code that agents maintain. The right path is free fall.
Keywords: web,framework,agents,progressive-enhancement,server-rendered,htmx-alternative
Author: Robert Sharp
Author-email: Robert Sharp <webmaster@sharpdesigndigital.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Dist: pydantic>=2.11
Requires-Dist: starlette>=0.47
Requires-Dist: pyjwt[crypto]>=2.10 ; extra == 'auth'
Requires-Dist: fastapi>=0.115 ; extra == 'fastapi'
Requires-Dist: python-multipart>=0.0.20 ; extra == 'fastapi'
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/siliconsociety/Curvature
Project-URL: Repository, https://github.com/siliconsociety/Curvature
Project-URL: Issues, https://github.com/siliconsociety/Curvature/issues
Provides-Extra: auth
Provides-Extra: fastapi
Description-Content-Type: text/markdown

# Curvature

*The right path is free fall.*

[![gate](https://github.com/siliconsociety/Curvature/actions/workflows/gate.yml/badge.svg)](https://github.com/siliconsociety/Curvature/actions/workflows/gate.yml)
[![PyPI](https://img.shields.io/pypi/v/curvature)](https://pypi.org/project/curvature/)
[![Python](https://img.shields.io/pypi/pyversions/curvature)](https://pypi.org/project/curvature/)
[![Coverage floor](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsiliconsociety%2FCurvature%2Fmain%2Ffloor-badge.json)](https://github.com/siliconsociety/Curvature/blob/main/ratchet.toml)
[![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

## Spiral is project spacetime

Spiral is on by default. Every directory is a local body: its substantial
source files occupy surface, and the surface-to-volume law determines how
much room a healthy leaf has to grow.

For a sphere of radius \(r\),

$$
A(r)=4\pi r^2,\qquad
V(r)=\frac{4}{3}\pi r^3,\qquad
\frac{V(r)}{A(r)}=\frac{r}{3}.
$$

Curvature normalizes each direct source file \(f\) by its language's base
ceiling \(B_{\tau(f)}\), then measures the occupied surface of directory
\(D\):

$$
m_f=\frac{\operatorname{lines}(f)}{B_{\tau(f)}},\qquad
A_D=\sum_{f\in\operatorname{direct}(D)}\min(1,m_f),\qquad
R_D=\max(1,\sqrt{A_D}).
$$

The effective ceiling is the ratcheted base multiplied by that local radius:

$$
C_f=\operatorname{round}(B_fR_D).
$$

A lone Python leaf therefore begins at 300 lines and cannot buy room by
becoming oversized. Two substantial neighboring leaves have radius
\(\sqrt2\) and a 424-line Python ceiling; three have 520, five have 671, and
eight have 849. Child directories form their own bodies, so distant project
mass cannot inflate a local file. At thirteen meaningful neighbors the
twelve-neighbor coordination bound fires and the directory must branch. The
gate also prunes hollow branches that retain only cache archaeology or missing
tracked leaves. The derivation and adoption controls live in
[The Spiral law](docs/SPIRAL.md).

A web framework for code that agents maintain. Live, dynamic web apps
in pure Python — single-page feel, pages that update themselves in
real time, zero JavaScript app code — and a gate that makes the
maintainable path the only path that builds. (Not a static-site
generator: state lives on the server, and open pages stay current over
a live stream.)

Curvature's design center is the maintainer nobody watches: the coding
agent in its forty-third session, at 2 a.m., doing whatever the shape of
the code suggests. Frameworks built for humans enforce their discipline
through culture. Curvature's discipline is machine-checked — every
invariant in [SPEC.md](https://github.com/siliconsociety/Curvature/blob/main/SPEC.md) names the check that enforces it, and
violations are reported by `curvature check` as **anomalies** — regions where the geometry failed to steer.
The canonical documentation is [AGENTS.md](https://github.com/siliconsociety/Curvature/blob/main/AGENTS.md); this README is
the courtesy translation. The argument for all of it is the
[MANIFESTO](https://github.com/siliconsociety/Curvature/blob/main/MANIFESTO.md).

## The shape of it

```python
from curvature import Element, Props, redirect, respond
from curvature import html as h


class LapProps(Props):
    title: str
    done: bool


def lap(props: LapProps) -> Element:
    return h.li(props.title, class_="lap done" if props.done else "lap", id="lap")
```

- **Components** are functions of frozen, closed pydantic props. The UI
  is just Python: typed by pyright, measured by coverage, tested by
  pytest without a browser in sight.
- **The app works with JavaScript off.** Reads render full pages; writes
  are POST → redirect → GET through real forms. Your test suite drives
  it with httpx — which executes no JS — so the degraded path is the
  tested path, permanently.
- **Pages keep themselves current.** Live (SSE) pushes updates into
  every open browser by swapping server-rendered fragments declared by the
  application, with zero app JavaScript.
- **The client layer is closed and chartered.** `curvature.js` remains the
  stable, sole consumer-facing include. It boosts working links and GET forms
  into fragment swaps; its package-owned `live.js` branch manages only
  server-declared EventSource streams. Mutating forms stay native, native
  submitter overrides remain native semantics, and enhanced submissions expose
  `aria-busy` and `data-curvature-pending` while intent is in flight. Same-page
  fragment links and their history stay browser-native; cross-page boosts
  preserve and scroll to their fragment after swapping. Applications write no
  JavaScript.
- **The ratchet only tightens; healthy trees Spiral.** Base file ceilings
  fall, the coverage floor rises, and `curvature ratchet` is the only hand on
  the mechanism. Local occupied surface lets related leaves grow by radius,
  while a twelve-neighbor coordination bound keeps branches navigable. The
  10,000-line dumping ground and the 160-file trunk remain anomalies.

Drafting belongs to native controls: text, selection, and open details stay in
the browser while the operator edits. Server-derived or persisted state earns
a round trip and an identified fragment replacement. Pending attributes bridge
those two moments without pretending the server has already accepted anything.

## Start from nothing

One prerequisite, one line ([uv](https://docs.astral.sh/uv/)):

```bash
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

Then:

```bash
uvx curvature new app pitstop     # no venv, no Python even — uv brings it
cd pitstop
./gate.sh                      # green before you write a line
./run.sh                       # http://127.0.0.1:8000
```

Only have pip? `pip install curvature && python -m curvature new app pitstop`
— the `python -m` form dodges PATH entirely; the poured README carries
the rest of the old ritual. 

Onboarding an agent takes zero steps: the scaffold poured AGENTS.md,
the gate, and one example component as the pattern. Point your agent at
the directory and ask for a feature — the repo is the prompt.

## Develop the framework

The repository is the framework itself. Clone it, sync the locked development
environment, and run the same gate CI runs:

```bash
git clone https://github.com/siliconsociety/Curvature && cd Curvature
uv sync && ./gate.sh
```

## Updating an app

Curvature has two ownership classes. The installed package owns the runtime,
including `curvature.js`, `live.js`, response helpers, and the gate. Update that
runtime deliberately, review the lockfile, and run the app's gate:

```bash
uv lock --upgrade-package curvature
uv sync
./gate.sh
```

The app owns everything the scaffold or a satellite pour copied into its
repository. Package upgrades never overwrite those files. When a release
requires an app-source migration, its upgrade note names the files and the
owner applies the diff like any other code change. See
[docs/UPGRADING.md](docs/UPGRADING.md) for the complete contract and
release-specific notes.

## Status

Alpha. The contract, runtime, gate, browser-level boost tests, and a fresh-pour
Auth integration suite are real and exercised by the repository's test and
package proofs. Production readiness is earned by the gate and deployment
checks, not asserted by the version label. The spec is versioned and arguable;
argue by issue.

MIT.
