Back to feed

sledtools/pika branch #142

pika-orch-incus-cleanup-23

Split pikaci frontend modules

Target branch: master

Merge Commit: 63479e7503296344add6a9f0751f7c66863bb912

branch: merged tutorial: ready ci: success
Open CI Details

Continuous Integration

CI: success

Compact status on the review page, with full logs on the CI page.

Open CI Details

Latest run #178 success

6 passed

head 40afe3cac376d2d5eed72e6ff39e8e3ebc5a0769 · queued 2026-03-27 01:33:02 · 6 lane(s)

queued 7s · ran 28s

check-notifications · success check-agent-contracts · success check-pikachat · success check-pikachat-typescript · success check-pikachat-openclaw-e2e · success check-fixture · success

Summary

This branch decomposes the monolithic crates/pikaci/src/main.rs file by extracting two new modules: output.rs (display and serialization helpers) and targets.rs (CI target/job specifications and builder functions). The move is a pure structural refactor — no logic changes, no new features. Additionally, test-only fixture enums in crates/jerichoci/src/model.rs and crates/jerichoci/src/run.rs receive doc-comments clarifying they are non-production catalogs, and invariants/invariants.toml is updated with exclusion rules so these test fixtures and the new module files do not trigger architecture-invariant violations.

Tutorial Steps

Annotate test-only fixture enums in jerichoci to exempt them from invariants

Intent: The jerichoci crate contains test-scoped enum types (`StagedLinuxRustTarget`, `StagedLinuxRustLane`) that mirror production catalog shapes for testing. Without explicit annotation, architecture-invariant tooling could flag these as unauthorized catalog definitions. Adding doc-comments makes the exemption intent machine-readable.

Affected files: crates/jerichoci/src/model.rs, crates/jerichoci/src/run.rs

Evidence
@@ -452,6 +452,8 @@ mod tests {
     use std::fs;
     use std::path::Path;
 
+    // Test-only fixture catalog for model behavior checks. This is not production
+    // JerichoCI catalog data and should not count against architecture invariants.
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     enum StagedLinuxRustTarget {
@@ -475,6 +477,8 @@ mod tests {
         workspace_output_system: &'static str,
     }
 
+    // Test-only fixture catalog for model behavior checks. This is not production
+    // JerichoCI catalog data and should not count against architecture invariants.
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     enum StagedLinuxRustLane {
@@ -4471,6 +4471,8 @@ mod tests {
         action()
     }
 
+    // Test-only fixture catalog for run-path checks. This is not production
+    // JerichoCI catalog data and should not count against architecture invariants.
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     enum StagedLinuxRustLane {

Two files in jerichoci define test-only enums that replicate the shape of production staged-Linux catalogs. The project enforces architecture invariants that restrict where catalog definitions may live.

A two-line comment is added above each enum declaration inside #[cfg(test)] mod tests:

// Test-only fixture catalog for model behavior checks. This is not production
// JerichoCI catalog data and should not count against architecture invariants.

This appears in three locations:

  1. model.rsStagedLinuxRustTarget (line 454)
  2. model.rsStagedLinuxRustLane (line 479)
  3. run.rsStagedLinuxRustLane (line 4473)

The comments serve as anchors for the invariant checker's exclusion rules (configured in a later step).

Extract the output module from main.rs

Intent: Move all display, JSON serialization, and human-readable summary functions out of `main.rs` into a dedicated `output.rs` module. This reduces the size of the entrypoint file and groups presentation logic in one place.

Affected files: crates/pikaci/src/main.rs, crates/pikaci/src/output.rs

Evidence
@@ -1,84 +1,24 @@
 mod catalog;
 mod forge_manifest;
+mod output;
+mod targets;
@@ -374,41 +314,6 @@ fn staged_linux_remote_defaults_json(
-fn print_json(value: &impl serde::Serialize) -> anyhow::Result<()> {
@@ -374,41 +314,6 @@
-fn print_json_line(value: &impl serde::Serialize) -> anyhow::Result<()> {
@@ -374,41 +314,6 @@
-fn print_run_human_summary(run: &RunRecord) {
@@ -1812,15 +525,6 @@
-fn status_text(status: RunStatus) -> &'static str {

The following functions are removed from main.rs and relocated to crates/pikaci/src/output.rs:

FunctionPurpose
print_jsonPretty-print a serializable value to stdout
print_json_lineWrite a single JSON line to stdout
print_run_human_summaryPrint a human-readable run/job status block
status_textMap RunStatus to a static label string
format_status_linesBuild a Vec<String> of key=value diagnostic lines for a run
prepared_output_consumer_labelLabel for PreparedOutputConsumerKind
prepared_output_invocation_mode_labelLabel for PreparedOutputInvocationMode
prepared_output_launcher_transport_mode_labelLabel for PreparedOutputLauncherTransportMode

main.rs now imports these through the new module:

use output::{
    format_status_lines, prepared_output_consumer_label, print_json, print_json_line,
    print_run_human_summary, status_text,
};

The functions are moved verbatim — no signature or logic changes.

Extract the targets module from main.rs

Intent: Move all CI target construction logic — the `TargetSpec` struct, runtime helper constructors, job-base factories, every `*_jobs()` function, and the large `target_spec()` match dispatcher — into a dedicated `targets.rs` module. This is the largest single extraction and removes roughly 700 lines from `main.rs`.

Affected files: crates/pikaci/src/main.rs, crates/pikaci/src/targets.rs

Evidence
@@ -1,84 +1,24 @@
-use catalog::{PikaStagedLinuxLane, PikaStagedLinuxTarget, PikaStagedLinuxTargetInfoJson};
@@ -1,84 +1,24 @@
+use catalog::PikaStagedLinuxTargetInfoJson;
@@ -1,84 +1,24 @@
+use targets::{TargetSpec, staged_linux_target, target_spec};
@@ -462,504 +367,6 @@
-fn staged_linux_target(target_id: &str) -> anyhow::Result<PikaStagedLinuxTarget> {
@@ -462,504 +367,6 @@
-fn target_spec(name: &str) -> anyhow::Result<TargetSpec> {
@@ -462,504 +367,6 @@
-fn agent_contract_jobs() -> Vec<JobSpec> {
@@ -462,504 +367,6 @@
-fn pika_rust_jobs() -> Vec<JobSpec> {

The new crates/pikaci/src/targets.rs receives:

Struct

  • TargetSpec — the central type describing a CI target (id, description, filters, jobs).

Runtime helpers

  • remote_incus_runtime() — build an Incus JobRuntimeConfig
  • tart_runtime() — build a Tart JobRuntimeConfig
  • remote_incus_job_base(), host_local_job_base(), tart_job_base() — default JobSpec scaffolds
  • TART_HOST_SETUP_COMMAND constant

Job-group factories (each returns Vec<JobSpec>)

  • agent_contract_jobs, pika_rust_jobs, notification_jobs, pikachat_rust_jobs, pika_followup_jobs, pikachat_openclaw_e2e_jobs, pikachat_typescript_jobs, fixture_rust_jobs, pikachat_apple_followup_jobs, rmp_jobs
  • Individual Tart job builders: tart_agent_button_job, tart_ios_unit_jobs, tart_ios_unit_suite_job, tart_ios_ui_test_job, tart_ios_ui_note_to_self_job, tart_desktop_package_tests_job

Dispatchers

  • target_spec(name) -> Result<TargetSpec> — the main match-based target resolver
  • staged_linux_target(target_id) — parse a target ID into PikaStagedLinuxTarget
  • staged_linux_target_spec, single_job_target_spec, static_filters — helpers

In main.rs the import list shrinks from pulling individual jerichoci types for job construction to only the types needed for the CLI entrypoint:

use targets::{TargetSpec, staged_linux_target, target_spec};

All call-sites in main.rs that previously referenced these functions now resolve through the module re-export. No behavioral changes are introduced.

Slim down main.rs imports to match the reduced surface

Intent: With output and targets extracted, `main.rs` no longer directly references many jerichoci types. The import block is tightened to only what the remaining CLI orchestration code needs.

Affected files: crates/pikaci/src/main.rs

Evidence
@@ -1,84 +1,24 @@
-use jerichoci::{
-    GuestCommand, HostProcessRuntimeConfig, IncusRuntimeConfig, JobExecutionConfig,
-    JobRuntimeConfig, JobSpec, LogKind, RunLifecycleEvent, RunMetadata, RunOptions, RunRecord,
-    RunStatus, StagedLinuxCommandConfig, StagedLinuxRemoteDefaults, TartRuntimeConfig,
+use jerichoci::{
+    LogKind, RunLifecycleEvent, RunMetadata, RunOptions, RunRecord, RunStatus,
+    StagedLinuxRemoteDefaults, fulfill_prepared_output_request, gc_runs, git_changed_files,

Before the refactor main.rs imported 16 types/functions from jerichoci (including GuestCommand, HostProcessRuntimeConfig, IncusRuntimeConfig, JobExecutionConfig, JobRuntimeConfig, JobSpec, StagedLinuxCommandConfig, TartRuntimeConfig). After extraction, only the types used by CLI dispatch and run lifecycle remain:

use jerichoci::{
    LogKind, RunLifecycleEvent, RunMetadata, RunOptions, RunRecord, RunStatus,
    StagedLinuxRemoteDefaults, fulfill_prepared_output_request, gc_runs, git_changed_files,
    list_runs, load_logs, load_logs_metadata, load_prepared_outputs_record, load_run_record,
    record_skipped_run_with_reporter, rerun_jobs_with_metadata_and_reporter,
    run_jobs_with_metadata_and_reporter, staged_linux_remote_defaults,
};

The removed imports are now consumed exclusively inside targets.rs.

Update architecture invariants to accommodate the new module layout

Intent: The project's `invariants/invariants.toml` enforces constraints on where certain patterns may appear. The new files and the annotated test fixtures need explicit exclusion entries so the invariant checker does not produce false positives.

Affected files: invariants/invariants.toml

Evidence
@@ -452,6 +452,8 @@ mod tests {

Although the diff for invariants/invariants.toml was truncated in the payload, it is listed as a changed file. Based on the doc-comments added in step 1 and the new module files created in steps 2–3, the invariants file is expected to contain:

  1. Exclusion entries for crates/pikaci/src/output.rs and crates/pikaci/src/targets.rs — these files now contain patterns (e.g., catalog lane references, job-spec constructors) that previously lived in the already-exempted main.rs.
  2. Exclusion entries for test-only fixture enums in crates/jerichoci/src/model.rs and crates/jerichoci/src/run.rs — keyed on the comment sentinel added in step 1.

Without these updates, the invariant checker would flag the extracted code as violating the architecture rules, since the patterns moved to files not previously in its allow-list.

When reviewing this file, verify that each new exclusion is scoped as narrowly as possible (file path + test module context) rather than blanket-disabling the invariant.

Diff