use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::process::Command;
use hel::hel_archive::{
ArchiveInput, BundleManifest, SessionManifest, TargetManifest, write_archive_atomic,
};
use hel::hel_config::{
ContainerTemplate as ConfigContainer, HelConfig, ProjectBundle, ProjectRepository,
SshConnection, TargetTemplate,
};
use hel::hel_state::{
CheckpointMetadata, ManagedWorktree, ManagedWorktreeTarget, SessionRecord, SessionState,
};
use hel::hel_targets::ProcessExecutor;
use super::worktree::{
PrimaryCheckoutRequirement, create_managed_worktree, managed_worktree_target,
};
pub(super) fn checkpoint_test_session(session_id: &str) -> SessionRecord {
SessionRecord {
workspace_id: hel::hel_workspace::DEFAULT_WORKSPACE_ID.to_owned(),
archived: false,
container_cpus: None,
container_memory: None,
id: session_id.into(),
title: "checkpoint transition".into(),
harness_kind: hel::hel_config::HarnessKind::Codex,
last_profile: "codex".into(),
bundle_id: "project".into(),
project_directory: None,
managed_worktree: None,
target_template_id: "podman".into(),
resource_allocation: None,
additional_mounts: Vec::new(),
state: SessionState::Running,
target: None,
native_session_id: Some("native-session".into()),
acp_session_title: None,
session_title_override: None,
created_at: "2026-08-12T00:00:00Z".into(),
updated_at: "2026-08-12T00:00:00Z".into(),
viewed_through_event_ordinal: 0,
draft_input: String::new(),
last_error: None,
last_checkpoint_error: None,
checkpoint: None,
}
}
pub(super) fn write_checkpoint_gate_archive(
directory: &Path,
session_id: &str,
event_frontier: u64,
) -> CheckpointMetadata {
write_checkpoint_archive(directory, session_id, event_frontier, Vec::new())
}
pub(super) fn write_network_checkpoint_archive(
directory: &Path,
session_id: &str,
event_frontier: u64,
) -> CheckpointMetadata {
use hel::hel_archive::{RepositoryMetadata, RepositorySnapshot};
write_checkpoint_archive(
directory,
session_id,
event_frontier,
vec![RepositorySnapshot {
metadata: RepositoryMetadata {
id: "project".into(),
relative_destination: "project".into(),
origin: "https://fetch.example.test/project.git".into(),
push_urls: vec!["https://push.example.test/project.git".into()],
remote_workspace: true,
base_commit: "a".repeat(40),
head_commit: "a".repeat(40),
branch: Some(format!("mj/{session_id}")),
},
committed_bundle: Vec::new(),
staged_patch: Vec::new(),
unstaged_patch: Vec::new(),
untracked_tar: Vec::new(),
}],
)
}
fn write_checkpoint_archive(
directory: &Path,
session_id: &str,
event_frontier: u64,
repositories: Vec<hel::hel_archive::RepositorySnapshot>,
) -> CheckpointMetadata {
let archive_path = directory.join(format!("{session_id}.hel.zip"));
let verified = write_archive_atomic(
&archive_path,
&ArchiveInput {
session: SessionManifest {
id: session_id.into(),
title: "checkpoint gate".into(),
harness_kind: hel::hel_config::HarnessKind::Codex,
profile_id: "codex".into(),
native_session_id: "native-session".into(),
created_at: "2026-08-12T00:00:00Z".into(),
checkpointed_at: "2026-08-14T12:00:00Z".into(),
hel_version: "test".into(),
relay_version: "test".into(),
adapter_version: "test".into(),
},
target: TargetManifest {
template_id: "local".into(),
target_kind: "local-bare".into(),
details: BTreeMap::new(),
},
bundle: BundleManifest {
id: "project".into(),
primary_repository: "project".into(),
},
canonical_session: hel::hel_archive::CanonicalSessionSnapshot {
event_frontier,
event_frontier_digest: if event_frontier == 0 {
hel::hel_archive::EVENT_FRONTIER_GENESIS_DIGEST.into()
} else {
"a".repeat(64)
},
session: hel::hel_archive::CanonicalSessionState {
execution: hel::hel_archive::CanonicalExecutionState::Idle,
last_activity_at_ms: (event_frontier > 0).then_some(1_234),
session_title: None,
configuration: BTreeMap::new(),
},
transcript: Vec::new(),
queued_prompts: Vec::new(),
},
native_artifacts: Vec::new(),
repositories,
},
)
.unwrap();
CheckpointMetadata {
archive_path,
sha256: verified.archive_sha256,
created_at: "2026-08-14T12:00:00Z".into(),
event_frontier,
}
}
pub(super) fn resume_compatibility_config() -> HelConfig {
let mut config = HelConfig::default();
config.targets.insert(
"podman".into(),
TargetTemplate::LocalPodman {
container: ConfigContainer {
image: "example.invalid/hel-test:latest".into(),
pull_policy: Default::default(),
platform: None,
cpus: None,
memory: None,
environment: BTreeMap::new(),
workspace_storage: Default::default(),
},
},
);
config
.targets
.insert("local-bare".into(), TargetTemplate::LocalBare);
config.targets.insert(
"ssh-bare".into(),
TargetTemplate::SshBare {
ssh: SshConnection {
host: "builder".into(),
user: Some("dev".into()),
identity_file: None,
extra_args: Vec::new(),
},
permissions: hel::hel_config::PermissionMode::Yolo,
workspace_prefix: ".local/share/hel/workspaces".into(),
},
);
config
}
pub(super) fn raw_session_on(target_template_id: &str, directory: &str) -> SessionRecord {
let mut session = checkpoint_test_session("0123456789abcdef0123456789abcdef");
session.state = SessionState::Stopped;
session.bundle_id = "remote-project-abcdef".into();
session.project_directory = Some(PathBuf::from(directory));
session.target_template_id = target_template_id.into();
session
}
pub(super) fn managed_raw_session(target: ManagedWorktreeTarget) -> SessionRecord {
let session_id = "0123456789abcdef0123456789abcdef";
let repository = PathBuf::from("/home/dev/project");
let worktree_root = repository.join(".mj").join("worktrees").join(session_id);
let mut session = raw_session_on(
match target {
ManagedWorktreeTarget::Local => "local-bare",
ManagedWorktreeTarget::Ssh { .. } => "ssh-bare",
},
&worktree_root.to_string_lossy(),
);
session.managed_worktree = Some(ManagedWorktree {
source_project_directory: repository.clone(),
source_repository: repository,
worktree_root,
branch: format!("mj/{session_id}"),
target,
});
session
}
pub(super) fn ssh_worktree_target() -> ManagedWorktreeTarget {
managed_worktree_target(&resume_compatibility_config().targets["ssh-bare"]).unwrap()
}
pub(super) fn local_bundle(repository: &Path) -> ProjectBundle {
ProjectBundle {
primary_repo: "project".into(),
repositories: vec![ProjectRepository {
id: "project".into(),
github: None,
local: Some(repository.to_path_buf()),
destination: PathBuf::from("project"),
git_ref: None,
}],
}
}
pub(super) fn test_git(directory: &Path, args: &[&str]) -> String {
let output = Command::new("git")
.arg("-C")
.arg(directory)
.args(args)
.output()
.unwrap();
assert!(
output.status.success(),
"git {} failed: {}",
args.join(" "),
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8(output.stdout).unwrap().trim().to_owned()
}
pub(super) fn committed_repository() -> tempfile::TempDir {
let directory = tempfile::tempdir().unwrap();
test_git(directory.path(), &["init", "--initial-branch=master"]);
test_git(directory.path(), &["config", "user.name", "Hel Tests"]);
test_git(
directory.path(),
&["config", "user.email", "hel@example.invalid"],
);
std::fs::create_dir(directory.path().join("nested")).unwrap();
std::fs::write(directory.path().join("nested/file.txt"), "base\n").unwrap();
test_git(directory.path(), &["add", "."]);
test_git(directory.path(), &["commit", "-m", "base"]);
directory
}
pub(super) fn managed_worktree_session(repository: &Path, session_id: &str) -> SessionRecord {
let worktree = ManagedWorktree {
source_project_directory: repository.to_path_buf(),
source_repository: repository.to_path_buf(),
worktree_root: repository.join(".mj/worktrees").join(session_id),
branch: format!("mj/{session_id}"),
target: ManagedWorktreeTarget::Local,
};
create_managed_worktree(
&ProcessExecutor,
&worktree,
None,
PrimaryCheckoutRequirement::Clean,
)
.unwrap();
let mut session = checkpoint_test_session(session_id);
session.state = SessionState::Stopped;
session.bundle_id = "remote-project-abcdef".into();
session.target_template_id = "local-bare".into();
session.project_directory = Some(worktree.worktree_root.clone());
session.managed_worktree = Some(worktree);
session
}