Concepts · 3 of 7
Composing cases
A case opens child cases at run time, and their outcomes become evidence in the parent.
Work that one case cannot hold opens further cases. An audit opens one change per finding; an epic opens one change per story; an incident opens an investigation and, once the cause is known, a remediation change. The parent's conclusion depends on how its children end.
Engineering protocols express this with two primitives Canon will provide (decision record 0081): an action that opens a child case, and an evidence kind that carries a child's terminal outcome back to the parent. Execution strategy (scheduling, retries) stays outside the protocol.
Decided · recorded, not built
- Decidedcase.open(protocol, subject)An action that opens a child case; its authority is declared by the parent protocol. Not in Canon protocol/1 yet.
- Decidedcase_outcome evidenceA child's terminal outcome is evidence for a parent claim. Not in Canon protocol/1 yet.
- DecidedParent–child links stored by AEPThe planning view becomes a rendering of the case graph.
Planned · roadmap only
- PlannedFan-out with for_eachDesign proposal; no decision record yet.
- PlannedFan-in quantifiers every / some / noneDesign proposal; no decision record yet.
- PlannedCancellation with parent.closedDesign proposal.
- Parentcase.open
An action of the parent protocol opens one child case per item.
- Childrentheir own protocol
Each child runs under its own protocol and its own commission.
- Evidencecase_outcome
Each terminal outcome returns to the parent as evidence.
- Fan-inevery / some / none
A parent claim quantifies over the children; UNKNOWN while any is open.
Opening children: fan-out
The number of children is often known only at run time: an audit finds seven issues, an epic has
twelve stories. The children come from evidence the parent already holds. In the proposed syntax,
for_each makes an action admissible once per evidence record that has no child yet, so the
frontier lists concrete instances, remediation.open[finding-3], remediation.open[finding-5], and
each one is checked on its own.
evidence_kinds:
finding:
description: One issue the audit found; carries a subject (repository, path, revision).
actions:
remediation.open:
for_each: {evidence: finding} # one admissible instance per finding not yet opened
opens:
protocol: software.change
subject: finding.subject
requires:
- capability: case.open
Because case.open needs a capability, a composition policy can cap how many children one case may
open, instead of a protocol hard-coding a number.
Deciding on the children: fan-in
A parent claim quantifies over the children opened by one action, by outcome:
claims:
findings.resolved:
true_when:
children:
protocol: software.change
opened_by: remediation.open
every:
outcome: [accepted, declined]
The quantifiers are three-valued, like every Canon claim:
| Quantifier | TRUE when | FALSE when | UNKNOWN when |
|---|---|---|---|
every | every child is closed with a matching outcome | some child is closed with a non-matching outcome | no mismatch yet, but some child is still open |
some | some child is closed with a matching outcome | every child is closed and none matches | no match yet, but some child is still open |
none | every child is closed and none matches | some child is closed with a matching outcome | no match yet, but some child is still open |
More columns: swipe horizontally, or focus the table and use the arrow keys.
With no children opened, every and none are TRUE and some is FALSE; a protocol that needs at
least one child says so with a separate claim. UNKNOWN while any child is open is what makes the
parent wait, without a scheduler and without a state machine.
Cancellation and failure
| Situation | Proposed rule |
|---|---|
A child ends abandoned | It counts as a non-matching outcome, so an every claim becomes FALSE. The parent protocol decides whether that blocks it or whether it may open a replacement. |
| The parent reaches a terminal outcome while children are open | Each open child receives a parent.closed evidence record, and its own protocol declares what that means; for most, outcome abandoned. |
| The parent is abandoned | The same. No child is left running silently. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
Still open: whether several commissions may work one case at once, how cycles are prevented (a case must not open an ancestor), and whether a child may read its parent's evidence.
Three shapes
assessment.audit/1
action review.dimension → evidence finding (0..n)
action remediation.open for_each finding → software.change/1
claim findings.resolved every child outcome in [accepted, declined]
outcome remediated assessed + findings.resolved
delivery.wave/1
action story.open for_each story_selected → software.change/1
claim stories.done every child outcome in [accepted, declined]
action integration.merge precondition stories.done, needs repository.merge
incident.response/1
action investigation.open → investigation (one child)
action remediation.open → software.change/1 (one child, after cause.identified)
The shipped incident.response/1 does not open children yet; these lines show where it would.