Skip to content

Commit 95788fb

Browse files
Merge pull request #425 from compoundingtech/schickling-assistant/2026-09-02-fix-raw-workspace-projection
fix(catalog): exclude workspaces from raw preimages
2 parents 4e7d513 + cee2520 commit 95788fb

2 files changed

Lines changed: 14 additions & 25 deletions

File tree

src/catalog_transaction.rs

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,7 +1812,9 @@ fn project_raw_current(root: &Path) -> Result<DeclarationProjection> {
18121812
let mut files = BTreeMap::new();
18131813
add_optional_regular(root, &root.join(crate::catalog::CONFIG_FILE), &mut files)?;
18141814
let spec_paths = collect_canonical_specs(root, ProjectionSource::Current, &mut files)?;
1815-
let workspace_dirs = raw_workspace_dirs(root, &spec_paths)?;
1815+
// Invalid declarations cannot establish typed workspace facts; canonical runtime directories
1816+
// are excluded structurally by the shared bundle collector instead.
1817+
let workspace_dirs = BTreeSet::new();
18161818
for spec in &spec_paths {
18171819
let bundle = spec.parent().context("canonical spec has no bundle")?;
18181820
collect_bundle_files(
@@ -1834,30 +1836,6 @@ fn project_raw_current(root: &Path) -> Result<DeclarationProjection> {
18341836
})
18351837
}
18361838

1837-
fn raw_workspace_dirs(root: &Path, spec_paths: &[PathBuf]) -> Result<BTreeSet<String>> {
1838-
let mut workspace_dirs = BTreeSet::new();
1839-
for spec in spec_paths {
1840-
let bundle = spec.parent().context("canonical spec has no bundle")?;
1841-
let workspace = bundle.join(".workspace");
1842-
match fs::symlink_metadata(&workspace) {
1843-
Ok(metadata) => {
1844-
anyhow::ensure!(
1845-
metadata.is_dir() && !metadata.file_type().is_symlink(),
1846-
"canonical workspace fact is not a real directory: {}",
1847-
workspace.display()
1848-
);
1849-
workspace_dirs.insert(normalized_relative(root, &workspace)?);
1850-
}
1851-
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
1852-
Err(error) => {
1853-
return Err(error)
1854-
.with_context(|| format!("inspect workspace fact {}", workspace.display()));
1855-
}
1856-
}
1857-
}
1858-
Ok(workspace_dirs)
1859-
}
1860-
18611839
fn project(
18621840
root: &Path,
18631841
source: ProjectionSource,

tests/catalog_apply.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,12 @@ profile "dev.example.observe" {{
19011901
)
19021902
.unwrap();
19031903
fs::write(agent.join("status"), "busy").unwrap();
1904+
fs::create_dir_all(agent.join(".workspace")).unwrap();
1905+
fs::write(
1906+
agent.join(".workspace/session.txt"),
1907+
"preserve live workspace",
1908+
)
1909+
.unwrap();
19041910

19051911
let raw_capture_dir = temp.path().join("raw-capture-legacy");
19061912
let captured = raw_snapshot(&catalog, &raw_capture_dir);
@@ -1914,6 +1920,7 @@ profile "dev.example.observe" {{
19141920
fs::read_to_string(raw_capture_dir.join("catalog.kdl")).unwrap(),
19151921
legacy_config
19161922
);
1923+
assert!(!raw_capture_dir.join("agents/host/worker/.workspace").exists());
19171924

19181925
let desired = temp.path().join("desired-component");
19191926
write_agent(&desired, "worker", false);
@@ -1958,6 +1965,10 @@ profile "dev.example.observe" {{
19581965
"preserve mutable context"
19591966
);
19601967
assert_eq!(fs::read_to_string(agent.join("status")).unwrap(), "busy");
1968+
assert_eq!(
1969+
fs::read_to_string(agent.join(".workspace/session.txt")).unwrap(),
1970+
"preserve live workspace"
1971+
);
19611972
let applied = st2::catalog::load(&catalog).unwrap();
19621973
assert_eq!(applied.pty_root.as_deref(), Some(pty_root));
19631974
assert_eq!(

0 commit comments

Comments
 (0)