1use kernel::event::Who;
16use kernel::event::record::{CheckpointCommitted, Opening, RunFrozen, RunStarted};
17use kernel::{
18 Address, AxCode, AxError, Completion, EventDraft, EventKind, Ledger, Locator, Payload, RunId,
19 TimeMs,
20};
21
22use crate::catalog::SkillPin;
23use crate::handoff::Handoff;
24
25use super::RunPlan;
26
27#[derive(Debug, Clone, Copy)]
30pub struct Charter<'a> {
31 pub run: RunId,
32 pub who: &'a str,
34 pub addr: &'a Address,
35 pub task: &'a str,
36 pub goal: &'a str,
37 pub job: &'a Locator,
38 pub parent: Option<RunId>,
39 pub predecessor: Option<RunId>,
40 pub dispatched_by: &'a Who,
41 pub skills: &'a [SkillPin],
42 pub policy: kernel::RunPolicy,
44 pub naming: Option<kernel::B3Hash>,
46 pub opening: Option<Opening>,
50 pub effort: Option<kernel::Effort>,
54 pub agent: Option<&'a kernel::event::record::AgentRunIdentity>,
58}
59
60impl RunPlan {
61 pub fn charter(&self) -> Charter<'_> {
64 Charter {
65 run: self.run,
66 who: &self.who,
67 addr: &self.addr,
68 task: &self.task,
69 goal: &self.goal,
70 job: &self.job,
71 parent: self.parent,
72 predecessor: self.predecessor,
73 dispatched_by: &self.dispatched_by,
74 skills: &self.skills,
75 policy: self.run_policy.reader().now(),
76 naming: self.naming,
77 opening: Some(self.opening),
78 effort: self.shape.effort,
79 agent: None,
80 }
81 }
82}
83
84impl Charter<'_> {
85 pub(crate) fn open(
92 &self,
93 ledger: &mut dyn Ledger,
94 now: &mut dyn FnMut() -> Result<TimeMs, AxError>,
95 ) -> Result<(), AxError> {
96 let pin = CheckpointCommitted::JobPinned {
97 job: self.job.clone(),
98 };
99 ledger.append(EventDraft {
100 run: RunId::CITY,
101 t: now()?,
102 who: Who::City.to_string(),
103 addr: Some(self.addr.clone()),
104 kind: EventKind::CheckpointCommitted,
105 data: Payload::of(&pin)?,
106 ig: false,
107 })?;
108 let started = RunStarted {
109 task: self.task.to_owned(),
110 goal: self.goal.to_owned(),
111 job: Some(self.job.clone()),
112 parent: self.parent,
113 predecessor: self.predecessor,
114 skills: self.skills.to_vec(),
115 dispatched_by: Some(self.dispatched_by.clone()),
116 policy: Some(self.policy),
117 naming: self.naming,
118 opening: self.opening,
119 effort: self.effort,
120 agent: self.agent.cloned(),
121 };
122 ledger.append(EventDraft {
123 run: self.run,
124 t: now()?,
125 who: Who::City.to_string(),
126 addr: Some(self.addr.clone()),
127 kind: EventKind::RunStarted,
128 data: Payload::of(&started)?,
129 ig: false,
130 })?;
131 Ok(())
132 }
133
134 pub(crate) fn close(
140 &self,
141 ledger: &mut dyn Ledger,
142 handoff: &Handoff,
143 completion: &Completion,
144 t: TimeMs,
145 ) -> Result<(), AxError> {
146 ledger.append(EventDraft {
147 run: self.run,
148 t,
149 who: self.who.to_owned(),
150 addr: None,
151 kind: EventKind::HandoffWritten,
152 data: handoff.payload()?,
153 ig: false,
154 })?;
155 let closing = t.value().checked_add(1).ok_or_else(|| {
156 AxError::failure(AxCode::InvalidArgs, "stamp run_frozen", "u64 overflow")
157 .with_recovery("check the clock the caller injected")
158 })?;
159 ledger.append(EventDraft {
160 run: self.run,
161 t: TimeMs::new(closing),
162 who: self.who.to_owned(),
163 addr: None,
164 kind: EventKind::RunFrozen,
165 data: Payload::of(&RunFrozen::of(completion))?,
166 ig: false,
167 })?;
168 Ok(())
169 }
170
171 pub(crate) fn line(&self, kind: EventKind, data: Payload, t: TimeMs) -> EventDraft {
173 EventDraft {
174 run: self.run,
175 t,
176 who: self.who.to_owned(),
177 addr: Some(self.addr.clone()),
178 kind,
179 data,
180 ig: false,
181 }
182 }
183}