Skip to content

epic-3/story-4: Add entity lookup helpers - #36

Closed
usmanabbas7 wants to merge 6 commits into
epic-3/story-3-add-default-segments-and-custom-segment-evaluationfrom
epic-3/story-4-add-entity-lookup-helpers
Closed

epic-3/story-4: Add entity lookup helpers#36
usmanabbas7 wants to merge 6 commits into
epic-3/story-3-add-default-segments-and-custom-segment-evaluationfrom
epic-3/story-4-add-entity-lookup-helpers

Conversation

@usmanabbas7

Copy link
Copy Markdown
Collaborator

Story 3.4 — Add Entity Lookup Helpers (FR28)

Adds the read-only entity-lookup surface over the Story 1.2 immutable indexed ConfigSnapshot. Part of sprint sprint/2026-04-06-convert-python-sdk.

What was built

  • Context.get_config_entity(entity_type, key), get_config_entities(entity_type, keys), get_config_entity_by_id(entity_type, entity_id) — Pythonic snake_case public lookup methods returning typed domain entities (never raw transport dicts), None/empty on miss.
  • evaluation/entity_lookup.py (NEW, L2) — dedicated resolver with a single localized _no_result() decision point so Story 4.2 can swap None → the FR50 typed-reason result without changing the hit return. Context stays a thin orchestrator delegating to it.
  • domain/config_snapshot.py — reused Story 1.2's by-key index; added only the missing _goals_by_id, _segments_by_key, _segments_by_id at construction time (no parallel index, no per-lookup rebuild).
  • Documented SUPPORTED_ENTITY_TYPES vocabulary; unknown/unsupported entity_type yields the same None/empty no-result (never a crash, never a sentinel string).

Scope discipline

  • Entity-lookup only (FR28). No segment surface (Story 3.3), no FR50 typed-reason taxonomy (Story 4.2). Read-only over the immutable snapshot, network-free, determinism (FR25) untouched.
  • Frozen package-root exports unchanged (no EntityType enum introduced).

Tests — zero regressions

  • 462 → 494 (+32): 3 snapshot-index, 21 resolver, 5 Context surface, 2 layering, 1 integration round-trip. Full prior suite stayed green (NFR22).
  • Layering enforced via static-scan tests/test_layering.py (import-linter not installed): entity_lookup.py L2 clause + config_snapshot.py L0-clean clause.

Beads

Epic ai-driven-product-dev-d09w; tasks -fiak (SDK-1 indexes), -p66d (SDK-2 resolver), -uabk (SDK-3 Context surface), -1apb (SDK-4 layering+integration) — all closed.

Readiness & review

Readiness PASS 9/10, 0 auto-delegations (well-formed standalone story, no audit findings). Code review clean round 1.

Stacked on epic-3/story-3 (#35#34#33 chain).

🤖 Generated with Claude Code

@usmanabbas7 usmanabbas7 self-assigned this Jun 8, 2026
@usmanabbas7
usmanabbas7 requested a review from clllaur June 8, 2026 09:09

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements read-only configuration entity lookup functionality (Story 3.4 / FR28) for the Convert Python SDK, adding precomputed indexes to ConfigSnapshot and new lookup methods to Context. Feedback on the changes suggests using List instead of list in get_config_entities for type-hinting consistency, and adding a TODO comment in resolve_entities to future-proof the unresolved key filtering when _no_result() is updated to return a non-None object in a future story.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +160 to +161
if entity is not None:
resolved.append(entity)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of resolve_entities uses if entity is not None: to filter out unresolved keys. However, the design of _no_result() (as described in its docstring) is intended to allow Story 4.2 to replace None with a typed-reason result object (which will be a non-None object). If _no_result() is changed to return a non-None object, entity is not None will evaluate to True for unresolved keys, causing the reason objects to be incorrectly appended to the resolved list instead of being skipped.

To ensure future-proofing and maintain the contract of skipping unresolved keys, consider adding a TODO comment or a helper function to ensure this check is updated when _no_result() is modified.

Suggested change
if entity is not None:
resolved.append(entity)
if entity is not None: # TODO(Story 4.2): Update this check if _no_result() returns a non-None reason object
resolved.append(entity)

Comment on lines +527 to +529
def get_config_entities(
self, entity_type: str, keys: list[str]
) -> list[Mapping[str, Any]]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with the rest of the file (which uses capital List from typing, e.g., List[ExperienceResult]), please use List instead of the lowercase list generic type in the signature of get_config_entities.

Suggested change
def get_config_entities(
self, entity_type: str, keys: list[str]
) -> list[Mapping[str, Any]]:
def get_config_entities(
self, entity_type: str, keys: List[str]
) -> List[Mapping[str, Any]]:

usmanabbas7 and others added 6 commits June 15, 2026 16:26
Beads: ai-driven-product-dev-fiak

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…GREEN)

Beads: ai-driven-product-dev-fiak

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (RED)

Beads: ai-driven-product-dev-p66d

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation (GREEN)

Beads: ai-driven-product-dev-p66d

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…GREEN)

Beads: ai-driven-product-dev-uabk

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-1apb

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@usmanabbas7
usmanabbas7 force-pushed the epic-3/story-4-add-entity-lookup-helpers branch from 9d4e32d to 663c22b Compare June 15, 2026 11:26
@usmanabbas7

Copy link
Copy Markdown
Collaborator Author

F-066 propagation (rebase onto remediated 3-3)

Rebased onto the remediated epic-3/story-3 (commit f2d8916, F-066 segments_matched latch). This branch does not modify evaluation/segments.py — the latch fix is inherited cleanly (no conflicts, no sweep changes; segments.py/test_segments.py are byte-identical to remediated 3-3).

  • uv run pytest504 passed
  • CI gate: no .github/workflows/ on this branch → no-ci.

@abbaseya

Copy link
Copy Markdown
Collaborator

Superseded — all commits already in main (bc76b64). Closing without merge as part of post-sprint cleanup.

@abbaseya abbaseya closed this Jun 18, 2026
@abbaseya
abbaseya deleted the epic-3/story-4-add-entity-lookup-helpers branch June 18, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants