Metadata-Version: 2.5
Name: horsegraph
Version: 0.2.0a1
Summary: Plan node graphs read through Tiny Horse canonical storage and visualized as ClaySpace worlds.
Author: Magus
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: clayspace,dependency-graph,git,planning,tinyhorse
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.10
Requires-Dist: clayspace<0.2,>=0.1.3
Requires-Dist: tinyhorse>=0.2.4
Provides-Extra: gdrive
Requires-Dist: tinyhorse[gdrive]>=0.2.4; extra == 'gdrive'
Provides-Extra: test
Requires-Dist: pytest>=7; extra == 'test'
Description-Content-Type: text/markdown

# Horsegraph 0.2.0a1 — alpha

See [operating runbook](docs/OPERATING.md), [migration guide](docs/MIGRATION.md), and [release notes](docs/RELEASE-NOTES.md). Run `horsegraph demo --case maintenance --out demo-proof` in an isolated environment.

# horsegraph

Plan node graphs (`NODE-GRAPH.json`) read through **Tiny Horse** canonical storage and visualized as **ClaySpace** worlds.

- **Tiny Horse** is the source of truth. horsegraph reads the graph from a bound checkout (and can run `tinyhorse doctor` on it), or straight from the canonical bundle in storage (`file:` or `gdrive://`), or from a Drive project by name. When it reads from storage it fetches and verifies the bundle and reads the graph at canonical HEAD, so the view shows what was parked, not unparked local edits.
- **ClaySpace** draws it. Every node is a ClaySpace Cell, every dependency is a Cell with an arrowhead, and the whole graph is a valid `clayspace.world.snapshot`. The HTML is ClaySpace's own self-contained orbit preview, plus a label, hover-detail and legend overlay.

```bash
pip install horsegraph            # add [gdrive] for Drive storage / --project
```

## Use

```bash
# from a Tiny Horse-bound checkout (default graph path docs/runner-gateway/NODE-GRAPH.json)
horsegraph render --checkout . --doctor --out plan.html --world plan.world.json

# straight from canonical storage, no checkout needed
horsegraph render --storage gdrive://FOLDER_ID/Demo.bundle
horsegraph render --project "Demo"            # resolved like `tinyhorse claim`

# plan views
horsegraph next  --checkout .                 # "Needs you now" / "Agent candidates next"
horsegraph path  --checkout .                 # longest dependency chain to the goal node
horsegraph check --checkout .                 # validate; exit 1 on warnings (e.g. done before its deps)

# any JSON file, no Tiny Horse
horsegraph render --file examples/NODE-GRAPH.json
```

`--graph` changes the path inside the repo; `--ref` reads a tag or commit from storage instead of HEAD.

The ClaySpace world it writes with `--world` opens with the usual tools (`clayspace world inspect`, `clayspace world preview`).

## Reading the 3D view

| Shape | Meaning |
|---|---|
| low green slab | done |
| blue block | open, agent node |
| tall amber tower with a flagpole | open owner action, needs you |
| cyan | on the longest dependency chain to the goal |
| pink + sphere | goal node |
| grey, thin | parked (`later`, `after-proof`) |

Columns run left to right by dependency depth, and rows group by track. Drag to orbit, scroll to zoom, and hover a label for the node's title, deps and the contract items it advances.

## Graph format

```json
{
  "title": "…", "goal": "G-RELEASE",
  "tracks": {"CLI": "Command Line Interface"},
  "nodes": [
    {"id": "CLI-2", "title": "…", "owner": "agent", "status": "open",
     "deps": ["CLI-1", "CORE-2"], "track": "CLI", "closes": ["C2"]}
  ]
}
```

`owner` is `agent` or `owner`. `status` is `done`, `open`, `later`, `after-proof` or `available-verified`. Extra fields are kept. Cycles, unknown deps and duplicate ids are rejected.

## Python

```python
from horsegraph import from_storage, render
graph, prov = from_storage("file:/srv/git/demo.bundle")
print(graph.critical_path(), [n.id for n in graph.ready("owner")])
render(graph, "plan.html", provenance=prov.to_dict(), subtitle=prov.summary())
```

## Release

```bash
python -m build && twine upload dist/*
```
