Metadata-Version: 2.4
Name: spine-pkg
Version: 0.3.0
Summary: Turn any repository into a queryable Program Knowledge Graph — deterministic, provenance-carrying code facts.
Project-URL: Homepage, https://github.com/synaptixs/spine-pkg
Project-URL: Repository, https://github.com/synaptixs/spine-pkg
Project-URL: Issues, https://github.com/synaptixs/spine-pkg/issues
Author-email: Synaptixs <noreply@synaptixs.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: ast,code-analysis,knowledge-graph,provenance,rdf,static-analysis
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Documentation
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.12
Requires-Dist: pyshacl>=0.26
Requires-Dist: rdflib>=7.0
Requires-Dist: typer>=0.12
Provides-Extra: all
Requires-Dist: openpyxl>=3.1; extra == 'all'
Requires-Dist: pypdf>=4; extra == 'all'
Requires-Dist: python-docx>=1.1; extra == 'all'
Requires-Dist: sqlglot>=25; extra == 'all'
Requires-Dist: tree-sitter-c-sharp>=0.21; extra == 'all'
Requires-Dist: tree-sitter-c>=0.21; extra == 'all'
Requires-Dist: tree-sitter-cpp>=0.21; extra == 'all'
Requires-Dist: tree-sitter-go>=0.21; extra == 'all'
Requires-Dist: tree-sitter-java>=0.21; extra == 'all'
Requires-Dist: tree-sitter-typescript>=0.21; extra == 'all'
Requires-Dist: tree-sitter>=0.21; extra == 'all'
Provides-Extra: asr
Requires-Dist: openai-whisper>=20231117; extra == 'asr'
Provides-Extra: asr-api
Requires-Dist: httpx>=0.27; extra == 'asr-api'
Provides-Extra: c
Requires-Dist: tree-sitter-c>=0.21; extra == 'c'
Requires-Dist: tree-sitter>=0.21; extra == 'c'
Provides-Extra: cpp
Requires-Dist: tree-sitter-cpp>=0.21; extra == 'cpp'
Requires-Dist: tree-sitter>=0.21; extra == 'cpp'
Provides-Extra: csharp
Requires-Dist: tree-sitter-c-sharp>=0.21; extra == 'csharp'
Requires-Dist: tree-sitter>=0.21; extra == 'csharp'
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: openpyxl>=3.1; extra == 'dev'
Requires-Dist: pypdf>=4; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: python-docx>=1.1; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: sqlglot>=25; extra == 'dev'
Provides-Extra: docs
Requires-Dist: pypdf>=4; extra == 'docs'
Provides-Extra: go
Requires-Dist: tree-sitter-go>=0.21; extra == 'go'
Requires-Dist: tree-sitter>=0.21; extra == 'go'
Provides-Extra: java
Requires-Dist: tree-sitter-java>=0.21; extra == 'java'
Requires-Dist: tree-sitter>=0.21; extra == 'java'
Provides-Extra: media
Requires-Dist: pillow>=10; extra == 'media'
Requires-Dist: pytesseract>=0.3.10; extra == 'media'
Provides-Extra: office
Requires-Dist: openpyxl>=3.1; extra == 'office'
Requires-Dist: python-docx>=1.1; extra == 'office'
Provides-Extra: sql
Requires-Dist: sqlglot>=25; extra == 'sql'
Provides-Extra: typescript
Requires-Dist: tree-sitter-typescript>=0.21; extra == 'typescript'
Requires-Dist: tree-sitter>=0.21; extra == 'typescript'
Description-Content-Type: text/markdown

# Spine

Turn any repository into a queryable **Program Knowledge Graph** — symbols, calls,
imports, database schema, and documentation, as universal facts that carry provenance
back to the line they came from.

Everything here is **deterministic and model-free** — extraction *and* the synthesis
on top of it. The same commit in always yields the same bytes out, so the output is
diffable, cacheable, and safe to gate CI on.

```bash
pip install 'spine-pkg[all]'
spine understand .        # writes episteme/ — a code-true knowledge base
spine state .             # what this repo is today, and how healthy
spine extract . -q handleRequest   # who calls it, and what it touches
```

Because `understand` is deterministic, `spine understand --check` belongs in CI: it
re-renders and diffs against the committed `episteme`, exiting non-zero when the
docs and the code have drifted apart. That makes the knowledge base *provably*
current rather than hopefully current.

## Commands

| | |
|---|---|
| `spine extract [path]` | Scan a repo, print a summary. `--query <symbol>` shows callers and blast radius; `--json` dumps facts. |
| `spine verify [path]` | Check graph invariants — dangling edges, unresolvable provenance, unjoined imports. Exits non-zero on error, so it can stand guard in CI. |
| `spine export [path]` | Export the whole graph as `sqlite`, `graphml`, `dot`, or `json`. Writes `spine-facts.<ext>` unless you pass `--out`. Never truncated. |
| `spine understand [path]` | Build a committed `episteme` knowledge base — architecture, domain model, tech context, conventions, glossary, per-module pages. `--check` verifies it still matches the code. |
| `spine state [path]` | A snapshot of what the repo is today and how healthy it looks. `--lens developer\|stakeholder`; `--out report.html` for a self-contained shareable report. |
| `spine profile [path]` | Languages, framework, database, test runner, task type. |
| `spine docs [path] -d FILE` | Reconcile documentation claims against the code graph and report drift. |
| `spine languages` | Show which language front-ends are active in this install. |
| `spine media extract PATHS` | OCR images and transcribe audio/video into reviewable artifacts. Opt-in; see below. |

## Languages

Python works out of the box with no extra dependencies. Every other front-end
lazy-imports its parser, so the base install stays small and you pay only for what
you use:

```bash
pip install 'spine-pkg[java]'        # or typescript, csharp, c, cpp, go, sql
pip install 'spine-pkg[all]'         # every front-end at once
```

If a language's extra isn't installed, its files are invisible to the graph rather
than an error — so `spine extract` counts them and tells you what to install:

```
Scanned . — 0 grounded nodes, 0 external, 0 edges.

  ! 103 Go file(s) found but NOT extracted — install the front-end:  pip install 'spine-pkg[go]'
```

`spine languages` shows the same thing ahead of time. Both warnings go to stderr, so
`extract --json` and `export` stay pipe-safe.

## Documents and media

Markdown, reStructuredText, plain text, and HTML parse with the standard library.
PDF needs `[docs]`; Word and Excel need `[office]`.

`spine media extract` is deliberately separate from the graph build. It MAY run a
model and be slow, so it is explicit and opt-in: it creates a `.spine-media` directory
on first run, writes reviewable artifacts there for you to commit, and the
deterministic extractor only ever reads those. Image OCR (`[media]`, plus a system
`tesseract` binary) and `--asr local` (`[asr]`) run entirely on your machine.
`--asr api` uploads audio and video off-machine and refuses to run without an
explicit `--allow-remote`.

## Caching

Facts are cached per commit under `~/.cache/spine/`, and the cache is trusted only on
a clean working tree — a dirty tree always re-extracts, because a stale graph is
worse than a slow one.

## Design notes

- **The graph is the source of truth.** Consumers render facts; they never re-derive
  them from paths or filenames. A new fact means extending `facts.py` and the
  front-ends, not the renderer.
- **Bounded output is honest output.** Aggregations cap their results and record what
  was elided. Exports are the exception — they are always complete, because the point
  of handing the graph to another tool is that its filtering is better than ours.
- **Local paths only.** `spine` scans a checkout on disk and never clones for you.
- **Calls resolve where the source states a type.** A method called on a variable
  binds when that variable has a parameter or assignment annotation, or comes from a
  constructor for a class in the same module. A union of two real types, a rebound
  variable, or a `with` target resolves to nothing — a fabricated edge is worse than
  a missing one. Annotating a local is what makes its calls visible, which is a good
  reason to annotate it.

## License

MIT
