Analysis algorithms for Choreo.Requirement diagrams.
Provides traceability coverage, risk propagation, impact analysis, and structural validation.
Summary
Functions
Detects cycles among requirement-to-requirement relationships.
Returns components, tests, and stakeholders related to a requirement.
Returns coverage statistics for the requirements diagram.
Returns high or critical risk requirements that are neither satisfied nor verified.
Returns all nodes upstream and downstream of a given node.
Returns requirements that have no relationships.
Returns requirements related to a given component, test, or stakeholder.
Propagates risk from parent requirements down to their children.
Returns a traceability matrix: requirements mapped to their related components, tests, and stakeholders.
Returns high or critical risk requirements that do not have a lower-risk child refinement.
Returns requirements with no satisfies edge from a component.
Returns requirements with no verifies edge from a test.
Evaluates structural integrity and returns a list of human-readable warnings and errors.
Returns human-readable validation messages.
Functions
@spec circular_dependencies(Choreo.Requirement.t()) :: [[Yog.node_id()]]
Detects cycles among requirement-to-requirement relationships.
Only considers depends, refines, contains, and derives edges.
Returns a list of cycles, where each cycle is a list of node IDs.
@spec components_for(Choreo.Requirement.t(), Yog.node_id()) :: [Yog.node_id()]
Returns components, tests, and stakeholders related to a requirement.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1, id: "R1", text: "One")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :r1)
iex> Analysis.components_for(req, :r1)
[:c]
@spec coverage(Choreo.Requirement.t()) :: map()
Returns coverage statistics for the requirements diagram.
Returns a map with satisfied, verified, and orphan requirement IDs plus ratios.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1, id: "R1", text: "One")
...> |> Choreo.Requirement.add_requirement(:r2, id: "R2", text: "Two")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.add_test(:t)
...> |> Choreo.Requirement.satisfies(:c, :r1)
...> |> Choreo.Requirement.verifies(:t, :r2)
iex> %{satisfied: [:r1], verified: [:r2], orphan: []} = Analysis.coverage(req)
@spec high_risk_gaps(Choreo.Requirement.t()) :: [Yog.node_id()]
Returns high or critical risk requirements that are neither satisfied nor verified.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1,
...> id: "R1",
...> text: "Critical",
...> risk: :critical
...> )
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :r1)
iex> Analysis.high_risk_gaps(req)
[] # satisfied, so not a gap
@spec impact_of(Choreo.Requirement.t(), Yog.node_id()) :: [Yog.node_id()]
Returns all nodes upstream and downstream of a given node.
Useful for impact analysis: "if I change this component, what else is affected?"
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1, id: "R1", text: "One")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :r1)
iex> Analysis.impact_of(req, :c)
[:r1]
@spec orphan_requirements(Choreo.Requirement.t()) :: [Yog.node_id()]
Returns requirements that have no relationships.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:orphan, id: "R1", text: "Orphan")
...> |> Choreo.Requirement.add_requirement(:sat, id: "R2", text: "Satisfied")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :sat)
iex> Analysis.orphan_requirements(req)
[:orphan]
@spec requirements_for(Choreo.Requirement.t(), Yog.node_id()) :: [Yog.node_id()]
Returns requirements related to a given component, test, or stakeholder.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1, id: "R1", text: "One")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :r1)
iex> Analysis.requirements_for(req, :c)
[:r1]
@spec risk_propagation(Choreo.Requirement.t()) :: %{required(Yog.node_id()) => atom()}
Propagates risk from parent requirements down to their children.
A child requirement inherits the maximum risk of any ancestor through
refines, contains, or derives relationships.
Returns a map of requirement ID to propagated risk.
@spec traceability_matrix(Choreo.Requirement.t()) :: %{ required(Yog.node_id()) => map() }
Returns a traceability matrix: requirements mapped to their related components, tests, and stakeholders.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:r1, id: "R1", text: "One")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :r1)
iex> matrix = Analysis.traceability_matrix(req)
iex> matrix[:r1].components
[:c]
@spec unmitigated_risks(Choreo.Requirement.t()) :: [Yog.node_id()]
Returns high or critical risk requirements that do not have a lower-risk child refinement.
These are risks that have not been decomposed into more manageable pieces.
@spec unsatisfied(Choreo.Requirement.t()) :: [Yog.node_id()]
Returns requirements with no satisfies edge from a component.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:unsat, id: "R1", text: "Unsatisfied")
...> |> Choreo.Requirement.add_requirement(:sat, id: "R2", text: "Satisfied")
...> |> Choreo.Requirement.add_component(:c)
...> |> Choreo.Requirement.satisfies(:c, :sat)
iex> Analysis.unsatisfied(req)
[:unsat]
@spec unverified(Choreo.Requirement.t()) :: [Yog.node_id()]
Returns requirements with no verifies edge from a test.
Examples
iex> req = Choreo.Requirement.new()
...> |> Choreo.Requirement.add_requirement(:unver, id: "R1", text: "Unverified")
...> |> Choreo.Requirement.add_requirement(:ver, id: "R2", text: "Verified")
...> |> Choreo.Requirement.add_test(:t)
...> |> Choreo.Requirement.verifies(:t, :ver)
iex> Analysis.unverified(req)
[:unver]
@spec validate(Choreo.Requirement.t()) :: [{:error | :warning, String.t()}]
Evaluates structural integrity and returns a list of human-readable warnings and errors.
@spec validate_messages(Choreo.Requirement.t()) :: [{:error | :warning, String.t()}]
Returns human-readable validation messages.