lingot 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ matrix:
7
+ os: [ubuntu-latest, macos-latest, windows-latest]
8
+ python-version: ["3.10", "3.11", "3.12"]
9
+ fail-fast: false
10
+ runs-on: ${{ matrix.os }}
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: ${{ matrix.python-version }}
16
+ - run: pip install -e ".[dev]"
17
+ - run: pytest -q
18
+ - run: ruff check src/
@@ -0,0 +1,36 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ tags: ["v*"]
5
+
6
+ permissions:
7
+ contents: read
8
+ id-token: write
9
+
10
+ jobs:
11
+ quality:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install -e ".[dev]"
19
+ - run: pytest -q
20
+ - run: ruff check src/
21
+ - name: Smoke import
22
+ run: python -c "import lingot; print(lingot.__version__)"
23
+
24
+ publish:
25
+ needs: quality
26
+ runs-on: ubuntu-latest
27
+ environment: release
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.12"
33
+ - run: pip install build twine
34
+ - run: python -m build
35
+ - run: twine check dist/*
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,18 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+
12
+ # Node / TS
13
+ node_modules/
14
+ ts/dist/
15
+
16
+ # OS / editor
17
+ .DS_Store
18
+ Thumbs.db
lingot-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: lingot
3
+ Version: 0.0.1
4
+ Summary: Umbrella orchestrator for the Autarkis spatial stack — the mint for embodied-AI ground truth.
5
+ Project-URL: Homepage, https://github.com/Autarkis/lingot
6
+ Project-URL: Repository, https://github.com/Autarkis/lingot
7
+ Project-URL: Issues, https://github.com/Autarkis/lingot/issues
8
+ Author-email: Boris Blosse <borisblosse@gmail.com>
9
+ Keywords: embodied-ai,ground-truth,robotics,simulation,spatial,synthetic-data
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: Other/Proprietary License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.10
20
+ Provides-Extra: dev
21
+ Requires-Dist: build; extra == 'dev'
22
+ Requires-Dist: pyright>=1.1; extra == 'dev'
23
+ Requires-Dist: pytest>=7.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.1; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Lingot
28
+
29
+ **The mint for the reserve currency of embodied AI.** Lingot is the umbrella
30
+ orchestrator of the Autarkis spatial stack — the thin layer that depends on the
31
+ worker services and conducts them through one pipeline:
32
+
33
+ ```
34
+ spec -> cadastre (registry + solve) -> chitin (physics .phys) -> oneiros (render) -> StagedScene
35
+ ```
36
+
37
+ Lingot is intentionally thin. It owns the *order* and the *data hand-off*; the
38
+ work lives in the workers, each an independently published package.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ pip install lingot # Python orchestrator + CLI (PyPI: lingot)
44
+ npm install @autarkis/lingot # JS orchestrator / client (npm bare `lingot` is taken -> scoped)
45
+ ```
46
+
47
+ > The Rust force-directed solver is **not** vendored here — it ships as its own
48
+ > worker package and is pulled in as a dependency. Lingot orchestrates; it does
49
+ > not implement.
50
+
51
+ ## Local development
52
+
53
+ The worker repos are siblings (`../cadastre`, `../chitin`, `../oneiros`). Wire
54
+ them in editable mode, then run the pipeline on a spec:
55
+
56
+ ```bash
57
+ just dev-install
58
+ just run path/to/spec.json
59
+ ```
60
+
61
+ Every pipeline stage delegates to a worker adapter in `src/lingot/workers.py`.
62
+ Stages with no wired worker raise a clear error naming what to connect — the
63
+ skeleton runs end-to-end the moment the seams are filled.
64
+
65
+ ## Layout
66
+
67
+ ```
68
+ lingot/
69
+ |- src/lingot/ # Python orchestrator
70
+ | |- pipeline.py # stage order + data hand-off
71
+ | |- workers.py # one adapter seam per worker service
72
+ | \- cli.py # `lingot run spec.json`
73
+ |- ts/ # @autarkis/lingot — JS orchestrator / client
74
+ \- justfile # dev / test / build across py + ts
75
+ ```
76
+
77
+ See [`../LINGOT.md`](../LINGOT.md) for the full thesis.
lingot-0.0.1/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Lingot
2
+
3
+ **The mint for the reserve currency of embodied AI.** Lingot is the umbrella
4
+ orchestrator of the Autarkis spatial stack — the thin layer that depends on the
5
+ worker services and conducts them through one pipeline:
6
+
7
+ ```
8
+ spec -> cadastre (registry + solve) -> chitin (physics .phys) -> oneiros (render) -> StagedScene
9
+ ```
10
+
11
+ Lingot is intentionally thin. It owns the *order* and the *data hand-off*; the
12
+ work lives in the workers, each an independently published package.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install lingot # Python orchestrator + CLI (PyPI: lingot)
18
+ npm install @autarkis/lingot # JS orchestrator / client (npm bare `lingot` is taken -> scoped)
19
+ ```
20
+
21
+ > The Rust force-directed solver is **not** vendored here — it ships as its own
22
+ > worker package and is pulled in as a dependency. Lingot orchestrates; it does
23
+ > not implement.
24
+
25
+ ## Local development
26
+
27
+ The worker repos are siblings (`../cadastre`, `../chitin`, `../oneiros`). Wire
28
+ them in editable mode, then run the pipeline on a spec:
29
+
30
+ ```bash
31
+ just dev-install
32
+ just run path/to/spec.json
33
+ ```
34
+
35
+ Every pipeline stage delegates to a worker adapter in `src/lingot/workers.py`.
36
+ Stages with no wired worker raise a clear error naming what to connect — the
37
+ skeleton runs end-to-end the moment the seams are filled.
38
+
39
+ ## Layout
40
+
41
+ ```
42
+ lingot/
43
+ |- src/lingot/ # Python orchestrator
44
+ | |- pipeline.py # stage order + data hand-off
45
+ | |- workers.py # one adapter seam per worker service
46
+ | \- cli.py # `lingot run spec.json`
47
+ |- ts/ # @autarkis/lingot — JS orchestrator / client
48
+ \- justfile # dev / test / build across py + ts
49
+ ```
50
+
51
+ See [`../LINGOT.md`](../LINGOT.md) for the full thesis.
lingot-0.0.1/justfile ADDED
@@ -0,0 +1,25 @@
1
+ # Lingot — umbrella orchestrator. Conducts the worker services (cadastre, chitin,
2
+ # oneiros, solver) into a labeled StagedScene. See ../LINGOT.md for the thesis.
3
+
4
+ # Editable-install Lingot + the sibling worker repos for local dev.
5
+ dev-install:
6
+ pip install -e ".[dev]"
7
+ pip install -e ../cadastre || echo "skip cadastre (not pip-installable yet)"
8
+ pip install -e ../chitin || echo "skip chitin"
9
+ pip install -e ../oneiros || echo "skip oneiros"
10
+
11
+ # Run the Python test suite.
12
+ test:
13
+ pytest
14
+
15
+ # Run the pipeline on a spec file.
16
+ run spec:
17
+ lingot run {{spec}}
18
+
19
+ # Build the JS orchestrator (@autarkis/lingot).
20
+ ts-build:
21
+ cd ts && npm install && npm run build
22
+
23
+ # Build the Python wheel.
24
+ build:
25
+ python -m build
@@ -0,0 +1,57 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "lingot"
7
+ version = "0.0.1"
8
+ description = "Umbrella orchestrator for the Autarkis spatial stack — the mint for embodied-AI ground truth."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ authors = [{ name = "Boris Blosse", email = "borisblosse@gmail.com" }]
12
+ keywords = ["robotics", "synthetic-data", "simulation", "spatial", "ground-truth", "embodied-ai"]
13
+ classifiers = [
14
+ "Development Status :: 2 - Pre-Alpha",
15
+ "Intended Audience :: Developers",
16
+ "Intended Audience :: Science/Research",
17
+ "License :: Other/Proprietary License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
23
+ ]
24
+
25
+ # Worker services Lingot conducts. Commented until published; `just dev-install`
26
+ # editable-installs the sibling repos from ../ for local dev.
27
+ dependencies = [
28
+ # "cadastre",
29
+ # "chitin",
30
+ # "oneiros",
31
+ # "lingot-solver",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ dev = ["pytest>=7.0", "ruff>=0.1", "pyright>=1.1", "build"]
36
+
37
+ [project.scripts]
38
+ lingot = "lingot.cli:main"
39
+
40
+ [project.urls]
41
+ Homepage = "https://github.com/Autarkis/lingot"
42
+ Repository = "https://github.com/Autarkis/lingot"
43
+ Issues = "https://github.com/Autarkis/lingot/issues"
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["src/lingot"]
47
+
48
+ [tool.ruff]
49
+ target-version = "py310"
50
+ line-length = 100
51
+
52
+ [tool.pyright]
53
+ include = ["src"]
54
+ typeCheckingMode = "standard"
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
@@ -0,0 +1,14 @@
1
+ """Lingot — umbrella orchestrator for the Autarkis spatial stack.
2
+
3
+ Lingot is thin. It depends on the worker services — cadastre (registry + solve),
4
+ chitin (physics compile), oneiros (render) — and conducts them through the
5
+ pipeline that turns a constraint spec into an exported, labeled StagedScene.
6
+
7
+ It is the mint: spec in, certified unit of ground truth out. The workers are the
8
+ machinery; Lingot owns the order and the hand-off. See ../LINGOT.md for the thesis.
9
+ """
10
+
11
+ from lingot.pipeline import Pipeline, PipelineResult
12
+
13
+ __version__ = "0.0.1"
14
+ __all__ = ["Pipeline", "PipelineResult", "__version__"]
@@ -0,0 +1,42 @@
1
+ """`lingot` command-line entrypoint."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ from lingot import __version__
11
+ from lingot.pipeline import Pipeline
12
+
13
+
14
+ def main(argv: list[str] | None = None) -> int:
15
+ parser = argparse.ArgumentParser(
16
+ prog="lingot",
17
+ description="Mint a StagedScene from a constraint spec by conducting the worker services.",
18
+ )
19
+ parser.add_argument("--version", action="version", version=f"lingot {__version__}")
20
+ sub = parser.add_subparsers(dest="command", required=True)
21
+
22
+ run = sub.add_parser("run", help="Run the full pipeline on a spec file.")
23
+ run.add_argument("spec", help="Path to a constraint spec (JSON).")
24
+ run.add_argument("-o", "--out", help="Write the StagedScene JSON here (default: stdout).")
25
+
26
+ args = parser.parse_args(argv)
27
+
28
+ if args.command == "run":
29
+ result = Pipeline().run_file(args.spec)
30
+ payload = json.dumps(result.staged_scene, indent=2)
31
+ if args.out:
32
+ Path(args.out).write_text(payload, encoding="utf-8")
33
+ print(f"wrote {args.out}", file=sys.stderr)
34
+ else:
35
+ print(payload)
36
+ return 0
37
+
38
+ return 1
39
+
40
+
41
+ if __name__ == "__main__":
42
+ raise SystemExit(main())
@@ -0,0 +1,49 @@
1
+ """The Lingot pipeline: constraint spec -> exported, labeled StagedScene.
2
+
3
+ Stage order mirrors the stack architecture:
4
+
5
+ spec --> registry(build) --> solver(resolve) --> chitin(compile physics)
6
+ --> oneiros(render) --> export(StagedScene)
7
+
8
+ Lingot owns the order and the data hand-off; each stage is delegated to a worker
9
+ adapter (see workers.py). A stage with no wired worker raises a clear
10
+ NotImplementedError naming what to wire — the skeleton runs end-to-end the moment
11
+ the seams are filled.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ from dataclasses import dataclass, field
18
+ from pathlib import Path
19
+ from typing import Any
20
+
21
+ from lingot.workers import Workers, load_default_workers
22
+
23
+
24
+ @dataclass
25
+ class PipelineResult:
26
+ staged_scene: dict[str, Any]
27
+ artifacts: dict[str, Any] = field(default_factory=dict)
28
+
29
+
30
+ @dataclass
31
+ class Pipeline:
32
+ """Conducts the worker services through the scene-minting pipeline."""
33
+
34
+ workers: Workers = field(default_factory=load_default_workers)
35
+
36
+ def run(self, spec: dict[str, Any]) -> PipelineResult:
37
+ w = self.workers
38
+
39
+ scene = w.require("registry").build_scene(spec)
40
+ scene = w.require("solver").resolve(scene)
41
+ scene = w.require("compiler").compile_physics(scene)
42
+ scene = w.require("renderer").render(scene)
43
+ staged = w.require("exporter").export(scene)
44
+
45
+ return PipelineResult(staged_scene=staged)
46
+
47
+ def run_file(self, spec_path: str | Path) -> PipelineResult:
48
+ spec = json.loads(Path(spec_path).read_text(encoding="utf-8"))
49
+ return self.run(spec)
@@ -0,0 +1,78 @@
1
+ """Adapters to the worker services Lingot orchestrates.
2
+
3
+ Each Protocol below is the seam between Lingot (the conductor) and one worker
4
+ package (the instrument). Wiring a real tool means implementing one adapter and
5
+ pointing it at that worker's real entrypoint — nothing else in the pipeline moves.
6
+
7
+ Status: seams defined, real wiring TODO. We deliberately do NOT guess the workers'
8
+ public APIs here (verify before calling); each adapter names the tool and the
9
+ stage it owns so wiring is a localized, one-file job.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from dataclasses import dataclass
15
+ from typing import Any, Protocol
16
+
17
+
18
+ # --- Worker seams (one per stage of the mint) ------------------------------
19
+
20
+
21
+ class Registry(Protocol):
22
+ """cadastre — the spatial identity tree the scene is struck against."""
23
+
24
+ def build_scene(self, spec: dict[str, Any]) -> Any: ...
25
+
26
+
27
+ class Solver(Protocol):
28
+ """force-directed constraint solver — resolves typed intent into geometry."""
29
+
30
+ def resolve(self, scene: Any) -> Any: ...
31
+
32
+
33
+ class Compiler(Protocol):
34
+ """chitin — bakes physics, emitting .phys collider sidecars."""
35
+
36
+ def compile_physics(self, scene: Any) -> Any: ...
37
+
38
+
39
+ class Renderer(Protocol):
40
+ """oneiros — casts the photoreal surface (Cosmos bridge) over the structure."""
41
+
42
+ def render(self, scene: Any) -> Any: ...
43
+
44
+
45
+ class Exporter(Protocol):
46
+ """scene_to_dict / StagedScene — JSON interchange Atrium and FiftyOne consume."""
47
+
48
+ def export(self, scene: Any) -> dict[str, Any]: ...
49
+
50
+
51
+ @dataclass
52
+ class Workers:
53
+ """Container of wired worker adapters. Unwired seams raise a clear error."""
54
+
55
+ registry: Registry | None = None
56
+ solver: Solver | None = None
57
+ compiler: Compiler | None = None
58
+ renderer: Renderer | None = None
59
+ exporter: Exporter | None = None
60
+
61
+ def require(self, name: str) -> Any:
62
+ worker = getattr(self, name)
63
+ if worker is None:
64
+ raise NotImplementedError(
65
+ f"Lingot worker '{name}' is not wired yet. Implement the {name!r} "
66
+ f"adapter against the real package and pass it into "
67
+ f"Pipeline(workers=Workers({name}=...))."
68
+ )
69
+ return worker
70
+
71
+
72
+ def load_default_workers() -> Workers:
73
+ """Best-effort discovery of installed worker packages.
74
+
75
+ Returns an empty Workers() for now — real adapters land here as each tool's
76
+ public API is verified (`just dev-install` makes the sibling repos importable).
77
+ """
78
+ return Workers()
@@ -0,0 +1,14 @@
1
+ import pytest
2
+
3
+ from lingot import Pipeline, __version__
4
+
5
+
6
+ def test_version():
7
+ assert __version__ == "0.0.1"
8
+
9
+
10
+ def test_unwired_stage_raises_clear_error():
11
+ # Every stage delegates to a worker adapter; with none wired, the first stage
12
+ # must fail loudly and name what to wire.
13
+ with pytest.raises(NotImplementedError, match="registry"):
14
+ Pipeline().run({})
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@autarkis/lingot",
3
+ "version": "0.0.1",
4
+ "description": "The mint for the reserve currency of embodied AI — JS-side orchestrator/client for the Autarkis spatial stack.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": ["dist"],
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "node --test"
12
+ },
13
+ "license": "UNLICENSED",
14
+ "private": true
15
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @autarkis/lingot — JS-side orchestrator / client for the Autarkis spatial stack.
3
+ *
4
+ * The bare npm name `lingot` is taken by an unrelated package, so the JS package
5
+ * is scoped under the org: `@autarkis/lingot`. (PyPI keeps the bare `lingot`.)
6
+ *
7
+ * Lingot is thin: it conducts the worker services and surfaces the StagedScene —
8
+ * the JSON interchange Atrium and FiftyOne consume — to JS/TS consumers.
9
+ */
10
+
11
+ export interface StagedScene {
12
+ [key: string]: unknown;
13
+ }
14
+
15
+ export interface PipelineResult {
16
+ stagedScene: StagedScene;
17
+ artifacts: Record<string, unknown>;
18
+ }
19
+
20
+ /**
21
+ * Conducts the worker services. Real transport — HTTP/IPC to the Python
22
+ * pipeline, or the solver wasm binding — lands behind this seam.
23
+ */
24
+ export class Lingot {
25
+ async run(_spec: Record<string, unknown>): Promise<PipelineResult> {
26
+ throw new Error(
27
+ "Lingot JS orchestrator is not wired yet: connect run() to the Python " +
28
+ "pipeline (HTTP/IPC) or the solver wasm binding.",
29
+ );
30
+ }
31
+ }
32
+
33
+ export const VERSION = "0.0.1";
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true
12
+ },
13
+ "include": ["src"]
14
+ }