feat(engineering): V1-A — Q-001 subsystem-scoped + pillar query integration test

Phase V1-A of the Engineering V1 Completion Plan. Scope was kept tight
per the plan: a single Q-001 shape fix and an integration test that
proves the four pillar queries work end-to-end against one seed graph.

Code change:
  - subsystem_contents() in src/atocore/engineering/queries.py returns
    {subsystem, contains: [{id, type, entity_type, name, status}]} by
    walking inbound part_of edges (the inverse of CONTAINS), filtered
    to active children. `type` matches the catalog spec; `entity_type`
    preserves parity with the rest of this module's response shape.
  - GET /entities/Subsystem/{id}?expand=contains route in routes.py
    matches the Q-001 spec invocation verbatim; 400 on unsupported
    expand, 404 on missing-or-wrong-type.
  - Aliased under /v1.
  - The existing project-wide /engineering/projects/{name}/systems
    route stays as-is for Q-004 (whole-project tree).

V1-A acceptance test (tests/test_v1_a_pillar_queries.py):
  - Q-001 subsystem-scoped: Optics → Primary Mirror + Diverger Lens
  - Q-005 requirements_for: Primary Mirror has its single satisfied req
  - Q-006 orphan_requirements: orphan surfaces, satisfied does not
  - Q-017 evidence_chain: supported claim has the FEA result via
    'supports'; unsupported claim does not
  - Q-009 risky_decisions / Q-011 unsupported_claims also asserted
    against the same seed (Codex P2: don't seed data you don't assert)

Plus targeted tests for the Q-001 helper: missing id, wrong type,
nested child subsystems, inactive-child filtering, real /v1 GET
behavior.

Reviewed by Codex twice: GO WITH CONDITIONS at b575773, GO at 0e83525
after the dual-key emit + Q-009/Q-011 + /v1-behavior + nested/inactive
amends folded in.

Tests: 596 -> 605 (+9). Full local suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-29 13:03:58 -04:00
parent 785756fb58
commit 23cdb3149f
4 changed files with 379 additions and 0 deletions

View File

@@ -2393,6 +2393,41 @@ def api_entity_audit(entity_id: str, limit: int = 100) -> dict:
return {"entity_id": entity_id, "entries": entries, "count": len(entries)}
@router.get("/entities/Subsystem/{subsystem_id}")
def api_subsystem_contents(subsystem_id: str, expand: str = "contains") -> dict:
"""Q-001 (subsystem-scoped variant) — the spec-shaped invocation.
Per ``docs/architecture/engineering-query-catalog.md`` Q-001:
``GET /entities/Subsystem/<id>?expand=contains``
→ ``{ subsystem, contains: [{ id, type, name, status }] }``
Distinct from the project-wide tree at
``GET /engineering/projects/{name}/systems`` (Q-004), which stays
as-is. V1-A only adds this single shape fix; broader query catalog
closure is V1-C.
``expand`` is currently restricted to ``"contains"``; other expand
facets (Q-007 ``constraints``, Q-008 ``decisions``) land in V1-C.
"""
if expand != "contains":
raise HTTPException(
status_code=400,
detail=(
f"unsupported expand={expand!r} for /entities/Subsystem; "
"V1-A supports only 'contains'."
),
)
from atocore.engineering.queries import subsystem_contents
result = subsystem_contents(subsystem_id)
if result is None:
raise HTTPException(
status_code=404,
detail=f"Subsystem not found or not a subsystem: {subsystem_id}",
)
return result
@router.get("/entities/{entity_id}")
def api_get_entity(entity_id: str) -> dict:
"""Get an entity with its relationships and related entities."""