From cd20663a7e55cc324d3965e3aa32d42ebf939125 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Sat, 3 Oct 2026 19:45:48 +0100 Subject: [PATCH] Keep demo recovery fixtures portable across temporary path aliases Both macOS installer jobs failed the connected recovery controls because their temporary estate retained the /var symlink prefix. Resolve only the fixture root and exercise both paths under a real alias; keep production symlink rejection and complete observation windows unchanged. Contract-Neutral: Test fixture path canonicalisation and a connected portability control only; no demo runtime, workflow, release or installation contract changes. Change-source: pulse-maintainer --- .../tests/test_demo_runtime_transaction.py | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/scripts/tests/test_demo_runtime_transaction.py b/.github/scripts/tests/test_demo_runtime_transaction.py index 3900e32a01..487e845fd9 100644 --- a/.github/scripts/tests/test_demo_runtime_transaction.py +++ b/.github/scripts/tests/test_demo_runtime_transaction.py @@ -145,7 +145,10 @@ class TransactionTest(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.addCleanup(self.tmp.cleanup) - root = Path(self.tmp.name) + # Model an owned estate, not the OS alias leading to its temporary + # directory (for example macOS /var -> /private/var). The production + # history guard still rejects symlinks introduced inside the estate. + root = Path(self.tmp.name).resolve() self.paths = {name: root / "estate" / name for name in engine.PATHS} for name, path in self.paths.items(): path.parent.mkdir(parents=True, exist_ok=True) @@ -456,7 +459,7 @@ class TransactionTest(unittest.TestCase): def test_unhealthy_recovery_retains_original_generated_history(self): self.host.unhealthy = True code, receipt = self.run_transaction() - self.assertEqual(code, 0) + self.assertEqual(code, 0, receipt.get("failure")) self.assertFalse(receipt["healthy_baseline"]) self.assertFalse((self.paths["data"] / "alerts/events.db").exists()) self.assertEqual((self.attempt / "snapshot/data/alerts/events.db").read_bytes(), b"synthetic opaque persistent file") @@ -489,7 +492,7 @@ class TransactionTest(unittest.TestCase): def test_listener_readiness_does_not_spend_the_watch_window(self): self.host.ready_until = 30 code, receipt = self.run_transaction() - self.assertEqual(code, 0) + self.assertEqual(code, 0, receipt.get("failure")) self.assertEqual(receipt["forward"]["elapsed_seconds"], 300) self.assertGreaterEqual(self.host.clock, 330) self.assertEqual(self.host.starts, 1) @@ -822,6 +825,29 @@ class RuntimeSelectionTest(unittest.TestCase): engine.runtime_members(self.archive(directory, entries), 'v6.4.6') +class PortableTransactionFixtureTest(unittest.TestCase): + def test_recovery_controls_accept_a_symlinked_temporary_parent(self): + # macOS commonly exposes its temporary directory through /var -> + # /private/var. Exercise both failing recovery paths with a real + # equivalent alias, without changing the production symlink guard. + with tempfile.TemporaryDirectory() as directory: + root = Path(directory).resolve() + real = root / "real" + real.mkdir() + alias = root / "alias" + alias.symlink_to(real, target_is_directory=True) + cases = unittest.TestSuite([ + TransactionTest("test_unhealthy_recovery_retains_original_generated_history"), + TransactionTest("test_listener_readiness_does_not_spend_the_watch_window"), + ]) + result = unittest.TestResult() + with patch.object(tempfile, "tempdir", str(alias)): + cases.run(result) + self.assertEqual(result.testsRun, 2) + self.assertEqual(result.errors, []) + self.assertEqual(result.failures, []) + + class NativeGateTest(unittest.TestCase): def row(self, run_id=10, **fields): return {'id': run_id, 'head_sha': 'a' * 40, 'run_attempt': 1,