Drafts rebase onto the live settings; the review speaks in words

A draft started before someone else's Apply used to carry that older config and would have put
the newer changes back. Now every read of the draft replays only the draft's own changes onto the
live settings (base config from history), so the review lists exactly what you changed. Values
read in words (windows as days and hours), long ones fold open with was/now, commands are no
longer red, and warnings the live config already had are not repeated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 19:44:51 -04:00
co-authored by Claude Fable 5.1
parent edfd218ac9
commit 0eee778a92
6 changed files with 181 additions and 22 deletions
+28 -2
View File
@@ -88,9 +88,13 @@ class TestDraftAndPlan(unittest.TestCase):
hd2["checks"][0]["optional"] = False
after["site"]["editing_code"] = "new words"
after["hosts"]["lighting"]["notes"] = "keep it Public"
texts = [ap.words_for(p, a, b, self.cfg, after)["text"] for p, a, b in ap.changed_paths(self.cfg, after)]
words = [ap.words_for(p, a, b, self.cfg, after) for p, a, b in ap.changed_paths(self.cfg, after)]
texts = [w["text"] for w in words]
self.assertIn("key HD2 › check 1 › optional: yes → no", texts)
self.assertIn("computer Lighting PC › notes: Keep the network profile on Public: rtpMIDI's Bonjour rules only allow Public. → keep it Public", texts)
self.assertIn("computer Lighting PC › notes changed", texts) # long values fold open
note = next(w for w in words if w["text"] == "computer Lighting PC › notes changed")
self.assertEqual((note["before"][:8], note["after"]), ("Keep the", "keep it Public"))
self.assertEqual(ap.plain_value([{"days": ["sun"], "start": "06:30", "end": "13:30"}, {"days": ["wed"], "start": "16:00", "end": "21:00"}]), "Sun 6:30 am – 1:30 pm; Wed 4 pm – 9 pm")
self.assertTrue(any(t == "site › editing code changed" for t in texts), texts) # a secret: never its value
more = json.loads(json.dumps(self.cfg))
midi = next(t for t in more["tiles"] if t["id"] == "midi")
@@ -100,6 +104,28 @@ class TestDraftAndPlan(unittest.TestCase):
self.assertTrue(texts[0].startswith("key MIDI › check %d added: " % (len(midi["checks"]))), texts)
class TestRebase(unittest.TestCase):
def test_set_path_and_rebase(self):
base = json.loads(json.dumps(CONFIG))
live = json.loads(json.dumps(base)); live["debounce_seconds"] = 7 # moved on since the draft started
live["fixes"]["vista"]["label"] = "start Vista (new words)"
draft = {"config": json.loads(json.dumps(base))}
draft["config"]["auto_fix"]["windows"].append({"days": ["wed"], "start": "16:00", "end": "21:00"}) # the draft's own change
next(t for t in draft["config"]["tiles"] if t["id"] == "hd2")["checks"][0]["optional"] = False
draft["config"]["hosts"]["lighting"]["notes"] = "mine"
merged, changes = ap.rebase(draft, live, base)
self.assertEqual(merged["debounce_seconds"], 7) # the live change survives
self.assertEqual(merged["fixes"]["vista"]["label"], "start Vista (new words)")
self.assertEqual(len(merged["auto_fix"]["windows"]), 2) # and the draft's own
self.assertFalse(next(t for t in merged["tiles"] if t["id"] == "hd2")["checks"][0]["optional"])
self.assertEqual(merged["hosts"]["lighting"]["notes"], "mine")
self.assertEqual(len(changes), 3)
cfg = json.loads(json.dumps(base))
ap.set_path(cfg, "tiles[hd2]", None); self.assertFalse(any(t["id"] == "hd2" for t in cfg["tiles"]))
ap.set_path(cfg, "tiles[hd9]", {"id": "hd9", "label": "HD9"}); self.assertTrue(any(t["id"] == "hd9" for t in cfg["tiles"]))
ap.set_path(cfg, "hosts.newpc.ssh", "a@b"); self.assertEqual(cfg["hosts"]["newpc"]["ssh"], "a@b")
class TestPipeline(unittest.TestCase):
def setUp(self):
self.data = tempfile.mkdtemp(prefix="sp-pipe-")