Tasks: a Python SDK that embeds the-loop into somebody else's service
Phase 3 of 3. A DAG of small, verifiable tasks derived from
requirements.md,design.mdandtesting-plan.md. Each task names the requirements it satisfies and the testing-plan row that proves it.
Task list
[x] T1 — Extract
/api/v1intoapi/routes.py. MoveConfigHolderand the request bodies out ofapi/app.py; addbuild_router(holder) -> APIRoutercarrying every operation, prefix included.create_appincludes it and keeps CORS, the MCP mount and its lifespan. Requirements: R2.1, R2.7 · Test: T3, T4[x] T2 — Move the per-request behaviour onto a route class. Config refresh, the
api.requestaudit (exemptinghealthby operation id) and theValueError/LookupError/SpliceErrortranslation move from middleware and app-level handlers into the router'sroute_class.create_appdrops all four. Requirements: R2.3, R4.3, NFR4 · Test: T2, T4, T10[x] T3 — Extract
build_lifespanintoapi/lifespan.py. The hosted-ingress and MCP-session-manager compositioncreate_appperforms becomes a function both consumers call;create_appcalls it with its own arguments. Requirements: R2.5, R3.6 · Test: T4[x] T4 — Let
api/mcp.build_apptake an explicit host allowlist. Optionalallowed_hosts; absent keeps today'sservice.host/portderivation byte-for-byte. Requirements: R2.5 · Test: T2, T4[x] T5 —
sdk/environment.py: the requirement table andcheck_environment(). One record per binary (name, config key, capability, install hint, per-config predicate); resolution byshutil.whichonly. Requirements: R5.2, R5.3, R5.4, R5.5 · Test: T1, T10[x] T6 —
sdk/client.py:TheLoopconstruction and the capability namespaces. Strict config load,config/config_pathmutual exclusion, the eight namespaces,status(),config/config_pathproperties. Requirements: R1.1–R1.5, R4.1, R4.2, R4.4, R4.5, R4.6 · Test: T1, T5[x] T7 —
TheLoop.router(),.mcp_app(),.lifespan(),.mount(). Deferred imports of FastAPI/MCP; the empty-prefix refusal; the un-composed-lifespan refusal; the mount report. Requirements: R2.2, R2.4, R2.6, R3.1–R3.6 · Test: T1, T2, T10[x] T8 —
sdk/__init__.py: the public surface.__all__as the semver'd contract (NFR5), with the module docstring stating what is and is not public. Requirements: R1.1, NFR5 · Test: T5[x] T9 — Unit tests.
tests/test_sdk_client.py,tests/test_sdk_environment.py. Requirements: R1.4, R4.5, R5.3 · Test: T1[x] T10 — Embedding integration tests.
tests/test_sdk_embedding_integration.py, each with a Gherkin docstring naming its scenario and the requirement it traces. Requirements: R2.1–R2.6, R3.1–R3.4, R4.3, NFR4 · Test: T2[x] T11 — Security/abuse-case tests.
tests/test_sdk_security_integration.py— one per abuse case this code can be made to fail. Requirements: §Security abuse cases 2 and 5, R3.3, R3.5 · Test: T10[x] T12 — Parity tests.
tests/test_sdk_docs_parity.py: public symbols ↔ docs, environment table ↔ environment page, namespace methods ↔corecallables. Extendtests/test_api_contract_parity.pywith the router-level assertion. Requirements: R6.4, R2.1 · Test: T3, T5[x] T13 — The SDK documentation.
docs/sdk/index.md,embedding.md,environment.md,reference.md; VitePress nav; links fromdocs/cli/service.mdand the README. Requirements: R6.1, R6.2 · Test: T5, T13[x] T14 — Capability doc and decision record.
docs/capabilities/sdk.mdplus its index row; the control-plane capability doc gains the embedded consumer;decision-085. Requirements: R6.3 · Test: T5[x] T15 — Vendor-SDK analysis and the three follow-up issues.
docs/reports/vendor-sdk-analysis.md; one GitHub issue each for the Claude Agent SDK, the Cursor programmatic surface and PyGithub; linked from the ticket. Requirements: R7.1, R7.2, R7.3 · Test: reviewed as documentation (no code path)[x] T16 — Verification. Execute the testing plan, tick each activity only once run, commit evidence under
evidence/. Requirements: all · Test: T1–T5, T10, T13, T14
Dependency graph (DAG)
graph TD
T1 --> T2 --> T7
T1 --> T7
T3 --> T7
T4 --> T7
T5 --> T6 --> T7 --> T8
T6 --> T9
T7 --> T10 & T11
T8 --> T12 & T13
T13 --> T14
T9 & T10 & T11 & T12 & T14 --> T16
T15 --> T16T15 is independent of the code path and can run at any point; everything else funnels through T7, which is where the seam actually exists.
Checkpoints
- After T4 — the refactor is complete and behaviour-neutral: the whole existing suite must pass with no test adapted. If a test needed changing, the refactor was not neutral; stop and say why in the execution log.
- After T8 — the public surface is frozen for this work item; T12's parity tests are what keep it honest from here.
- After T12 — all gates green before documentation is written, so the docs describe what exists rather than what was planned.
Review comments
None yet.