[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "ratatoskr"
version = "0.22.1"
description = "Worldtree Conversation API debug console (web + headless CLI) — multi-pane observability"
readme = "README.md"
requires-python = ">=3.12"
license = { file = "LICENSE" }
authors = [{ name = "Vuong Hoang" }]
keywords = ["worldtree", "debug", "sse", "web", "observability"]

# Network transport for the injected AsyncClient (INV-CUT-1); SSE parsing is
# owned by worldtree-sdk post-cutover (#20 slice-7 dropped httpx-sse).
dependencies = [
    "httpx>=0.27",
    "worldtree-sdk==1.2.0", # #20 cutover: the consumer client layer (gitea PyPI); the hand-rolled wrappers now live behind ratatoskr.wt. 1.2.0 = response-side allocation caps + a new exported `ResponseTooLarge` (a ProtocolError, NOT a ConnectionDropped — retrying an oversized response is futile; caps: 2xx body 108,004,096 B, SSE frame 540,000 B; the caps assume a 2.5.0 server, which worldtree-dev runs, so safe on legal traffic). We catch it explicitly at the stream + read surfaces (INV-CUT-2). Absorbed WT spec 2.4.0/2.5.0 (zero-schema, no generated-type change). 1.1.2 = closed the SSE turn-stream traversal we caught in 1.1.1 (quote safe="" at turn_stream.py:185). 1.1.1 = path-encoding correctness fix + additive define_or_reuse / set_persona_state_raw (our parity #6) + 64 KiB error-body alloc cap. Same frozen wire as 1.0.0 (drop-in).
]

[project.optional-dependencies]
web = [
    "starlette>=0.40",
    "uvicorn[standard]>=0.30",
]
# Tier-3 Bifrost consumer: the durable memory.* + affect.* persistence
# provider Worldtree writes into. Opt-in extra — distinct deployment surface
# from the debug TUI. Recipe: bifrost/docs/implementing-a-consumer.md.
provider = [
    "ratatoskr[web]",       # reuse the starlette + uvicorn ASGI stack
    "bifrost==1.1.5",       # consumer engines + library. 1.1.5 = gate ALL optional store verbs → clean unsupported_capability (not 500), extending 1.1.4's maintenance-verb backstop to the full optional-verb set + a v0.6 memory verb-floor conformance harness (frozen wire v0.6, no schema change). 1.1.4 = hasattr-gate backstop for the maintenance verbs (mark_superseded/mark_invalid/patch_many/delete_many/upsert_edges/get_edges_for → unimplemented verb degrades to unsupported_capability 400, never AttributeError/500/retry-storm; we surfaced it via WT #364) + 1.1.3 scan/cursor conformance harness + 1.1.2 frozen-v0.6 fix. 1.1.1 = frozen-wire serialization fix (ADR-0008): additive capability fields are gated on the NEGOTIATED wire, so a v0.6-negotiated describe_store handshake stays v0.6-clean. 1.1.0 leaked the v0.7-additive `sortable_chunk_fields` into v0.6 StoreCapabilities → a strict v0.6 client (additionalProperties:false) rejects our server's handshake. Wire schemas + pins UNCHANGED (serialization-correctness only); our v0.7 handshake with Worldtree b47 is unaffected. (1.1.0 = wire v0.7 additive: memory.scan sort + sortable_chunk_fields; 1.0.0 = first STABLE, wire v0.6 FROZEN; 0.8.0/v0.6 scope_all/scope_any #11; 0.7.0/v0.5 agent_self)
    "jsonschema>=4",        # bifrost runtime dep — envelope validation
    "sqlite-vec>=0.1.6",    # vector index for the memory plane (vec0 virtual table)
]
dev = [
    "pytest>=8",
    "pytest-asyncio>=0.24",
    "respx>=0.21",          # httpx mocking for SSE-recorded snapshot tests
    "ruff>=0.6",
    "mypy>=1.11",
    "pyyaml>=6",            # used by docs/contracts/contract_parser.py and scripts/contract_drift_check.py
    "ratatoskr[web]",       # web extras included in dev so test_web_* can import starlette
]

[project.scripts]
ratatoskr                 = "ratatoskr.cli:main"
ratatoskr-web             = "ratatoskr.web.entrypoint:main"
ratatoskr-provider        = "ratatoskr.provider.serve:main"
ratatoskr-memory-provider = "ratatoskr.provider.serve_memory:main"
ratatoskr-combined-provider = "ratatoskr.provider.serve_combined:main"

[project.urls]
Repository = "https://gitea.phasefinal.com/vh/ratatoskr"
"Design Brief" = "https://gitea.phasefinal.com/vh/brokkr-smithy/src/branch/main/docs/ratatoskr-design-brief.md"

# Worldtree spec pin — see docs/SPEC-PIN.md for the full bump procedure.
# Ratatoskr is built against Worldtree at this commit; the vendored
# spec snapshot in docs/ reflects that SHA.
[tool.ratatoskr.spec-pin]
worldtree-spec-rev = "c9e59ec"
worldtree-version = "v1.0.0b22"
pinned-on = "2026-07-06"

# Bifrost lives on the auth-gated gitea PyPI index (not public PyPI).
# uv reads the credential from UV_INDEX_GITEA_USERNAME / _PASSWORD or ~/.netrc.
[[tool.uv.index]]
name = "gitea"
url = "https://gitea.phasefinal.com/api/packages/vh/pypi/simple/"

[tool.uv.sources]
bifrost = { index = "gitea" }
worldtree-sdk = { index = "gitea" }

[tool.hatch.build.targets.wheel]
packages = ["src/ratatoskr"]

# Issue #16: ship the web companion's static HTML in the wheel so
# importlib.resources can locate it post-install.
[tool.hatch.build.targets.wheel.force-include]
"src/ratatoskr/web/static" = "ratatoskr/web/static"

[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP", "RUF"]

[tool.mypy]
python_version = "3.12"
strict = true
