luplo.core.impact¶
Impact analysis — traverse typed edges to find an item’s blast radius.
Given an item, walk outgoing links edges whose link_type is one of
depends / blocks / supersedes / conflicts up to a fixed
depth ceiling, and return the set of items reachable through those edges.
The ceiling (MAX_IMPACT_DEPTH) is a product-level design
principle, enforced server-side: there is no config knob, no --deep
override, no per-tenant exception. If a caller needs more than five
hops, the model needs decomposing — not this limit raising.
Traversal is outgoing only (links.from_item_id = parent). Edge
direction has an intended meaning for each type; the traversal layer
does not second-guess it.
Cycles are handled inside the recursive CTE via a path array: an item that is already on the current walk is not traversed a second time.
Attributes¶
Edge types that |
|
Hard ceiling on traversal depth. Not user-configurable. |
|
Depth |
Classes¶
One hop in an impact traversal, from |
|
An item reached by traversal, together with the edge that first reached it. |
|
Structured output of |
Functions¶
|
Run an impact analysis from item_id. |
Module Contents¶
- luplo.core.impact.TRAVERSABLE_LINK_TYPES: frozenset[str]¶
Edge types that
impactwill walk. Other link types are ignored.
- luplo.core.impact.MAX_IMPACT_DEPTH: int = 5¶
Hard ceiling on traversal depth. Not user-configurable.
- luplo.core.impact.MIN_IMPACT_DEPTH: int = 1¶
Depth
0would return only the root, so the smallest useful value is1.
- class luplo.core.impact.ImpactEdge¶
One hop in an impact traversal, from
parent_idtochild_id.
- class luplo.core.impact.ImpactNode¶
An item reached by traversal, together with the edge that first reached it.
depthis the shortest-path depth from the root (1means the item is a direct neighbour of the root).- item: luplo.core.models.Item¶
- via: ImpactEdge¶
- class luplo.core.impact.ImpactResult¶
Structured output of
impact().nodesis deduplicated: every item appears once, at its shortest-path depth. Ordering is(depth ASC, title ASC, link_type ASC)— stable across runs so diffs are readable.- root: luplo.core.models.Item¶
- nodes: list[ImpactNode]¶
- async luplo.core.impact.impact(conn: psycopg.AsyncConnection[Any], item_id: str, project_id: str, *, depth: int = MAX_IMPACT_DEPTH) ImpactResult¶
Run an impact analysis from item_id.
- Parameters:
conn – Async psycopg connection.
item_id – Root item (full ID or hex prefix — resolved via
luplo.core.id_resolve.resolve_uuid_prefix()).project_id – Project scope. Traversal never crosses projects; any edge pointing at an item outside this project is dropped.
depth – Maximum hops to traverse. Clamped to
[MIN_IMPACT_DEPTH, MAX_IMPACT_DEPTH]— out-of-range values raiseValidationError.
- Returns:
An
ImpactResultcarrying the root item and the list of reachable items ordered by(depth, title, link_type).- Raises:
ValidationError – If
depthis outside the allowed range.NotFoundError – If the root item does not exist in this project or is soft-deleted.