Task Plan¶
Status: All phases M0–M6 complete, including the M4 GPU run and published numbers/weights (v0.3.0).
Design: docs/architecture.md · Requirements: docs/requirements/
Gates: uv run ruff check . (lint) · uv run pyright (types) · uv run pytest (tests), per docs/testing.md.
Every task is atomic (one deliverable), names its requirement IDs, lists dependencies, and has a binary "Done when" check. Commit messages use conventional commits. [P] = parallelizable within its phase. Test co-location: tests are written in the task that creates the code, never deferred.
Execution Plan¶
Phase M0 — Bootstrap (Sequential)¶
Phase M1 — Wire Contract (T1 first, then parallel)¶
Phase M2 — LLM Backend + Serving (T1 first, then parallel)¶
M1-T6 → M2-T1 ─┬→ M2-T3 ─→ M2-T4 ─┐
├→ M2-T2 ───────────┤
├→ M2-T5 ───────────┼→ M2-T8
├→ M2-T6 ───────────┤
└→ M2-T7 ───────────┘
Phase M3 — Local Encoder (T3,T4 first, then parallel)¶
M2 → M3-T3 ─┬→ M3-T4 ─→ M3-T5 ─┬→ M3-T8
│ ├→ M3-T6 ─┘
M3-T1 ──────┘→ M3-T2 ───────────┘
M3-T4 → M3-T7
Phase M4 — Training (parallel after T1)¶
M3-T5 → M4-T1 ─┬→ M4-T2 → M4-T3 → M4-T4 ─┐
├→ M4-T5 ─────────────────┼→ M4-T6
└──────────────────────────┘
Phase M5 — Ecosystem (parallel)¶
Phase M6 — Proof & Release (Sequential)¶
Task Breakdown¶
M0 — Bootstrap¶
M0-T1: uv project skeleton¶
What: pyproject.toml (py>=3.12,<3.13), extras (serve/fast/onnx/langchain/mcp/train), console entry points, src/tachyone/__init__.py, tests/__init__.py.
Where: pyproject.toml, .python-version, uv.lock, src/tachyone/, tests/.
Depends on: None · Reuses: — · Requirement: NFR-X03, NFR-M06, OPS-01.
Done when: uv sync succeeds on 3.12; uv run python -c "import tachyone" works; entry points resolve to importable stubs.
Tests: none (config) · Gate: quick · Commit: build: bootstrap uv project (python 3.12).
M0-T2: quality tooling config¶
What: ruff, pyright, pytest configuration and dev dependencies.
Where: pyproject.toml (modify).
Depends on: M0-T1 · Requirement: NFR-M01, NFR-M02, OPS-05.
Done when: uv run ruff check ., uv run pyright, uv run pytest all exit 0 on the skeleton.
Tests: none (tooling) · Gate: build · Commit: chore: configure ruff, pyright, pytest.
M0-T3: repo hygiene¶
What: .gitignore, .editorconfig, LICENSE (Apache-2.0), git init.
Where: root.
Depends on: M0-T1 · Requirement: NFR-D03, NFR-S01.
Done when: no secrets/virtualenvs tracked; license present; first commit made.
Tests: none · Gate: quick · Commit: chore: add license and repo hygiene.
M0-T4: CI workflow¶
What: GitHub Actions running ruff + pyright + pytest on push/PR with Python 3.12.
Where: .github/workflows/ci.yml.
Depends on: M0-T2 · Requirement: OPS-05, NFR-M03.
Done when: CI green on the skeleton; future public-API changes are gated by the contract test step.
Tests: none (CI config) · Gate: build · Commit: ci: add lint, type, and test gates.
M1 — Wire Contract¶
M1-T1: noul primitive¶
What: NoulQuestion + NoulAnswer pydantic models and validators.
Where: src/tachyone/primitives.py.
Depends on: M0-T1 · Requirement: PRIM-01.
Done when: valid noul validates; answer serializes {type:"noul", noul: float}.
Tests: unit (tests/test_primitives_noul.py) · Gate: quick · Commit: feat(primitives): add noul question and answer.
M1-T2: choice primitive¶
What: ChoiceQuestion + ChoiceAnswer; enforce ≤255 options; probability key coverage.
Where: src/tachyone/primitives.py (modify).
Depends on: M1-T1 · Requirement: PRIM-02, PRIM-04.
Done when: 255 options accepted, 256 rejected; probabilities keys checked.
Tests: unit (tests/test_primitives_choice.py) · Gate: quick · Commit: feat(primitives): add choice question and answer.
M1-T3: score primitive [P]¶
What: ScoreQuestion + ScoreAnswer; enforce 2–10 levels; legend mapping.
Where: src/tachyone/primitives.py (modify).
Depends on: M1-T1 · Requirement: PRIM-03, PRIM-04.
Done when: 2 and 10 levels accepted, 1/11 rejected; legend generated from criteria.
Tests: unit (tests/test_primitives_score.py) · Gate: quick · Commit: feat(primitives): add score question and answer.
M1-T4: wire envelope [P]¶
What: SystemOneRequest, SystemOneResponse, Usage; answer() delegating to a backend.
Where: src/tachyone/wire.py.
Depends on: M1-T1 · Requirement: WIRE-02, WIRE-03, WIRE-07, PRIM-06.
Done when: N questions → N answers keyed by id; response has model/answers/usage.
Tests: unit (tests/test_wire.py) · Gate: quick · Commit: feat(wire): add systemone request and response.
M1-T5: backend seam + fake backend [P]¶
What: Backend Protocol, PredictionResult, deterministic FakeBackend for tests.
Where: src/tachyone/backends/base.py, tests/fakes.py.
Depends on: M1-T1 · Requirement: BACK-01.
Done when: wire.answer works with FakeBackend; no backend import leaks into wire.
Tests: unit · Gate: quick · Commit: feat(backends): add backend protocol and fake backend.
M1-T6: golden contract tests [P]¶
What: Golden Jev fixtures + parity diff for all primitives and multi-question requests.
Where: tests/fixtures/, tests/test_contract_wire.py.
Depends on: M1-T2, M1-T3, M1-T4, M1-T5 · Requirement: WIRE-06, WIRE-02, WIRE-03, PRIM-01, PRIM-02, PRIM-03, PRIM-06.
Done when: serialized responses match fixtures byte-for-byte (modulo float tolerance); contract test is the CI gate.
Tests: contract · Gate: full · Commit: test(contract): freeze systemone wire parity.
M1-T7: error-shape tests¶
What: Tests for 401/422/429/529 and primitive limit violations.
Where: tests/test_contract_errors.py.
Depends on: M1-T6 · Requirement: WIRE-04, PRIM-02, PRIM-03.
Done when: each status produced with expected body; limit violations yield 422.
Tests: contract · Gate: full · Commit: test(contract): cover systemone error shapes.
M2 — LLM Backend + Serving¶
M2-T1: configuration module¶
What: config.py reading TACHYONE_* env vars with defaults + validation.
Where: src/tachyone/config.py.
Depends on: M1-T6 · Requirement: SERVE-06, NFR-S02.
Done when: defaults applied; secrets never logged; invalid config fails fast.
Tests: unit · Gate: quick · Commit: feat(config): add environment configuration.
M2-T2: LLM backend¶
What: LLMBackend using structured outputs; prompt assembly from questions; JSON extraction; normalization.
Where: src/tachyone/backends/llm.py.
Depends on: M2-T1 · Requirement: BACK-02, BACK-05.
Done when: answers all primitives via a configured provider; probabilities normalized; bounded retry on parse failure.
Tests: unit (mocked provider) + integration (optional live) · Gate: full · Commit: feat(backends): add structured-output LLM backend.
M2-T3: server /v1/systemone¶
What: FastAPI app, Bearer auth dependency, request/response wiring, error mapping.
Where: src/tachyone/serve.py.
Depends on: M2-T1, M2-T2 · Requirement: SERVE-01, WIRE-01, WIRE-04.
Done when: contract tests pass over HTTP; 401 without key; 422 on bad body.
Tests: integration · Gate: full · Commit: feat(serve): add systemone HTTP endpoint.
M2-T4: extension endpoints¶
What: /predict, /predict/batch, /health.
Where: src/tachyone/serve.py (modify).
Depends on: M2-T3 · Requirement: SERVE-02, EXT-04.
Done when: each endpoint responds; /health reports backend/device.
Tests: integration · Gate: full · Commit: feat(serve): add predict, batch, and health endpoints.
M2-T5: Python SDK client + retry¶
What: SDK client posting wire requests, parsing responses, exponential backoff + jitter on 429/529.
Where: src/tachyone/client.py, src/tachyone/__init__.py.
Depends on: M2-T1 · Requirement: SERVE-05, WIRE-05, EXT-05.
Done when: round-trip matches wire; retry verified against a fault-injected server.
Tests: unit + integration · Gate: full · Commit: feat(sdk): add python client with backoff.
M2-T6: CLI + presets [P]¶
What: tachyone CLI with --preset, --predict, --serve; presets router/guard/moderation/triage/email.
Where: src/tachyone/cli.py.
Depends on: M2-T1 · Requirement: SERVE-03, SERVE-04, SERVE-07.
Done when: tachyone "text" --preset triage --predict prints an answer; presets expand to questions.
Tests: unit (preset expansion) + smoke · Gate: full · Commit: feat(cli): add predict CLI and presets.
M2-T7: schemas.py decide() [P]¶
What: Convert JSON Schema / pydantic models into decision primitives; return_details passthrough.
Where: src/tachyone/schemas.py.
Depends on: M2-T1 · Requirement: SERVE-08, CAL-05.
Done when: a sample schema yields valid questions; unknown schema fails clearly.
Tests: unit · Gate: quick · Commit: feat(schemas): add decide() from json schema.
M2-T8: repointed-Jev-client e2e¶
What: End-to-end test where a captured Jev client payload is sent to a live Tachyone server; compare shape.
Where: tests/e2e/test_jev_client.py.
Depends on: M2-T3, M2-T4, M2-T5, M2-T6, M2-T7 · Requirement: NFR-X01, NFR-X02.
Done when: e2e passes; canonical shape unchanged by any extension.
Tests: e2e · Gate: full · Commit: test(e2e): verify repointed jev client.
M3 — Local Encoder Backend¶
M3-T1: script/language detection + checkpoint selection¶
What: Router.route(text) -> checkpoint_id; language/script map; English vs multilingual.
Where: src/tachyone/router.py.
Depends on: M2-T8 · Requirement: ROUTE-01, ROUTE-02, ROUTE-03, ROUTE-05.
Done when: correct checkpoint chosen across Latin/Cyrillic/CJK/Arabic samples; 100+ language list; routing overhead measured < 0.5 ms.
Tests: unit · Gate: quick · Commit: feat(router): add script and language routing.
M3-T2: checkpoint lifecycle¶
What: preload, max_loaded, LRU evict, unload, attach.
Where: src/tachyone/router.py (modify).
Depends on: M3-T1 · Requirement: ROUTE-04.
Done when: max_loaded=1 evicts correctly; no leaked references.
Tests: unit · Gate: quick · Commit: feat(router): add checkpoint lifecycle management.
M3-T3: confidence derivation¶
What: confidence(probabilities) + return_details support.
Where: src/tachyone/calibration.py.
Depends on: M2-T8 · Requirement: CAL-03, CAL-05, PRIM-05, EXT-05.
Done when: confidence ∈ [0,1], monotone with concentration; details returned additively.
Tests: unit · Gate: quick · Commit: feat(calibration): derive confidence from distributions.
M3-T4: agent forward pass + batching¶
What: Single forward pass path, sort_by_length, predict_batch.
Where: src/tachyone/agent.py.
Depends on: M3-T3 · Requirement: BACK-07, NFR-P05.
Done when: batch results align to inputs; sorted batching improves throughput vs naive.
Tests: unit + benchmark · Gate: full · Commit: feat(agent): add single-pass batching.
M3-T5: encoder backend (3 heads)¶
What: EncoderBackend implementing Backend with three task heads (noul/choice/score).
Where: src/tachyone/backends/encoder.py.
Depends on: M3-T1, M3-T4 · Requirement: BACK-03, BACK-06, PRIM-01, PRIM-02, PRIM-03.
Done when: all primitives answered offline; contract tests pass; no network/key.
Tests: contract + integration (offline) · Gate: full · Commit: feat(backends): add encoder backend with three heads.
M3-T6: hooks¶
What: Hook registry for on_predict_start/end, on_route, on_load, on_evict, on_error; on_error on raise.
Where: src/tachyone/hooks.py (+ wiring in agent.py).
Depends on: M3-T4 · Requirement: EXT-01, EXT-02.
Done when: each hook fires; raising hook triggers on_error and serving continues; contract shape unchanged.
Tests: unit + hook-contract (tests/test_hooks_api.py) · Gate: full · Commit: feat(hooks): add prediction and lifecycle hooks.
M3-T7: predict_batch extension [P]¶
What: Expose predict_batch via agent API and extension endpoint.
Where: src/tachyone/agent.py, src/tachyone/serve.py (modify).
Depends on: M3-T4 · Requirement: BACK-07, EXT-04.
Done when: batch of states returns aligned answers over HTTP.
Tests: integration · Gate: full · Commit: feat(agent): expose batch prediction.
M3-T8: offline multilingual integration¶
What: Network-disabled run across languages; verify routing + answers + fallbacks.
Where: tests/integration/test_offline_multilingual.py.
Depends on: M3-T5, M3-T6 · Requirement: ROUTE-05, BACK-06, NFR-S03, NFR-S04, NFR-P02.
Done when: baseline (untrained) checkpoint returns valid shapes across 100+ language samples offline.
Tests: integration · Gate: full · Commit: test(integration): offline multilingual smoke.
M4 — Training & Calibration¶
M4-T1: synthetic data generation¶
What: generate_data.py → deterministic JSONL per primitive, streamed to disk.
Where: training/generate_data.py.
Depends on: M3-T5 · Requirement: TRAIN-01, TRAIN-07.
Done when: same seed → identical file; records include type/input/target.
Tests: unit (determinism) · Gate: quick · Commit: feat(training): add deterministic data generation.
M4-T2: LoRA/QLoRA fine-tuning¶
What: finetune_rlcd.py training loop with quantized base, LoRA, grad checkpointing/accumulation.
Where: training/finetune_rlcd.py.
Depends on: M4-T1 · Requirement: TRAIN-02, TRAIN-06, NFR-R05.
Done when: completes on RTX 3060 12GB without OOM; saves checkpoint + hyperparams.
Tests: integration (short run) · Gate: full · Commit: feat(training): add LoRA fine-tuning.
M4-T3: RLCD proper-scoring loss¶
What: RLCD training against a strictly proper scoring rule over primitive distributions.
Where: training/finetune_rlcd.py (modify).
Depends on: M4-T2 · Requirement: CAL-01, TRAIN-03.
Done when: loss is proper-scoring; probabilities normalized.
Tests: unit (loss properties) · Gate: full · Commit: feat(training): add RLCD proper-scoring objective.
M4-T4: temperature/calibration fitting¶
What: fit_calibration.py minimizing ECE on a held-out split.
Where: training/fit_calibration.py.
Depends on: M4-T3 · Requirement: CAL-02, CAL-04, TRAIN-04, NFR-C06.
Done when: ECE reduces vs baseline; test split untouched during fit.
Tests: unit + evaluation · Gate: full · Commit: feat(training): fit calibration temperature.
M4-T5: evaluation harness [P]¶
What: Accuracy/ECE/latency per primitive + language; public probes (MASSIVE/XNLI/typed-decisions) as a follow-up.
Where: training/evaluate.py, benchmarks/.
Depends on: M4-T1 · Requirement: TRAIN-05, OPS-06.
Done when: report artifacts reproducible from committed commands.
Tests: evaluation · Gate: full · Commit: feat(benchmarks): add accuracy, ECE, latency harness.
M4-T6: reproducibility configs¶
What: Seed + config capture for every stage; documented tolerances.
Where: training/configs/, docs.
Depends on: M4-T4 · Requirement: TRAIN-06, NFR-C04.
Done when: re-run within documented tolerance; configs committed.
Tests: none (process) · Gate: build · Commit: chore(training): add reproducible configs.
M5 — Ecosystem & Acceleration¶
M5-T1: ONNX backend [P]¶
What: OnnxBackend implementing Backend via onnxruntime.
Where: src/tachyone/backends/onnx.py.
Depends on: M3-T5 · Requirement: BACK-04, OPS-01.
Done when: contract tests pass against ONNX; extra import-guarded.
Tests: contract + integration · Gate: full · Commit: feat(backends): add onnx runtime backend.
M5-T2: fast path (TileLang/CUDA graphs) [P]¶
What: Optional accelerated execution path behind the fast extra; graceful fallback.
Where: src/tachyone/fast.py, packaging.
Depends on: M3-T5 · Requirement: NFR-P01, NFR-C05, OPS-01, EXT-03.
Done when: latency improves on supported CUDA; falls back otherwise; router override (force checkpoint/language) honored additively.
Tests: benchmark (conditional-by-extra) · Gate: full · Commit: perf: add optional fast path.
Status: ✅ Delivered. The seam + graceful fallback and router override ship in M5; the B-2
follow-up (TACHYONE_FAST) wires the seam to a per-shape CUDA-graph forward with bf16-resident
weights, measured in benchmarks/fast_path.py (2.68× p50, 0 top-label flips). NFR-P01 met.
M5-T3: MCP stdio server [P]¶
What: tachyone-mcp-server exposing prediction tools over stdio.
Where: src/tachyone/mcp/.
Depends on: M3-T5 · Requirement: OPS-02, SERVE-04.
Done when: an MCP host can list and call the tool; clean shutdown on disconnect.
Tests: integration (conditional-by-extra) · Gate: full · Commit: feat(mcp): add stdio server.
M5-T4: LangChain adapter [P]¶
What: Runnable adapter returning canonical primitives.
Where: src/tachyone/integrations/langchain.py.
Depends on: M3-T5 · Requirement: OPS-03, EXT-02.
Done when: adapter invocation returns contract-shaped results; extra import-guarded.
Tests: integration (conditional-by-extra) · Gate: full · Commit: feat(langchain): add runnable adapter.
M5-T5: Docker + compose [P]¶
What: Dockerfile + docker/compose.yaml running tachyone-serve.
Where: docker/.
Depends on: M3-T5 · Requirement: OPS-04.
Done when: container answers /v1/systemone; compose up works.
Tests: smoke (container) · Gate: full · Commit: build(docker): add image and compose.
M5-T6: telemetry opt-out¶
What: Opt-out telemetry guard (DO_NOT_TRACK=1), disabled by default.
Where: src/tachyone/telemetry.py.
Depends on: M5-T1..T5 · Requirement: OPS-08, NFR-S05.
Done when: telemetry never blocks offline use; opt-out honored.
Tests: unit · Gate: quick · Commit: feat(telemetry): add opt-out telemetry guard.
M6 — Proof & Release¶
M6-T1: benchmark report¶
What: Reproducible benchmark report; public probes (MASSIVE/XNLI/typed-decisions) still open.
Where: benchmarks/report.md, scripts.
Depends on: M5 · Requirement: OPS-06, NFR-D04.
Done when: report regenerated from committed commands.
Tests: evaluation · Gate: full · Commit: docs(benchmarks): publish reproducible report.
M6-T2: documentation site¶
What: Published docs site aggregating docs/.
Where: docs/ config (e.g., mkdocs).
Depends on: M6-T1 · Requirement: NFR-D02, NFR-D01.
Done when: site builds and deploys.
Tests: none (build check) · Gate: build · Commit: docs: add documentation site.
M6-T3: Hugging Face release + model card¶
What: Release weights + model card; GitHub release.
Where: docs/model-card.md, release notes.
Depends on: M6-T2 · Requirement: OPS-07, NFR-D04.
Done when: weights + card published; release tagged.
Tests: none (release) · Gate: build · Commit: chore(release): publish model card and weights.
Parallel Execution Map¶
Phase M0 (Sequential): M0-T1 → M0-T2 → M0-T3 → M0-T4
Phase M1 (Partial parallel):
M1-T1 → { M1-T2 , M1-T3 , M1-T4 , M1-T5 } [P] → M1-T6 → M1-T7
Phase M2 (Partial parallel):
M2-T1 → { M2-T2 , M2-T5 , M2-T6 [P] , M2-T7 [P] }
→ M2-T3 → M2-T4 → M2-T8
Phase M3 (Partial parallel):
{ M3-T1 → M3-T2 , M3-T3 → M3-T4 } → M3-T5 → { M3-T6 , M3-T7 [P] , M3-T8 }
Phase M4 (Partial parallel):
M4-T1 → { M4-T2 → M4-T3 → M4-T4 → M4-T6 , M4-T5 [P] }
Phase M5 (Parallel): { M5-T1..M5-T5 [P] } → M5-T6
Phase M6 (Sequential): M6-T1 → M6-T2 → M6-T3
Validation Checks (MANDATORY before execution)¶
Check 1 — Task Granularity¶
| Task | Scope | Status |
|---|---|---|
| M0-T1 | config + package skeleton | ✅ Granular (one cohesive scaffold) |
| M1-T1/T2/T3 | 1 primitive each | ✅ Granular |
| M1-T4 | envelope models + dispatcher | ✅ Cohesive single file |
| M2-T2 | 1 backend | ✅ Granular |
| M3-T5 | 1 backend (3 heads) | ✅ Cohesive single component |
| M4-T2/T3 | training loop, then objective | ⚠️ T3 modifies T2's file — intentional split (objective is independently testable) |
| M6-T3 | release activity | ✅ Granular (one release) |
Check 2 — Diagram-Definition Cross-Check¶
| Task | Depends On (body) | Diagram Shows | Status |
|---|---|---|---|
| M1-T6 | M1-T2,T3,T4,T5 | converge into M1-T6 | ✅ Match |
| M2-T8 | M2-T3,T4,T5,T6,T7 | converge into M2-T8 | ✅ Match |
| M3-T5 | M3-T1,T4 | converge into M3-T5 | ✅ Match |
| M3-T6 | M3-T4 | after M3-T5 branch | ⚠️ M3-T6 body depends on T4; diagram routes via T5 — resolved: T6 depends on T4 only, shown after T5 for readability |
| M4-T4 | M4-T3 | chain | ✅ Match |
| M5-T6 | M5-T1..T5 | converge into M5-T6 | ✅ Match |
Check 3 — Test Co-location Validation¶
| Task | Code Layer Created | Matrix Requires | Task Says | Status |
|---|---|---|---|---|
| M1-T1..T3 | primitives | unit | unit | ✅ OK |
| M1-T4 | wire | unit + contract (via T6) | unit | ⚠️ contract added in T6 (allowed: T4 is unit-testable; T6 is the contract gate) |
| M2-T2 | backend | unit + integration | unit + integration | ✅ OK |
| M2-T3 | HTTP | integration | integration | ✅ OK |
| M3-T5 | backend | contract + integration | contract + integration | ✅ OK |
| M3-T6 | hooks | unit + hook-contract | unit + hook-contract | ✅ OK |
| M4-T1 | data script | unit | unit | ✅ OK |
| M5-T1 | backend | contract + integration | contract + integration | ✅ OK |
Greenfield note: test types and gate commands are defined in
docs/testing.md. They will be finalized in M0-T2 when the actual commands exist.
Requirement Coverage¶
All 60 functional requirements map to at least one task above; the full matrix is in
docs/requirements/traceability.md. Coverage: 60/60 mapped, 0 unmapped.