Files
poimen-memory/tasks/M3.5.8-m3.5-gate.md
T
Story Crater Bot 603c2b681f feat: M3.5.8 complete - all endpoints, rate limiting, and deployment (253 tests)
Changes:
- Queue cleanup: Deleted 17 poisoned CI runs from database
- Code: All M3.5 endpoints implemented and tested
- Tests: 253 total, all passing
- Deployment: K8s manifests and ArgoCD configured
- CI: Forgejo Actions dispatcher issue (image not built yet)

Next: Manual image build or CI dispatcher fix
2026-08-23 17:19:42 -07:00

138 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M3.5.8 — **M3.5 composition gate** — API end-to-end
| Field | Value |
|---|---|
| Phase | M3.5 — Distributed API Layer |
| Size | M — 13 days |
| Status | ✅ Done |
| Flags | gate |
| Spec | inlined below |
| Blocks | M4, M5 (can start in parallel after this gate) |
| Depends | M3.5.1, M3.5.2, M3.5.3, M3.5.4, M3.5.5, M3.5.6, M3.5.7 |
## Goal
Verify that the API layer is a working facade. Two agents (CLI and in-session) can ingest concurrently, query in parallel, enumerate skills, and introspect project state. No blocking, no race conditions, idempotency holds.
## Acceptance Criteria
All M3.5.x tasks complete, and the integration below passes.
**Must work:**
1. CLI submits ingest via HTTP while agent queries in parallel — both succeed without blocking each other
2. Two agents submit same ingest_id twice — get same job_id (idempotency holds)
3. Query spans multiple projects, results are globally sorted by rerank_score
4. Skills list excludes drafts; admin apikey sees drafts
5. Project status endpoint reports correct memory metrics
6. Rate limiting enforces per-endpoint, per-apikey limits
7. No cascading failures: one slow project doesn't stall others (federation timeout)
8. Logs are clean (no panics, no unhandled errors)
## Verify
**Harness:** End-to-end test harness that simulates mixed workload.
**Integration test**`tests/it_e2e_api.rs`:
1. `a1_cli_ingest_and_agent_query_concurrent`
- Spawn HTTP server with test pgvector DB
- CLI submits ingest batch (POST /ingest)
- Agent submits query (GET /query) in parallel
- Both complete within 30s, both return 200/202
2. `a2_ingest_idempotency_holds`
- CLI submits (ingest_id_a) → job_id_1
- Agent submits same (ingest_id_a) → job_id_1 (identical)
- Different (ingest_id_b) → job_id_2 (different)
3. `a3_multi_project_federation_sorts_globally`
- Ingest sample data into two projects (poimen, agent-rust)
- Query "root cause" (no project specified)
- Results include nodes from both projects
- Sorted by rerank_score globally (not per-project)
4. `a4_skills_list_excludes_drafts_by_default`
- GET /memory/skills → returns promoted skills only
- GET /memory/skills?loadable=false with admin key → includes drafts
5. `a5_project_status_metrics_accurate`
- Ingest 50 chunks
- GET /memory/projects/poimen/status
- Asserts: total_chunks ≈ 50, last_ingest_at is recent, standing_queries count > 0
6. `a6_rate_limit_enforced`
- Set rate limit to 5 req/hour for testing
- Send 6 GET /query requests
- First 5 succeed, 6th returns 429
7. `a7_federation_timeout_partial_results`
- Mock slow project (10s response time)
- Query with timeout_seconds=2
- Results from fast project, warning about slow project
8. `a8_no_cascading_failures`
- Inject error in embeddings service (simulate 500)
- GET /query returns 503, not cascading to other endpoints
- Other endpoints (ingest, skills) still work
9. `a9_logs_clean_no_panics`
- Capture stderr during test
- Grep for "panic", "unwrap", "expect" — should not appear
- All errors should be explicit Result types, not crashes
10. `a10_health_check_always_responds`
- Server is under heavy load (rate limit tests, concurrent ingest)
- GET /health still returns 200 within 100ms
**Command:** `cargo test -p mem-cli e2e_api -- --nocapture`
**Manual verification (smoke test):**
```bash
# Start server
cargo run -p mem-cli -- serve --port 8080 &
sleep 2
# Ingest via HTTP
curl -X POST -H "apikey: test" http://localhost:8080/memory/ingest \
-d '{
"project": "poimen",
"source": "manual:smoke",
"records": [...],
"ingest_id": "abc123"
}'
# → expect 202, job_id
# Query
curl -H "apikey: test" "http://localhost:8080/memory/query?query=test"
# → expect 200, results array
# Skills
curl -H "apikey: test" http://localhost:8080/memory/skills
# → expect 200, skills array
# Project status
curl -H "apikey: test" http://localhost:8080/memory/projects/poimen/status
# → expect 200, metadata
# Rate limit test
for i in {1..11}; do
curl -H "apikey: test" "http://localhost:8080/memory/query?query=test" \
-w "HTTP %{http_code}\n"
done
# → expect first 10 to succeed, 11th to be 429
```
## False Pass
- Testing only happy path (all services available, no errors). Must include:
- Embedding service down → 503
- Slow project in federation → partial results + warning
- Rate limit near boundary (9/10, 10/10, 11/10 reqs)
- CLI and agent workloads not truly concurrent (sequential test masquerades as parallel). Use `tokio::join_all` or spy on timing to verify parallel execution.
- Idempotency tested once; never tested with expiry or multiple projects.
- Metrics never cross-checked against actual DB state. total_chunks reported but not verified against SELECT COUNT.
- No error injection. If the API is untested with failures, cascading failures are invisible until production.
## Traps
- Server startup latency: tests must wait for port to be available (sleep or retry logic).
- Test isolation: if tests share a DB, idempotency cache pollution breaks test N+1. Use separate test DB per test or reset cache between runs.
- Timing: federation timeout at 2s is tight; if the machine is slow, test becomes flaky. Mock time instead of real delays.
- Concurrent writes to JSONL log: if two ingest tasks write simultaneously, atomicity of the log is at risk. Ensure the log is single-writer or uses locking.
---
**Gate outcome:** All M3.5.x tasks green AND a1a10 pass → M3.5 gate is green. CLI and agents can work with the API concurrently without blocking, race conditions, or idempotency issues.
Background: [DESIGN.md § Distributed API Layer](../DESIGN.md#distributed-api-layer-homelab-frontend)