1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use crate::{ActorId, ArtifactId, DecisionId, Key, ProjectId, RequirementId, RiskId, WorkItemId};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// Traceable motivation for one or more work items.
#[serde(deny_unknown_fields)]
pub struct Requirement {
/// Stable entity identity; it must match its containing map key.
pub id: RequirementId,
/// Human-readable key, unique in this entity category.
pub key: Key,
/// Project that owns this entity.
pub project: ProjectId,
/// Non-empty human-readable title.
pub title: String,
/// Requirement that the implementation must satisfy.
pub statement: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// Category of externally stored work evidence.
pub enum ArtifactKind {
/// A Git commit.
GitCommit,
/// A code review request.
PullRequest,
/// An external file.
File,
/// A build output.
Build,
/// Acceptance or test evidence.
TestResult,
/// A component specification.
Datasheet,
/// A supplier quotation.
Quote,
/// A procurement order.
PurchaseOrder,
/// A design file.
Cad,
/// A photograph.
Photo,
/// Evidence outside the standard categories.
Other,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// Reference to evidence with its creating principal and timestamp.
#[serde(deny_unknown_fields)]
pub struct Artifact {
/// Stable entity identity; it must match its containing map key.
pub id: ArtifactId,
/// Domain category of this value.
pub kind: ArtifactKind,
/// Non-empty locator of the evidence.
pub uri: String,
/// Human-readable evidence description.
pub label: String,
/// Artifact-specific attributes, such as a Git commit hash.
pub metadata: BTreeMap<String, String>,
/// Principal responsible for this evidence.
pub created_by: ActorId,
/// Timestamp at which the evidence was recorded.
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// Lifecycle of a recorded choice or question that can optionally gate execution.
pub enum DecisionStatus {
/// Unresolved question.
Open,
/// Recorded choice with an outcome.
Decided,
/// Decision no longer applicable.
Superseded,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// A question or choice included in work context, optionally blocking execution.
#[serde(deny_unknown_fields)]
pub struct Decision {
/// Stable entity identity; it must match its containing map key.
pub id: DecisionId,
/// Human-readable key, unique in this entity category.
pub key: Key,
/// Project that owns this entity.
pub project: ProjectId,
/// Question requiring a decision.
pub question: String,
/// Whether the question still gates execution.
pub status: DecisionStatus,
/// Non-empty resolution for a decided gate.
pub outcome: Option<String>,
/// When `decide`, or the reviewed change that created this replacement, resolved it; absent for
/// decisions resolved before this was recorded.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resolved_at: Option<DateTime<Utc>>,
/// Reason for the choice or for raising the question.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rationale: Option<String>,
/// Work whose context includes this decision, without imposing an execution gate.
#[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
pub related_work: BTreeSet<WorkItemId>,
/// Sources supporting the decision, distinct from task completion evidence.
#[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
pub artifact_ids: BTreeSet<ArtifactId>,
/// Work items gated by this decision.
pub blocks: BTreeSet<WorkItemId>,
/// Superseded decision whose rationale and sources this choice replaces.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub supersedes: Option<DecisionId>,
/// Structured alternatives; when present, a decided outcome is exactly one option key.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub options: Vec<crate::DecisionOption>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// Qualitative consequence of a risk.
pub enum RiskImpact {
/// Small consequence.
Low,
/// Moderate consequence.
Medium,
/// Large consequence.
High,
/// Project-threatening consequence.
Critical,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// Identified uncertainty with probability and related work.
#[serde(deny_unknown_fields)]
pub struct Risk {
/// Stable entity identity; it must match its containing map key.
pub id: RiskId,
/// Human-readable key, unique in this entity category.
pub key: Key,
/// Project that owns this entity.
pub project: ProjectId,
/// Risk event or condition.
pub description: String,
/// Probability in [0, 1].
pub probability: f64,
/// Qualitative consequence if the risk occurs.
pub impact: RiskImpact,
/// Work affected by the risk.
pub related_work: BTreeSet<WorkItemId>,
/// Optional response to reduce the risk.
pub mitigation: Option<String>,
}