369857d3f1
Heid panel review (Gróa + Hulda, thread 01KSP5P6CSJH) on v0.15.0/
v0.15.1 surfaced one load-bearing bug + several precision items. This
pass closes them.
Load-bearing fix — cancel paths targeted the wrong turn_id:
- `_TURN_COUNTER` allocates browser-local ids (1, 2, 3…); the real
upstream Worldtree turn_id (e.g. 799) only arrives in the first SSE
event. The v0.15.x cancel/disconnect/shutdown paths posted to
/sessions/{sid}/turns/{LOCAL_ID}/cancel — wrong URL upstream.
- TurnHandle.upstream_response (dead field) → upstream_turn_id: int|None.
Captured from the first event's sse_id.turn_id in the stream
generator. All cancel paths now target it. Cancel before the upstream
stream starts (upstream_turn_id None) is a no-op
({"cancelled": false, "reason": "not_started"}).
- The old cancel tests mocked the local-id URL, so they encoded the bug;
rewritten to assert the UPSTREAM id is targeted.
Behavior change (minor-bump driver) — server-side end_user_id:
- create_app gains end_user_id kwarg; entrypoint reads
RATATOSKR_END_USER_ID and threads it in. POST /api/sessions uses
app.state.end_user_id, IGNORING any browser-supplied value (a client
can't impersonate an arbitrary end-user partition). JS no longer
sends end_user_id.
Precision fixes:
- Entrypoint missing-extras ImportError catch scoped to starlette/
uvicorn ONLY; baseline-dep / first-party import failures now
propagate as real tracebacks instead of masking as exit-12.
- Lifespan shutdown logs per-pending session_id + upstream_turn_id
(was a single aggregate count).
Tests (+18; 376 total):
- disconnect_triggers_upstream_cancel (INV-005 load-bearing — drives
the stream generator directly + cancels the consuming task; would
have caught the turn_id bug)
- cancel_targets_upstream_turn_id, cancel_before_started_is_noop,
cancel_failed_500
- server-side end_user_id: uses / ignores-body / omits-when-unset
- create_app: routes_registered / state_attached / factory_stored
- entrypoint: default_host / port_zero / happy_argv / open / no-open
- real_import_bug_propagates (precision guard)
- full_event_vocab at the stream-endpoint layer
Contract #16 amended: v0.16.0 amendment banner + INV-005/006 reworded
for upstream_turn_id + FN sketches corrected (server-side end_user_id,
upstream_response→upstream_turn_id, manual client lifecycle vs the
non-executable async-with sketch, not-started cancel branch).
77 lines
2.2 KiB
TOML
77 lines
2.2 KiB
TOML
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[project]
|
|
name = "ratatoskr"
|
|
version = "0.16.0"
|
|
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
license = { file = "LICENSE" }
|
|
authors = [{ name = "Vuong Hoang" }]
|
|
keywords = ["worldtree", "tui", "debug", "sse", "textual"]
|
|
|
|
# Network + SSE consumer + TUI framework.
|
|
# See docs/design-brief.md §1 (Textual), §3 (httpx-sse).
|
|
dependencies = [
|
|
"httpx>=0.27",
|
|
"httpx-sse>=0.4",
|
|
"textual>=0.85",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
web = [
|
|
"starlette>=0.40",
|
|
"uvicorn[standard]>=0.30",
|
|
]
|
|
dev = [
|
|
"pytest>=8",
|
|
"pytest-asyncio>=0.24",
|
|
"respx>=0.21", # httpx mocking for SSE-recorded snapshot tests
|
|
"ruff>=0.6",
|
|
"mypy>=1.11",
|
|
"textual-dev>=1.5", # textual console + live reload during dev
|
|
"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"
|
|
|
|
[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 = "562001af28d752c3a60d449c7ddd09f44fa9dc9a"
|
|
worldtree-version = "v0.29.0"
|
|
pinned-on = "2026-05-26"
|
|
|
|
[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
|