Choreo.Requirement.Analysis (Choreo v0.11.0)

Copy Markdown View Source

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

circular_dependencies(req)

@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.

components_for(req, id)

@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]

coverage(req)

@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)

high_risk_gaps(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

impact_of(req, id)

@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]

orphan_requirements(req)

@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]

requirements_for(req, id)

@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]

risk_propagation(req)

@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.

traceability_matrix(req)

@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]

unmitigated_risks(req)

@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.

unsatisfied(req)

@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]

unverified(req)

@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]

validate(req)

@spec validate(Choreo.Requirement.t()) :: [{:error | :warning, String.t()}]

Evaluates structural integrity and returns a list of human-readable warnings and errors.

validate_messages(req)

@spec validate_messages(Choreo.Requirement.t()) :: [{:error | :warning, String.t()}]

Returns human-readable validation messages.