Skip to main content

performance/
performance.rs

1//! Bounded public-API performance workloads; no lower Agent or service is built.
2//!
3//! Build once in release mode, then invoke the executable directly:
4//! `performance linear --root /absolute/new-directory`
5//! `performance seed-history --root /absolute/new-directory --rows 1000`
6//! `performance seed-history --root /absolute/another-new-directory --rows 10000`
7//! `performance reopen-history --root /absolute/seed-directory --page-size 128 --open-only`
8//! `performance reopen-history --root /absolute/seed-directory --page-size 128`
9//! `performance ready32 --root /absolute/new-directory`
10//! `performance map4096 --root /absolute/new-directory`
11//! `performance repeated100 --root /absolute/new-directory`
12//! `performance nested-cancel --root /absolute/new-directory`
13//! `performance delayed-observer --root /absolute/new-directory`
14//!
15//! Seed commands refuse existing roots. Reopen runs in a separate invocation;
16//! the consumer never opens a second App in its seed process. Its v2 manifest
17//! records the exact run occurrence; earlier seed manifests must be regenerated.
18//! An external runner
19//! records executable/source digests, toolchain, host hardware, cache ordering
20//! and process RSS. Internal timings exclude process startup and build time.
21
22use std::collections::{BTreeMap, BTreeSet};
23use std::error::Error;
24use std::fs::{self, File, OpenOptions};
25use std::io::{Read, Write};
26use std::num::NonZeroUsize;
27use std::panic::{AssertUnwindSafe, resume_unwind};
28use std::path::PathBuf;
29use std::pin::Pin;
30use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
31use std::sync::{Arc, Mutex};
32use std::task::{Context, Poll, Waker};
33use std::time::{Duration, Instant};
34
35use agents_kit::Agent;
36use app_kit::workflow::{
37    ActionBackend, ActionDeclaration, ActionEvent, ActionMode, ActionRequest, CheckpointKind,
38    ExecutionEvent, ExecutionOptions, RunId, RunSelector, RunSnapshot, RunStatus, StateChange,
39    WorkflowDefinition, WorkflowRun, WorkflowState,
40};
41use app_kit::{App, AppConfig, AppError, Shutdown, WorkspaceConfig, WorkspaceId};
42use futures_util::{FutureExt, Stream, StreamExt, stream};
43use serde_json::{Map, Value, json};
44use storage_kit::StateStore;
45use storage_kit::state::config::{LanceStateStoreConfig, StateStoreConfig};
46use tokio::sync::Notify;
47
48const WORKLOAD_BUDGET: Duration = Duration::from_secs(30 * 60);
49const CLEANUP_BUDGET: Duration = Duration::from_secs(2 * 60);
50const CLEANUP_OBSERVATION: Duration = Duration::from_secs(10);
51const NODE_DEADLINE_MS: u64 = 60_000;
52const PAGE_SIZE: usize = 128;
53const MANIFEST_SCHEMA: &str = "app-kit-performance/v2";
54
55struct Performance {
56    command: Command,
57    root: PathBuf,
58}
59
60enum Command {
61    Linear,
62    SeedHistory { rows: u64 },
63    ReopenHistory { open_only: bool },
64    Ready,
65    Map,
66    Repeated,
67    NestedCancel,
68    DelayedObserver,
69}
70
71impl Performance {
72    fn parse() -> Result<Self, Box<dyn Error + Send + Sync>> {
73        let mut args = std::env::args().skip(1);
74        let command = args
75            .next()
76            .ok_or("expected a documented performance command")?;
77        let mut root = None;
78        let mut rows = None;
79        let mut page_size = None;
80        let mut open_only = false;
81        while let Some(arg) = args.next() {
82            match arg.as_str() {
83                "--root" if root.is_none() => {
84                    root = Some(PathBuf::from(args.next().ok_or("--root needs a path")?));
85                }
86                "--rows" if rows.is_none() => {
87                    rows = Some(args.next().ok_or("--rows needs a count")?.parse::<u64>()?);
88                }
89                "--page-size" if page_size.is_none() => {
90                    page_size = Some(
91                        args.next()
92                            .ok_or("--page-size needs a count")?
93                            .parse::<usize>()?,
94                    );
95                }
96                "--open-only" if !open_only => open_only = true,
97                _ => return Err(format!("unknown or repeated argument: {arg}").into()),
98            }
99        }
100        let command = match (command.as_str(), rows, page_size, open_only) {
101            ("linear", None, None, false) => Command::Linear,
102            ("ready32", None, None, false) => Command::Ready,
103            ("map4096", None, None, false) => Command::Map,
104            ("repeated100", None, None, false) => Command::Repeated,
105            ("nested-cancel", None, None, false) => Command::NestedCancel,
106            ("delayed-observer", None, None, false) => Command::DelayedObserver,
107            ("seed-history", Some(rows @ (1_000 | 10_000)), None, false) => {
108                Command::SeedHistory { rows }
109            }
110            ("reopen-history", None, Some(PAGE_SIZE), open_only) => {
111                Command::ReopenHistory { open_only }
112            }
113            _ => {
114                return Err(
115                    "invalid command options; see the example's invocation documentation".into(),
116                );
117            }
118        };
119        let root = root.ok_or("--root is required")?;
120        if !root.is_absolute() {
121            return Err("--root must be absolute and its parent must already exist".into());
122        }
123        Ok(Self { command, root })
124    }
125
126    fn settings(actions: u64) -> Value {
127        json!({
128            "runtime":"tokio-current-thread", "backend":"LanceDB directory",
129            "storage_operation_timeout_ms":30_000,
130            "node_deadline_ms":NODE_DEADLINE_MS, "workload_timeout_seconds":WORKLOAD_BUDGET.as_secs(),
131            "cleanup_timeout_seconds":CLEANUP_BUDGET.as_secs(), "history_page_size":PAGE_SIZE,
132            "history_row_ceiling":actions * 16 + 16
133        })
134    }
135
136    fn definition(linear: bool, actions: u64) -> Result<(WorkflowDefinition, usize), AppError> {
137        let mut nodes = Vec::new();
138        let mut routes = Map::new();
139        for index in 0..if linear { actions } else { 1 } {
140            let node = if linear {
141                format!("n{index:04}")
142            } else {
143                "count".to_owned()
144            };
145            nodes.push(json!({"id":node,"deadline_ms":NODE_DEADLINE_MS,
146            "step":{"kind":"state","mutations":[
147                {"kind":"increment","target":"count","value":{"kind":"literal","value":1}}
148            ]}}));
149            if linear && index + 1 < actions {
150                routes.insert(
151                    node,
152                    json!({"mode":"first","branches":[
153                        {"target":{"kind":"node","id":format!("n{:04}",index + 1)}}
154                    ]}),
155                );
156            } else if !linear {
157                routes.insert(
158                    node,
159                    json!({"mode":"first","branches":[
160                        {"when":{"kind":"less_than","left":{"kind":"state","path":"count"},
161                            "right":{"kind":"literal","value":actions}},
162                            "target":{"kind":"node","id":"count"}},
163                        {"target":{"kind":"end"}}
164                    ]}),
165                );
166            }
167        }
168        let source = json!({
169            "schema":"app-kit.workflow/v2","id":"performance","revision":"r1",
170            "state":{"count":0},"required":["count"],"reducers":{"count":"reject_concurrent"},
171            "entry":if linear {"n0000"} else {"count"}, "nodes":nodes,"routes":routes
172        })
173        .to_string();
174        assert!(
175            source.len() <= 1_048_576,
176            "generated definition must fit the real source bound"
177        );
178        Ok((WorkflowDefinition::parse(&source)?, source.len()))
179    }
180
181    fn read_manifest(&self) -> Result<Value, Box<dyn Error + Send + Sync>> {
182        // Reopen must never silently create a replacement empty store. Reject
183        // links and missing directories before passing the caller-owned path to LanceDB.
184        for name in [".performance-root", "manifest.json"] {
185            if !fs::symlink_metadata(self.root.join(name))?
186                .file_type()
187                .is_file()
188            {
189                return Err(format!("performance root needs a regular {name} file").into());
190            }
191        }
192        let mut marker = String::new();
193        File::open(self.root.join(".performance-root"))?
194            .take(MANIFEST_SCHEMA.len() as u64 + 1)
195            .read_to_string(&mut marker)?;
196        if marker != MANIFEST_SCHEMA {
197            return Err("root is not owned by this performance consumer".into());
198        }
199        if !fs::symlink_metadata(self.root.join("state"))?
200            .file_type()
201            .is_dir()
202            || fs::read_dir(self.root.join("state"))?
203                .next()
204                .transpose()?
205                .is_none()
206        {
207            return Err("performance state directory is absent or empty".into());
208        }
209        let mut encoded = String::new();
210        File::open(self.root.join("manifest.json"))?
211            .take(16_385)
212            .read_to_string(&mut encoded)?;
213        if encoded.len() > 16_384 {
214            return Err("performance manifest exceeds its bounded size".into());
215        }
216        let manifest: Value = serde_json::from_str(&encoded)?;
217        if manifest["schema"] != MANIFEST_SCHEMA
218            || manifest["dataset"] != "history"
219            || manifest["cleanup_joined"] != true
220        {
221            return Err("unsupported performance manifest".into());
222        }
223        let actions = manifest["actions"]
224            .as_u64()
225            .ok_or("manifest has no action count")?;
226        let rows = manifest["retained_rows"]
227            .as_u64()
228            .ok_or("manifest has no retained row count")?;
229        if !matches!(rows, 1_000 | 10_000)
230            || actions != (rows - 4) / 3
231            || manifest["terminal_checkpoint"] != rows - 1
232            || manifest["settings"] != Self::settings(actions)
233        {
234            return Err("manifest workload or settings do not match this consumer".into());
235        }
236        Ok(manifest)
237    }
238
239    fn samples(mut samples: Vec<Duration>) -> Value {
240        samples.sort_unstable();
241        let length = samples.len();
242        if length == 0 {
243            return json!({"count":0,"p50_ns":null,"p95_ns":null,"max_ns":null});
244        }
245        json!({"count":length,
246            "p50_ns":samples[(length * 50).div_ceil(100) - 1].as_nanos(),
247            "p95_ns":samples[(length * 95).div_ceil(100) - 1].as_nanos(),
248            "max_ns":samples[length - 1].as_nanos(),
249            "percentile":"nearest rank: ceil(p * n), one-based"})
250    }
251
252    fn verify_snapshot(snapshot: &RunSnapshot, actions: u64) {
253        assert!(matches!(snapshot.status, RunStatus::Succeeded));
254        assert!(snapshot.interactions.is_empty());
255        assert_eq!(
256            snapshot.state.values(),
257            &Map::from_iter([("count".into(), json!(actions))])
258        );
259        assert_eq!(snapshot.last_action_ordinal, Some(actions - 1));
260        assert_eq!(snapshot.outcomes.len(), 1);
261        assert_eq!(snapshot.outcomes[0].ordinal, actions - 1);
262        assert!(snapshot.outcomes[0].result.is_empty());
263    }
264
265    async fn history(
266        &self,
267        run: &WorkflowRun<StateStore, Agent, WorkloadAction>,
268        actions: u64,
269        linear: bool,
270        terminal_sequence: u64,
271    ) -> Result<Value, AppError> {
272        let ceiling = actions * 16 + 16;
273        let mut cursor = None;
274        let mut prior_sequence = None;
275        let mut rows = 0_u64;
276        let mut observed_actions = 0_u64;
277        let mut initial = 0;
278        let mut terminal = 0;
279        let mut controls = 0;
280        let mut halts = 0;
281        let mut samples = Vec::new();
282        let started = Instant::now();
283        loop {
284            assert!(
285                samples.len() < ceiling.div_ceil(PAGE_SIZE as u64) as usize + 1,
286                "history page ceiling exhausted without cursor completion"
287            );
288            let page_started = Instant::now();
289            let page = run
290                .history(cursor, NonZeroUsize::new(PAGE_SIZE).unwrap())
291                .await?;
292            samples.push(page_started.elapsed());
293            assert!(page.checkpoints.len() <= PAGE_SIZE);
294            assert!(
295                !page.checkpoints.is_empty() || page.next.is_none(),
296                "history cursor made no progress"
297            );
298            for row in &page.checkpoints {
299                assert_eq!(&row.run, run.id());
300                assert!(prior_sequence.is_none_or(|prior| row.sequence > prior));
301                prior_sequence = Some(row.sequence);
302                rows += 1;
303                assert!(
304                    rows <= ceiling,
305                    "declared retained-row workload ceiling exceeded"
306                );
307                match row.kind {
308                    CheckpointKind::Initial => {
309                        initial += 1;
310                        assert_eq!(observed_actions, 0);
311                        assert_eq!(row.sequence, 0);
312                    }
313                    CheckpointKind::Action => {
314                        assert_eq!(row.outcomes.len(), 1);
315                        let outcome = &row.outcomes[0];
316                        assert_eq!(outcome.ordinal, observed_actions);
317                        assert_eq!(
318                            outcome.node,
319                            if linear {
320                                format!("n{observed_actions:04}")
321                            } else {
322                                "count".into()
323                            }
324                        );
325                        assert!(outcome.result.is_empty());
326                        observed_actions += 1;
327                        assert_eq!(row.action_ordinal, Some(observed_actions - 1));
328                    }
329                    CheckpointKind::Terminal => {
330                        terminal += 1;
331                        assert!(matches!(row.status, RunStatus::Succeeded));
332                    }
333                    CheckpointKind::Control => {
334                        assert!(row.outcomes.is_empty());
335                        controls += 1;
336                        if let RunStatus::Halted { node, result } = &row.status {
337                            assert!(!linear);
338                            assert_eq!(row.sequence, 4);
339                            assert_eq!(node, "count");
340                            assert_eq!(result, &Some(Map::new()));
341                            halts += 1;
342                        }
343                    }
344                    CheckpointKind::Failed { .. } => {
345                        panic!("workload history contains a failed action")
346                    }
347                }
348                assert_eq!(
349                    row.state.values(),
350                    &Map::from_iter([("count".into(), json!(observed_actions))])
351                );
352                if !linear && matches!(row.sequence, 4 | 5) {
353                    assert!(matches!(row.kind, CheckpointKind::Control));
354                    assert_eq!(observed_actions, 1);
355                    assert_eq!(row.action_ordinal, Some(0));
356                    assert_eq!(row.position.as_deref(), Some("count"));
357                    if row.sequence == 5 {
358                        assert!(matches!(row.status, RunStatus::Paused));
359                    }
360                }
361            }
362            cursor = page.next;
363            // Each complete Checkpoint/WorkflowState is released with this page.
364            if cursor.is_none() {
365                break;
366            }
367        }
368        assert_eq!(initial, 1);
369        assert_eq!(terminal, 1);
370        assert_eq!(observed_actions, actions);
371        assert_eq!(prior_sequence, Some(terminal_sequence));
372        if !linear {
373            assert_eq!(rows, actions * 3 + 4);
374            assert_eq!(terminal_sequence, rows - 1);
375            assert_eq!(controls, actions * 2 + 2);
376            assert_eq!(halts, 1);
377            assert_eq!(samples.len(), (rows as usize).div_ceil(PAGE_SIZE));
378        }
379        let elapsed = started.elapsed();
380        let first = samples.first().copied().unwrap_or_default();
381        let subsequent: Duration = samples.iter().skip(1).copied().sum();
382        Ok(
383            json!({"rows":rows,"action_rows":observed_actions,"pages":samples.len(),
384            "elapsed_ns":elapsed.as_nanos(),"first_page_ns":first.as_nanos(),
385            "subsequent_pages_total_ns":subsequent.as_nanos(),
386            "rows_per_second":rows as f64 / elapsed.as_secs_f64(),"page_latency":Self::samples(samples)}),
387        )
388    }
389
390    async fn seed(
391        &self,
392        app: &App<StateStore, Agent, WorkloadAction>,
393        actions: u64,
394        linear: bool,
395    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
396        let workspace = app
397            .create_workspace(WorkspaceConfig {
398                name: Some("performance consumer".into()),
399                root: self.root.join("workspace"),
400            })
401            .await?;
402        let workflow = workspace.workflow("performance".parse()?).await?;
403        let mut run = workflow.prepare(WorkflowState::default()).await?;
404        let mut execution = run
405            .execution(ExecutionOptions {
406                halt_after: if linear {
407                    Vec::new()
408                } else {
409                    vec!["count".into()]
410                },
411                ..ExecutionOptions::default()
412            })
413            .await?;
414        let mut samples = Vec::with_capacity(actions as usize);
415        let started = Instant::now();
416        for ordinal in 0..actions {
417            let step_started = Instant::now();
418            let event = execution.step().await?;
419            samples.push(step_started.elapsed());
420            let Some(ExecutionEvent::Committed { outcomes, .. }) = event else {
421                panic!("each serial workload step must commit one action");
422            };
423            assert_eq!(outcomes.len(), 1);
424            assert_eq!(outcomes[0].ordinal, ordinal);
425            assert_eq!(
426                outcomes[0].node,
427                if linear {
428                    format!("n{ordinal:04}")
429                } else {
430                    "count".into()
431                }
432            );
433            assert!(outcomes[0].result.is_empty());
434            if !linear && ordinal == 0 {
435                // One public halt and explicit resume add two control rows to
436                // Initial + three checkpoints per action + Terminal.
437                let halted = execution.finish().await?;
438                assert!(matches!(&halted.status, RunStatus::Halted { node, result }
439                    if node == "count" && result == &Some(Map::new())));
440                assert_eq!(halted.checkpoint, 4);
441                assert_eq!(
442                    halted.state.values(),
443                    &Map::from_iter([("count".into(), json!(1))])
444                );
445                assert_eq!(halted.last_action_ordinal, Some(0));
446                assert!(halted.outcomes == outcomes);
447                assert!(halted.interactions.is_empty());
448                execution = run.execution(ExecutionOptions::default()).await?;
449            }
450        }
451        let snapshot = execution.finish().await?;
452        Self::verify_snapshot(&snapshot, actions);
453        let execution_elapsed = started.elapsed();
454        let history = self
455            .history(&run, actions, linear, snapshot.checkpoint)
456            .await?;
457        if let Command::SeedHistory { rows } = self.command {
458            assert_eq!(history["rows"], rows);
459        }
460        Ok(
461            json!({"dataset":if linear {"linear"} else {"history"},"actions":actions,
462            "workspace":workspace.id().to_string(),"run":run.id().to_string(),
463            "occurrence":snapshot.occurrence,
464            "expected_state":snapshot.state.values(),"last_action_ordinal":snapshot.last_action_ordinal,
465            "terminal_checkpoint":snapshot.checkpoint,"retained_rows":history["rows"],
466            "execution_ns":execution_elapsed.as_nanos(),
467            "actions_per_second":actions as f64 / execution_elapsed.as_secs_f64(),
468            "step_latency":Self::samples(samples),"history":history}),
469        )
470    }
471
472    async fn reopen(
473        &self,
474        app: &App<StateStore, Agent, WorkloadAction>,
475        manifest: &Value,
476        actions: u64,
477        open_only: bool,
478    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
479        let started = Instant::now();
480        let workspace: WorkspaceId = manifest["workspace"]
481            .as_str()
482            .ok_or("missing workspace ID")?
483            .parse()?;
484        let run_id: RunId = manifest["run"].as_str().ok_or("missing run ID")?.parse()?;
485        let occurrence = manifest["occurrence"]
486            .as_str()
487            .ok_or("missing run occurrence")?
488            .to_owned();
489        let workspace = app.workspace(workspace).await?;
490        let workflow = workspace.workflow("performance".parse()?).await?;
491        let run = workflow
492            .open_run(RunSelector::Exact {
493                id: run_id,
494                occurrence: occurrence.clone(),
495            })
496            .await?;
497        let snapshot = run.snapshot().await?;
498        Self::verify_snapshot(&snapshot, actions);
499        assert_eq!(snapshot.occurrence, occurrence);
500        assert_eq!(json!(snapshot.checkpoint), manifest["terminal_checkpoint"]);
501        assert_eq!(json!(snapshot.state.values()), manifest["expected_state"]);
502        assert_eq!(
503            json!(snapshot.last_action_ordinal),
504            manifest["last_action_ordinal"]
505        );
506        let lookup = started.elapsed();
507        if open_only {
508            return Ok(
509                json!({"dataset":"history","actions":actions,"mode":"open-only",
510                "lookup_and_snapshot_ns":lookup.as_nanos(),
511                "seed_retained_rows":manifest["retained_rows"],"observed_history_rows":null}),
512            );
513        }
514        let history = self
515            .history(&run, actions, false, snapshot.checkpoint)
516            .await?;
517        assert_eq!(history["rows"], manifest["retained_rows"]);
518        Ok(
519            json!({"dataset":"history","actions":actions,"mode":"full-history",
520            "lookup_and_snapshot_ns":lookup.as_nanos(),"history":history}),
521        )
522    }
523
524    fn definitions(&self, actions: u64) -> Result<(Vec<WorkflowDefinition>, usize), AppError> {
525        if matches!(
526            self.command,
527            Command::Linear | Command::SeedHistory { .. } | Command::ReopenHistory { .. }
528        ) {
529            let (definition, bytes) =
530                Self::definition(matches!(self.command, Command::Linear), actions)?;
531            return Ok((vec![definition], bytes));
532        }
533        let leaf = json!({
534            "schema":"app-kit.workflow/v2","id":"performance-leaf","revision":"r1",
535            "state":{"value":0,"result":0},"required":["value","result"],
536            "reducers":{"value":"reject_concurrent","result":"reject_concurrent"},
537            "entry":"work","nodes":[{"id":"work","deadline_ms":NODE_DEADLINE_MS,
538                "step":{"kind":"action","action":"performance-action","revision":"r1"}}],"routes":{}
539        });
540        let documents = match self.command {
541            Command::Ready => {
542                let mut nodes = vec![json!({"id":"fork","step":{"kind":"state","mutations":[]}})];
543                let mut branches = Vec::new();
544                for index in 0..32 {
545                    let node = format!("n{index:02}");
546                    nodes.push(json!({"id":node,"deadline_ms":NODE_DEADLINE_MS,
547                        "step":{"kind":"action","action":"performance-action","revision":"r1"}}));
548                    branches.push(json!({"target":{"kind":"node","id":node}}));
549                }
550                vec![json!({
551                    "schema":"app-kit.workflow/v2","id":"performance","revision":"r1",
552                    "state":{"value":0,"result":0},"required":["value","result"],
553                    "reducers":{"value":"reject_concurrent","result":"collect"},
554                    "entry":"fork","nodes":nodes,
555                    "routes":{"fork":{"mode":"broadcast","branches":branches}}
556                })]
557            }
558            Command::Map | Command::NestedCancel => {
559                let nested = matches!(self.command, Command::NestedCancel);
560                let items = if nested { 2 } else { 4_096 };
561                let mut documents = vec![
562                    json!({
563                        "schema":"app-kit.workflow/v2","id":"performance","revision":"r1",
564                        "state":{"value":0,"result":0},"required":["value","result"],
565                        "reducers":{"value":"reject_concurrent","result":"sum_integer"},
566                        "entry":"map","nodes":[{"id":"map","deadline_ms":if nested {NODE_DEADLINE_MS} else {WORKLOAD_BUDGET.as_millis() as u64},
567                            "step":{"kind":"map","workflow":if nested {"performance-mid"} else {"performance-leaf"},
568                            "items":{"kind":"literal","value":(0..items).collect::<Vec<_>>()},
569                            "input_key":"value","max_parallel":if nested {2} else {8},
570                            "reductions":[{"source":"result","target":"result","reducer":"sum_integer"}]}}],"routes":{}
571                    }),
572                    leaf,
573                ];
574                if nested {
575                    documents.push(json!({
576                        "schema":"app-kit.workflow/v2","id":"performance-mid","revision":"r1",
577                        "state":{"value":0,"result":0},"required":["value","result"],
578                        "reducers":{"value":"reject_concurrent","result":"sum_integer"},
579                        "entry":"map","nodes":[{"id":"map","deadline_ms":NODE_DEADLINE_MS,
580                            "step":{"kind":"map","workflow":"performance-leaf",
581                            "items":{"kind":"literal","value":(0..8).collect::<Vec<_>>()},
582                            "input_key":"value","max_parallel":8,
583                            "reductions":[{"source":"result","target":"result","reducer":"sum_integer"}]}}],"routes":{}
584                    }));
585                }
586                documents
587            }
588            Command::Repeated | Command::DelayedObserver => vec![leaf],
589            Command::Linear | Command::SeedHistory { .. } | Command::ReopenHistory { .. } => {
590                unreachable!()
591            }
592        };
593        let mut bytes = 0;
594        let mut definitions = Vec::with_capacity(documents.len());
595        for document in documents {
596            let source = document.to_string();
597            assert!(source.len() <= 1_048_576);
598            bytes += source.len();
599            definitions.push(WorkflowDefinition::parse(&source)?);
600        }
601        Ok((definitions, bytes))
602    }
603
604    async fn ready(
605        &self,
606        app: &App<StateStore, Agent, WorkloadAction>,
607        probe: &WorkloadProbe,
608    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
609        let workspace = app
610            .create_workspace(WorkspaceConfig {
611                name: None,
612                root: self.root.join("workspace"),
613            })
614            .await?;
615        let workflow = workspace.workflow("performance".parse()?).await?;
616        let mut waves = Vec::with_capacity(32);
617        let mut releases = Vec::with_capacity(32 * 31);
618        let mut barriers = Vec::with_capacity(32);
619        let started = Instant::now();
620        for permutation in 0..32 {
621            probe.assert_idle();
622            let mut run = workflow.prepare(WorkflowState::default()).await?;
623            let observer = workflow
624                .open_run(RunSelector::Latest(run.id().clone()))
625                .await?;
626            let mut execution = run.execution(ExecutionOptions::default()).await?;
627            let Some(ExecutionEvent::Committed { outcomes, .. }) = execution.step().await? else {
628                panic!("the native fork must commit before the ready wave");
629            };
630            assert_eq!(outcomes.len(), 1);
631            assert_eq!(
632                (outcomes[0].node.as_str(), outcomes[0].ordinal),
633                ("fork", 0)
634            );
635            let wave = Instant::now();
636            let mut finish = Box::pin(execution.finish());
637            tokio::select! {
638                _ = probe.wait_for(&probe.constructed, (permutation + 1) * 32) => {}
639                result = &mut finish => panic!("gated ready wave finished before admission: {}", result.is_ok()),
640            }
641            assert_eq!(probe.active.load(Ordering::SeqCst), 32);
642            let order = (0..32)
643                .map(|offset| (permutation + 31 - offset) % 32)
644                .collect::<Vec<_>>();
645            for (released, index) in order.iter().take(31).enumerate() {
646                let releasing = Instant::now();
647                probe.release(*index);
648                tokio::select! {
649                    _ = probe.wait_for(&probe.completed, permutation * 32 + released + 1) => {}
650                    result = &mut finish => panic!("a partial ready wave committed: {}", result.is_ok()),
651                }
652                releases.push(releasing.elapsed());
653                let visible = observer.snapshot().await?;
654                assert_eq!(
655                    visible.state.values()["result"],
656                    0,
657                    "staged siblings cannot expose a partial barrier"
658                );
659                assert_eq!(visible.last_action_ordinal, Some(0));
660            }
661            let barrier = Instant::now();
662            probe.release(order[31]);
663            let snapshot = finish.await?;
664            barriers.push(barrier.elapsed());
665            waves.push(wave.elapsed());
666            assert!(matches!(snapshot.status, RunStatus::Succeeded));
667            assert!(snapshot.interactions.is_empty());
668            assert_eq!(
669                snapshot.state.values()["result"],
670                json!((1..=32).collect::<Vec<_>>())
671            );
672            assert_eq!(snapshot.last_action_ordinal, Some(32));
673            assert_eq!(snapshot.outcomes.len(), 32);
674            for (index, outcome) in snapshot.outcomes.iter().enumerate() {
675                assert_eq!(outcome.node, format!("n{index:02}"));
676                assert_eq!(outcome.ordinal, index as u64 + 1);
677                assert_eq!(
678                    outcome.result,
679                    Map::from_iter([("value".into(), json!(index + 1))])
680                );
681            }
682            assert_eq!(std::mem::take(&mut *probe.order.lock().unwrap()), order);
683            assert_eq!(
684                probe.completed.load(Ordering::SeqCst),
685                (permutation + 1) * 32
686            );
687            probe.assert_idle();
688        }
689        assert_eq!(probe.peak.load(Ordering::SeqCst), 32);
690        let elapsed = started.elapsed();
691        Ok(
692            json!({"dataset":"ready32","permutations":32,"ready_actions_per_wave":32,
693            "caller_action_commits":1024,"native_fork_commits":32,
694            "execution_ns":elapsed.as_nanos(),"caller_actions_per_second":1024.0 / elapsed.as_secs_f64(),
695            "wave_latency_including_snapshot_probes":Self::samples(waves),
696            "release_to_source_completion_latency":Self::samples(releases),
697            "last_release_to_committed_barrier_latency":Self::samples(barriers)}),
698        )
699    }
700
701    async fn mapped(
702        &self,
703        app: &App<StateStore, Agent, WorkloadAction>,
704        probe: &WorkloadProbe,
705    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
706        let workspace = app
707            .create_workspace(WorkspaceConfig {
708                name: None,
709                root: self.root.join("workspace"),
710            })
711            .await?;
712        let workflow = workspace.workflow("performance".parse()?).await?;
713        let mut run = workflow.prepare(WorkflowState::default()).await?;
714        let observer = workflow
715            .open_run(RunSelector::Latest(run.id().clone()))
716            .await?;
717        let started = Instant::now();
718        let mut finish = Box::pin(run.execution(ExecutionOptions::default()).await?.finish());
719        tokio::select! {
720            _ = probe.wait_for(&probe.constructed, 8) => {}
721            result = &mut finish => panic!("map finished before its first eight blocked sources: {}", result.is_ok()),
722        }
723        assert_eq!(probe.active.load(Ordering::SeqCst), 8);
724        assert_eq!(probe.constructed.load(Ordering::SeqCst), 8);
725        let unchanged = observer.snapshot().await?;
726        assert_eq!(unchanged.state.values()["result"], 0);
727        assert!(unchanged.last_action_ordinal.is_none());
728        probe.release_all();
729        let snapshot = finish.await?;
730        let elapsed = started.elapsed();
731        assert!(matches!(snapshot.status, RunStatus::Succeeded));
732        assert!(snapshot.interactions.is_empty());
733        assert_eq!(snapshot.state.values()["result"], 4_096_u64 * 4_097 / 2);
734        assert_eq!(snapshot.last_action_ordinal, Some(0));
735        assert_eq!(snapshot.outcomes.len(), 1);
736        assert_eq!(snapshot.outcomes[0].node, "map");
737        assert_eq!(probe.constructed.load(Ordering::SeqCst), 4_096);
738        assert_eq!(probe.completed.load(Ordering::SeqCst), 4_096);
739        assert_eq!(probe.peak.load(Ordering::SeqCst), 8);
740        probe.assert_idle();
741        let child = workspace.workflow("performance-leaf".parse()?).await?;
742        let mut cursor = None;
743        let mut values = BTreeSet::new();
744        let verifying = Instant::now();
745        loop {
746            let page = child
747                .list_runs(cursor, NonZeroUsize::new(PAGE_SIZE).unwrap())
748                .await?;
749            assert!(page.len() <= PAGE_SIZE);
750            if page.is_empty() {
751                break;
752            }
753            for row in &page {
754                assert!(matches!(row.status, RunStatus::Succeeded));
755                let value = row.state.values()["value"].as_u64().unwrap();
756                assert!(
757                    value < 4_096 && values.insert(value),
758                    "every mapped input has exactly one retained child"
759                );
760                assert_eq!(row.state.values()["result"], value + 1);
761                assert_eq!(row.last_action_ordinal, Some(0));
762                assert_eq!(row.outcomes.len(), 1);
763                assert_eq!(row.outcomes[0].node, "work");
764            }
765            let last = page.last().unwrap();
766            cursor = Some(RunSelector::Exact {
767                id: last.id.clone(),
768                occurrence: last.occurrence.clone(),
769            });
770            assert!(values.len() <= 4_096);
771        }
772        assert_eq!(values.len(), 4_096);
773        Ok(json!({"dataset":"map4096","items":4096,"max_parallel":8,
774            "parent_node_deadline_ms":WORKLOAD_BUDGET.as_millis(),
775            "execution_ns":elapsed.as_nanos(),"child_actions_per_second":4096.0 / elapsed.as_secs_f64(),
776            "map_completion_latency":Self::samples(vec![elapsed]),
777            "child_inventory_verification_ns":verifying.elapsed().as_nanos(),"verified_children":values.len()}))
778    }
779
780    async fn repeated(
781        &self,
782        app: &App<StateStore, Agent, WorkloadAction>,
783        probe: &WorkloadProbe,
784    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
785        let workspace = app
786            .create_workspace(WorkspaceConfig {
787                name: None,
788                root: self.root.join("workspace"),
789            })
790            .await?;
791        let workflow = workspace.workflow("performance-leaf".parse()?).await?;
792        let started = Instant::now();
793        // Admit one run at a time, then directly poll at most 16 original
794        // executions together. No consumer task is spawned or detached.
795        let mut runs = std::pin::pin!(
796            stream::iter(0..100_u64)
797                .then(|value| {
798                    let workflow = &workflow;
799                    async move {
800                        let started = Instant::now();
801                        let run = workflow
802                            .prepare(WorkflowState::new(Map::from_iter([(
803                                "value".into(),
804                                json!(value),
805                            )]))?)
806                            .await?;
807                        Ok::<_, AppError>((value, run, started))
808                    }
809                })
810                .map(|prepared| async move {
811                    let (value, mut run, started) = prepared?;
812                    let snapshot = run
813                        .execution(ExecutionOptions::default())
814                        .await?
815                        .finish()
816                        .await?;
817                    assert!(matches!(snapshot.status, RunStatus::Succeeded));
818                    assert!(snapshot.interactions.is_empty());
819                    assert_eq!(snapshot.state.values()["value"], value);
820                    assert_eq!(snapshot.state.values()["result"], value + 1);
821                    assert_eq!(snapshot.last_action_ordinal, Some(0));
822                    assert_eq!(snapshot.outcomes.len(), 1);
823                    Ok::<_, AppError>((run.id().clone(), started.elapsed()))
824                })
825                .buffer_unordered(16)
826        );
827        tokio::select! {
828            _ = probe.wait_for(&probe.constructed, 16) => {}
829            result = runs.next() => panic!(
830                "run finished before the first 16 blocked sources: {:?}",
831                result.map(|result| result.map(|_| ())),
832            ),
833        }
834        assert_eq!(probe.active.load(Ordering::SeqCst), 16);
835        assert_eq!(probe.constructed.load(Ordering::SeqCst), 16);
836        probe.release_all();
837        let mut ids = BTreeSet::new();
838        let mut samples = Vec::with_capacity(100);
839        while let Some(result) = runs.next().await {
840            let (id, elapsed) = result?;
841            assert!(ids.insert(id));
842            samples.push(elapsed);
843        }
844        assert_eq!(ids.len(), 100);
845        assert_eq!(probe.constructed.load(Ordering::SeqCst), 100);
846        assert_eq!(probe.completed.load(Ordering::SeqCst), 100);
847        assert_eq!(probe.peak.load(Ordering::SeqCst), 16);
848        probe.assert_idle();
849        let rows = workflow
850            .list_runs(None, NonZeroUsize::new(128).unwrap())
851            .await?;
852        assert_eq!(rows.len(), 100);
853        assert_eq!(
854            rows.iter()
855                .map(|row| row.id.clone())
856                .collect::<BTreeSet<_>>(),
857            ids
858        );
859        assert!(
860            rows.iter()
861                .all(|row| matches!(row.status, RunStatus::Succeeded))
862        );
863        let elapsed = started.elapsed();
864        Ok(
865            json!({"dataset":"repeated100","runs":100,"caller_in_flight_limit":16,"admission":"sequential",
866            "production_active_limit":"unchanged; this measures only the caller's 16-journey envelope",
867            "execution_ns":elapsed.as_nanos(),"runs_per_second":100.0 / elapsed.as_secs_f64(),
868            "run_latency_including_admission":Self::samples(samples),"indefinite_stability_proof":false}),
869        )
870    }
871
872    async fn nested_cancel(
873        &self,
874        app: &App<StateStore, Agent, WorkloadAction>,
875        probe: &WorkloadProbe,
876    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
877        let workspace = app
878            .create_workspace(WorkspaceConfig {
879                name: None,
880                root: self.root.join("workspace"),
881            })
882            .await?;
883        let workflow = workspace.workflow("performance".parse()?).await?;
884        let run = workflow.start(ExecutionOptions::default()).await?;
885        tokio::select! {
886            _ = probe.wait_for(&probe.constructed, 16) => {}
887            result = run.wait() => panic!("nested run ended before its held leaf sources: {}", result.is_ok()),
888        }
889        assert_eq!(probe.active.load(Ordering::SeqCst), 16);
890        let cancelling = Instant::now();
891        let snapshot = tokio::time::timeout(Duration::from_secs(30), async {
892            loop {
893                let before = run.snapshot().await?;
894                assert_eq!(before.state.values()["result"], 0);
895                assert!(before.outcomes.is_empty() && before.last_action_ordinal.is_none());
896                match run.cancel(before.checkpoint).await {
897                    Ok(_) => break,
898                    Err(AppError::Conflict(_)) => tokio::task::yield_now().await,
899                    Err(error) => return Err(error),
900                }
901            }
902            run.wait().await
903        })
904        .await
905        .map_err(|_| {
906            AppError::Timeout("nested cancellation exceeded its declared 30-second grace".into())
907        })??;
908        let elapsed = cancelling.elapsed();
909        assert!(matches!(snapshot.status, RunStatus::Cancelled));
910        assert!(snapshot.interactions.is_empty() && snapshot.outcomes.is_empty());
911        assert!(snapshot.last_action_ordinal.is_none());
912        assert_eq!(snapshot.state.values()["result"], 0);
913        assert_eq!(probe.constructed.load(Ordering::SeqCst), 16);
914        assert_eq!(probe.completed.load(Ordering::SeqCst), 0);
915        probe.assert_idle();
916        for (id, count) in [
917            ("performance", 1),
918            ("performance-mid", 2),
919            ("performance-leaf", 16),
920        ] {
921            let child = workspace.workflow(id.parse()?).await?;
922            let rows = child
923                .list_runs(None, NonZeroUsize::new(128).unwrap())
924                .await?;
925            assert_eq!(rows.len(), count);
926            for row in rows {
927                assert!(matches!(row.status, RunStatus::Cancelled));
928                assert!(row.outcomes.is_empty() && row.last_action_ordinal.is_none());
929                assert_eq!(row.state.values()["result"], 0);
930            }
931        }
932        Ok(
933            json!({"dataset":"nested-cancel","depth":2,"intermediate_children":2,"leaf_children":16,
934            "cooperative_cancel_grace_ms":30_000,"cancellation_latency":Self::samples(vec![elapsed]),
935            "source_replays":0,"caller_sources_dropped":16,"agent_unknown_replay":"not applicable: no Agent attempt"}),
936        )
937    }
938
939    async fn delayed_observer(
940        &self,
941        app: &App<StateStore, Agent, WorkloadAction>,
942        probe: &WorkloadProbe,
943    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
944        let workspace = app
945            .create_workspace(WorkspaceConfig {
946                name: None,
947                root: self.root.join("workspace"),
948            })
949            .await?;
950        let workflow = workspace.workflow("performance-leaf".parse()?).await?;
951        let run = workflow.start(ExecutionOptions::default()).await?;
952        let observer = workflow
953            .open_run(RunSelector::Latest(run.id().clone()))
954            .await?;
955        // This public observation is deliberately never polled while the source
956        // produces its 256 partials and commits. It owns no execution work.
957        let delayed = observer.wait();
958        let produced = run.wait().await?;
959        assert!(matches!(produced.status, RunStatus::Succeeded));
960        assert_eq!(probe.completed.load(Ordering::SeqCst), 1);
961        probe.assert_idle();
962        tokio::time::sleep(Duration::from_secs(2)).await;
963        let observing = Instant::now();
964        let snapshot = delayed.await?;
965        let elapsed = observing.elapsed();
966        assert!(matches!(snapshot.status, RunStatus::Succeeded));
967        assert_eq!(snapshot.checkpoint, produced.checkpoint);
968        assert_eq!(snapshot.state.values()["result"], 1);
969        assert_eq!(snapshot.last_action_ordinal, Some(0));
970        assert_eq!(snapshot.outcomes.len(), 1);
971        assert_eq!(
972            snapshot.outcomes[0].result,
973            Map::from_iter([("value".into(), json!(1))])
974        );
975        assert_eq!(probe.constructed.load(Ordering::SeqCst), 1);
976        assert_eq!(probe.partials.load(Ordering::SeqCst), 256);
977        probe.assert_idle();
978        let terminal = run.snapshot().await?;
979        assert_eq!(terminal.checkpoint, snapshot.checkpoint);
980        assert_eq!(terminal.state, snapshot.state);
981        let mut cursor = None;
982        let mut actions = 0;
983        let mut rows = 0;
984        loop {
985            let page = run
986                .history(cursor, NonZeroUsize::new(PAGE_SIZE).unwrap())
987                .await?;
988            for row in &page.checkpoints {
989                rows += 1;
990                assert!(rows <= 32);
991                if matches!(row.kind, CheckpointKind::Action) {
992                    actions += 1;
993                    assert_eq!(row.action_ordinal, Some(0));
994                    assert_eq!(row.outcomes.len(), 1);
995                }
996            }
997            cursor = page.next;
998            if cursor.is_none() {
999                break;
1000            }
1001        }
1002        assert_eq!(
1003            actions, 1,
1004            "partials cannot become extra durable action commits"
1005        );
1006        Ok(
1007            json!({"dataset":"delayed-observer","unobserved_partial_events":256,"delay_after_terminal_confirmation_ms":2_000,
1008            "observation_latency":Self::samples(vec![elapsed]),"retained_rows":rows,
1009            "memory_scope":"external process RSS; this consumer retains no partial payloads"}),
1010        )
1011    }
1012
1013    async fn close(
1014        app: &mut App<StateStore, Agent, WorkloadAction>,
1015        success: bool,
1016    ) -> Result<(), AppError> {
1017        let deadline = Instant::now() + CLEANUP_BUDGET;
1018        let mut first_failure = None;
1019        loop {
1020            let remaining = deadline.saturating_duration_since(Instant::now());
1021            if remaining.is_zero() {
1022                return Err(first_failure.unwrap_or_else(|| {
1023                    AppError::Timeout("performance cleanup budget exhausted".into())
1024                }));
1025            }
1026            let policy = if success {
1027                Shutdown::Drain {
1028                    timeout: CLEANUP_OBSERVATION,
1029                }
1030            } else {
1031                Shutdown::CancelAndDrain {
1032                    timeout: CLEANUP_OBSERVATION,
1033                }
1034            };
1035            let result =
1036                tokio::time::timeout(remaining.min(CLEANUP_OBSERVATION), app.shutdown(policy))
1037                    .await;
1038            match result {
1039                Ok(Ok(())) => return first_failure.map_or(Ok(()), Err),
1040                Ok(Err(error @ AppError::Timeout(_))) => {
1041                    first_failure.get_or_insert(error);
1042                }
1043                Err(_) => {
1044                    first_failure.get_or_insert_with(|| {
1045                        AppError::Timeout("performance cleanup observation timed out".into())
1046                    });
1047                }
1048                Ok(Err(error)) => return Err(first_failure.unwrap_or(error)),
1049            }
1050            // A timed-out observer reattaches to its original finalizer.
1051        }
1052    }
1053
1054    async fn run(mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
1055        let manifest = if matches!(self.command, Command::ReopenHistory { .. }) {
1056            self.root = self.root.canonicalize()?;
1057            Some(self.read_manifest()?)
1058        } else {
1059            fs::create_dir(&self.root)?;
1060            self.root = self.root.canonicalize()?;
1061            fs::create_dir(self.root.join("workspace"))?;
1062            let mut marker = OpenOptions::new()
1063                .write(true)
1064                .create_new(true)
1065                .open(self.root.join(".performance-root"))?;
1066            marker.write_all(MANIFEST_SCHEMA.as_bytes())?;
1067            marker.sync_all()?;
1068            None
1069        };
1070        let actions = match self.command {
1071            Command::Linear => 1_000,
1072            Command::SeedHistory { rows } => (rows - 4) / 3,
1073            Command::Ready => 32 * 32,
1074            Command::Map => 4_096,
1075            Command::Repeated => 100,
1076            Command::NestedCancel => 16,
1077            Command::DelayedObserver => 1,
1078            Command::ReopenHistory { .. } => {
1079                manifest.as_ref().unwrap()["actions"].as_u64().unwrap()
1080            }
1081        };
1082        let linear = matches!(self.command, Command::Linear);
1083        let (definitions, definition_bytes) = self.definitions(actions)?;
1084        let probe = match self.command {
1085            Command::Ready => Some(WorkloadProbe::new(SourceMode::Permuted, 1_024)),
1086            Command::Map | Command::Repeated => {
1087                Some(WorkloadProbe::new(SourceMode::Parallel, actions as usize))
1088            }
1089            Command::NestedCancel => Some(WorkloadProbe::new(SourceMode::Held, 16)),
1090            Command::DelayedObserver => Some(WorkloadProbe::new(SourceMode::Partials, 1)),
1091            Command::Linear | Command::SeedHistory { .. } | Command::ReopenHistory { .. } => None,
1092        };
1093        if let Some(manifest) = &manifest {
1094            assert_eq!(manifest["definition_bytes"], json!(definition_bytes));
1095        }
1096        let mut app = None;
1097        let started = Instant::now();
1098        let observed = AssertUnwindSafe(tokio::time::timeout(WORKLOAD_BUDGET, async {
1099            let connecting = Instant::now();
1100            let config = LanceStateStoreConfig::directory(self.root.join("state"))
1101                .with_operation_timeout(Duration::from_secs(30))?;
1102            let store = StateStore::connect(StateStoreConfig::Lance(config)).await?;
1103            let connect = connecting.elapsed();
1104            let opening = Instant::now();
1105            app = Some(
1106                App::open(
1107                    AppConfig::<_, Agent>::new(store, Vec::new(), definitions).with_actions(
1108                        probe
1109                            .as_ref()
1110                            .map(WorkloadAction::new)
1111                            .into_iter()
1112                            .collect(),
1113                    ),
1114                )
1115                .await?,
1116            );
1117            let open = opening.elapsed();
1118            let mut result = match self.command {
1119                Command::Linear | Command::SeedHistory { .. } => {
1120                    self.seed(app.as_ref().unwrap(), actions, linear).await?
1121                }
1122                Command::Ready => {
1123                    self.ready(app.as_ref().unwrap(), probe.as_ref().unwrap())
1124                        .await?
1125                }
1126                Command::Map => {
1127                    self.mapped(app.as_ref().unwrap(), probe.as_ref().unwrap())
1128                        .await?
1129                }
1130                Command::Repeated => {
1131                    self.repeated(app.as_ref().unwrap(), probe.as_ref().unwrap())
1132                        .await?
1133                }
1134                Command::NestedCancel => {
1135                    self.nested_cancel(app.as_ref().unwrap(), probe.as_ref().unwrap())
1136                        .await?
1137                }
1138                Command::DelayedObserver => {
1139                    self.delayed_observer(app.as_ref().unwrap(), probe.as_ref().unwrap())
1140                        .await?
1141                }
1142                Command::ReopenHistory { open_only } => {
1143                    self.reopen(
1144                        app.as_ref().unwrap(),
1145                        manifest.as_ref().unwrap(),
1146                        actions,
1147                        open_only,
1148                    )
1149                    .await?
1150                }
1151            };
1152            result["store_connect_ns"] = json!(connect.as_nanos());
1153            result["app_open_ns"] = json!(open.as_nanos());
1154            result["workload_elapsed_ns"] = json!(started.elapsed().as_nanos());
1155            Ok::<_, Box<dyn Error + Send + Sync>>(result)
1156        }))
1157        .catch_unwind()
1158        .await;
1159        let success = matches!(&observed, Ok(Ok(Ok(_))));
1160        let closing = Instant::now();
1161        let cleanup = if let Some(mut app) = app.take() {
1162            let closed = AssertUnwindSafe(Self::close(&mut app, success))
1163                .catch_unwind()
1164                .await;
1165            drop(app);
1166            Some(closed)
1167        } else {
1168            None
1169        };
1170        if !success {
1171            eprintln!(
1172                "performance workload failed; cleanup completed={}",
1173                matches!(&cleanup, Some(Ok(Ok(()))))
1174            );
1175        }
1176        let mut result = match observed {
1177            Ok(Ok(result)) => result?,
1178            Ok(Err(_)) => {
1179                return Err(
1180                    AppError::Timeout("performance workload budget exhausted".into()).into(),
1181                );
1182            }
1183            Err(panic) => resume_unwind(panic),
1184        };
1185        match cleanup {
1186            Some(Ok(result)) => result?,
1187            Some(Err(panic)) => resume_unwind(panic),
1188            None => return Err("successful workload did not retain its App cleanup owner".into()),
1189        }
1190        // All run/workflow/App owners and the caller-created store have dropped.
1191        // A cleanup timeout remains a failure even if reattachment later joined.
1192        result["schema"] = json!(MANIFEST_SCHEMA);
1193        result["settings"] = Self::settings(actions);
1194        if let Some(probe) = &probe {
1195            probe.assert_idle();
1196            result["caller_sources"] = probe.report();
1197            result["settings"]
1198                .as_object_mut()
1199                .unwrap()
1200                .remove("history_row_ceiling");
1201            result["settings"]["private_task_counts"] =
1202                json!("not exposed; App shutdown proves joined ownership");
1203            result["settings"]["lower_agents_and_tool_handlers"] = json!("none constructed");
1204        }
1205        result["definition_bytes"] = json!(definition_bytes);
1206        result["process_id"] = json!(std::process::id());
1207        result["os"] = json!(std::env::consts::OS);
1208        result["architecture"] = json!(std::env::consts::ARCH);
1209        result["package_version"] = json!(env!("CARGO_PKG_VERSION"));
1210        result["cleanup_joined"] = json!(true);
1211        result["cleanup_ns"] = json!(closing.elapsed().as_nanos());
1212        let encoded = serde_json::to_vec(&result)?;
1213        assert!(
1214            encoded.len() <= 16_384,
1215            "result stays within the manifest bound"
1216        );
1217        if matches!(self.command, Command::SeedHistory { .. }) {
1218            let mut file = OpenOptions::new()
1219                .write(true)
1220                .create_new(true)
1221                .open(self.root.join("manifest.json"))?;
1222            file.write_all(&encoded)?;
1223            file.sync_all()?;
1224        }
1225        println!("{}", std::str::from_utf8(&encoded)?);
1226        Ok(())
1227    }
1228}
1229
1230// These counters observe only this consumer's concrete sources. They expose no
1231// runtime internals and do not claim to count App tasks or lower tool handlers.
1232#[derive(Clone, Copy)]
1233enum SourceMode {
1234    Permuted,
1235    Parallel,
1236    Held,
1237    Partials,
1238}
1239
1240struct WorkloadProbe {
1241    mode: SourceMode,
1242    expected: usize,
1243    open: AtomicBool,
1244    constructed: AtomicUsize,
1245    active: AtomicUsize,
1246    peak: AtomicUsize,
1247    completed: AtomicUsize,
1248    dropped: AtomicUsize,
1249    partials: AtomicUsize,
1250    permitted: Mutex<BTreeSet<usize>>,
1251    wakers: Mutex<BTreeMap<usize, Waker>>,
1252    order: Mutex<Vec<usize>>,
1253    lifetimes: Mutex<Vec<Duration>>,
1254    changed: Notify,
1255}
1256
1257impl WorkloadProbe {
1258    fn new(mode: SourceMode, expected: usize) -> Arc<Self> {
1259        Arc::new(Self {
1260            mode,
1261            expected,
1262            open: AtomicBool::new(false),
1263            constructed: AtomicUsize::new(0),
1264            active: AtomicUsize::new(0),
1265            peak: AtomicUsize::new(0),
1266            completed: AtomicUsize::new(0),
1267            dropped: AtomicUsize::new(0),
1268            partials: AtomicUsize::new(0),
1269            permitted: Mutex::new(BTreeSet::new()),
1270            wakers: Mutex::new(BTreeMap::new()),
1271            order: Mutex::new(Vec::new()),
1272            lifetimes: Mutex::new(Vec::new()),
1273            changed: Notify::new(),
1274        })
1275    }
1276
1277    async fn wait_for(&self, counter: &AtomicUsize, expected: usize) {
1278        loop {
1279            let changed = self.changed.notified();
1280            tokio::pin!(changed);
1281            changed.as_mut().enable();
1282            if counter.load(Ordering::SeqCst) >= expected {
1283                return;
1284            }
1285            changed.await;
1286        }
1287    }
1288
1289    fn release(&self, index: usize) {
1290        assert!(self.permitted.lock().unwrap().insert(index));
1291        let waker = self.wakers.lock().unwrap().remove(&index);
1292        if let Some(waker) = waker {
1293            waker.wake();
1294        }
1295    }
1296
1297    fn release_all(&self) {
1298        self.open.store(true, Ordering::SeqCst);
1299        let wakers = std::mem::take(&mut *self.wakers.lock().unwrap());
1300        for (_, waker) in wakers {
1301            waker.wake();
1302        }
1303    }
1304
1305    fn assert_idle(&self) {
1306        assert_eq!(
1307            self.active.load(Ordering::SeqCst),
1308            0,
1309            "original caller sources must be dropped"
1310        );
1311        assert_eq!(
1312            self.dropped.load(Ordering::SeqCst),
1313            self.constructed.load(Ordering::SeqCst)
1314        );
1315        assert!(self.wakers.lock().unwrap().is_empty());
1316        assert!(self.permitted.lock().unwrap().is_empty());
1317    }
1318
1319    fn report(&self) -> Value {
1320        json!({"constructed":self.constructed.load(Ordering::SeqCst),
1321            "completed":self.completed.load(Ordering::SeqCst),
1322            "dropped":self.dropped.load(Ordering::SeqCst),
1323            "active_after_cleanup":self.active.load(Ordering::SeqCst),
1324            "peak_live_sources":self.peak.load(Ordering::SeqCst),
1325            "partial_events":self.partials.load(Ordering::SeqCst),
1326            "construction_to_drop_latency":Performance::samples(std::mem::take(&mut *self.lifetimes.lock().unwrap()))})
1327    }
1328}
1329
1330struct WorkloadAction {
1331    declaration: ActionDeclaration,
1332    probe: Arc<WorkloadProbe>,
1333}
1334
1335impl WorkloadAction {
1336    fn new(probe: &Arc<WorkloadProbe>) -> Self {
1337        Self {
1338            declaration: ActionDeclaration {
1339                key: "performance-action".into(),
1340                revision: "r1".into(),
1341                reads: vec!["value".into()],
1342                writes: vec!["result".into()],
1343                required_inputs: Vec::new(),
1344                optional_inputs: Vec::new(),
1345                bound_inputs: Map::new(),
1346                default_inputs: Map::new(),
1347                tags: Vec::new(),
1348                source: None,
1349                mode: ActionMode::Asynchronous,
1350            },
1351            probe: Arc::clone(probe),
1352        }
1353    }
1354}
1355
1356impl ActionBackend for WorkloadAction {
1357    type Stream = WorkloadSource;
1358
1359    fn declaration(&self) -> &ActionDeclaration {
1360        &self.declaration
1361    }
1362
1363    fn start(&self, request: ActionRequest) -> Self::Stream {
1364        let value = match self.probe.mode {
1365            SourceMode::Permuted => request
1366                .context
1367                .node
1368                .strip_prefix('n')
1369                .unwrap()
1370                .parse()
1371                .unwrap(),
1372            SourceMode::Parallel | SourceMode::Held | SourceMode::Partials => {
1373                usize::try_from(request.state.values()["value"].as_u64().unwrap()).unwrap()
1374            }
1375        };
1376        assert!(
1377            self.probe.constructed.fetch_add(1, Ordering::SeqCst) < self.probe.expected,
1378            "a duplicate source construction exceeds this workload's exact bound"
1379        );
1380        let active = self.probe.active.fetch_add(1, Ordering::SeqCst) + 1;
1381        self.probe.peak.fetch_max(active, Ordering::SeqCst);
1382        self.probe.changed.notify_waiters();
1383        WorkloadSource {
1384            probe: Arc::clone(&self.probe),
1385            value,
1386            started: Instant::now(),
1387            state: SourceState::Polling(0),
1388        }
1389    }
1390}
1391
1392struct WorkloadSource {
1393    probe: Arc<WorkloadProbe>,
1394    value: usize,
1395    started: Instant,
1396    state: SourceState,
1397}
1398
1399enum SourceState {
1400    Polling(usize),
1401    Done,
1402}
1403
1404impl Stream for WorkloadSource {
1405    type Item = Result<ActionEvent, AppError>;
1406
1407    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
1408        let source = self.get_mut();
1409        let SourceState::Polling(polls) = &mut source.state else {
1410            return Poll::Ready(None);
1411        };
1412        *polls += 1;
1413        let polls = *polls;
1414        match source.probe.mode {
1415            SourceMode::Held => return Poll::Pending,
1416            SourceMode::Permuted | SourceMode::Parallel => {
1417                // The bounded map contains only sources currently waiting on
1418                // this harness gate, never every historical run or child.
1419                source
1420                    .probe
1421                    .wakers
1422                    .lock()
1423                    .unwrap()
1424                    .insert(source.value, cx.waker().clone());
1425                let ready = match source.probe.mode {
1426                    SourceMode::Permuted => {
1427                        source.probe.permitted.lock().unwrap().remove(&source.value)
1428                    }
1429                    SourceMode::Parallel => source.probe.open.load(Ordering::SeqCst),
1430                    SourceMode::Held | SourceMode::Partials => unreachable!(),
1431                };
1432                if !ready {
1433                    return Poll::Pending;
1434                }
1435                source.probe.wakers.lock().unwrap().remove(&source.value);
1436                if matches!(source.probe.mode, SourceMode::Parallel) && polls == 1 {
1437                    cx.waker().wake_by_ref();
1438                    return Poll::Pending;
1439                }
1440            }
1441            SourceMode::Partials if polls <= 256 => {
1442                source.probe.partials.fetch_add(1, Ordering::SeqCst);
1443                return Poll::Ready(Some(Ok(ActionEvent::Partial {
1444                    result: Map::from_iter([("progress".into(), json!(polls))]),
1445                })));
1446            }
1447            SourceMode::Partials => {}
1448        }
1449        source.state = SourceState::Done;
1450        if matches!(source.probe.mode, SourceMode::Permuted) {
1451            source.probe.order.lock().unwrap().push(source.value);
1452        }
1453        source.probe.completed.fetch_add(1, Ordering::SeqCst);
1454        source.probe.changed.notify_waiters();
1455        Poll::Ready(Some(Ok(ActionEvent::Completed {
1456            result: Map::from_iter([("value".into(), json!(source.value + 1))]),
1457            writes: vec![StateChange::Assign {
1458                values: Map::from_iter([("result".into(), json!(source.value + 1))]),
1459            }],
1460        })))
1461    }
1462}
1463
1464impl Drop for WorkloadSource {
1465    fn drop(&mut self) {
1466        self.probe.wakers.lock().unwrap().remove(&self.value);
1467        self.probe.active.fetch_sub(1, Ordering::SeqCst);
1468        self.probe.dropped.fetch_add(1, Ordering::SeqCst);
1469        self.probe
1470            .lifetimes
1471            .lock()
1472            .unwrap()
1473            .push(self.started.elapsed());
1474        self.probe.changed.notify_waiters();
1475    }
1476}
1477
1478#[tokio::main(flavor = "current_thread")]
1479async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
1480    Performance::parse()?.run().await
1481}