[object Object]

โ† back to Terminal Status

stopped variant: keep the base colour dot, put ๐Ÿ”ต NEXT TO it (2026-09-11)

b37dbc2c6e3599723db03482558f8e5d7ac3f415 ยท 2026-09-11 10:15:56 -0700 ยท Steve Abrams

Steve: 'keep color dot and place blue dot next to it when stopped โ€ฆ when running
revert back to original color dot with that dot next to the orig color dot flashing.'

Additive marker, never a replacement:  ๐ŸŸฃ -> ๐ŸŸฃ๐Ÿ”ต stopped -> ๐ŸŸฃ running.

Three defects caught while wiring it, each of which would have shipped a silent no-op:
  1. set() discarded the variant for any non-green colour ('variant if color == "green"'),
     so --stopped on purple/yellow/orange โ€” the blocked colours this exists for โ€” would
     have been accepted, reported success, and vanished. stopped is now colour-agnostic;
     monitoring stays green-only because it is the teal TINT of green.
  2. All three status_title() call sites built the title WITHOUT the variant, so even a
     stored variant would not render โ€” and the canonical check at load() compares title
     to expected, so the record would then be judged invalid and wiped.
  3. set_variant() first drafted against self.write()/self.painter() as methods; write()
     does not exist and the real path also updates the legacy .dot mirror, which is what
     allcolordots and dot-screen-router actually read. Updating only the JSON would have
     left every consumer showing the old title while the engine reported success.

Verified with negative tests: purple+stopped renders ๐ŸŸฃ๐Ÿ”ต and reverts clean; a bogus
variant raises; monitoring on a non-green colour is dropped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Files touched

Diff

commit b37dbc2c6e3599723db03482558f8e5d7ac3f415
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Sep 11 10:15:56 2026 -0700

    stopped variant: keep the base colour dot, put ๐Ÿ”ต NEXT TO it (2026-09-11)
    
    Steve: 'keep color dot and place blue dot next to it when stopped โ€ฆ when running
    revert back to original color dot with that dot next to the orig color dot flashing.'
    
    Additive marker, never a replacement:  ๐ŸŸฃ -> ๐ŸŸฃ๐Ÿ”ต stopped -> ๐ŸŸฃ running.
    
    Three defects caught while wiring it, each of which would have shipped a silent no-op:
      1. set() discarded the variant for any non-green colour ('variant if color == "green"'),
         so --stopped on purple/yellow/orange โ€” the blocked colours this exists for โ€” would
         have been accepted, reported success, and vanished. stopped is now colour-agnostic;
         monitoring stays green-only because it is the teal TINT of green.
      2. All three status_title() call sites built the title WITHOUT the variant, so even a
         stored variant would not render โ€” and the canonical check at load() compares title
         to expected, so the record would then be judged invalid and wiped.
      3. set_variant() first drafted against self.write()/self.painter() as methods; write()
         does not exist and the real path also updates the legacy .dot mirror, which is what
         allcolordots and dot-screen-router actually read. Updating only the JSON would have
         left every consumer showing the old title while the engine reported success.
    
    Verified with negative tests: purple+stopped renders ๐ŸŸฃ๐Ÿ”ต and reverts clean; a bogus
    variant raises; monitoring on a non-green colour is dropped.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---
 terminal_status.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 68 insertions(+), 9 deletions(-)

diff --git a/terminal_status.py b/terminal_status.py
index 07a7303..9f18286 100644
--- a/terminal_status.py
+++ b/terminal_status.py
@@ -79,10 +79,17 @@ def issued_clock():
     return time.clock_gettime_ns(getattr(time, "CLOCK_MONOTONIC_RAW", time.CLOCK_MONOTONIC))
 
 
-def status_title(color, label, ticket=""):
+STOPPED_MARK = "\U0001F535"   # ๐Ÿ”ต โ€” "stopped, needs Steve", shown NEXT TO the base dot
+
+
+def status_title(color, label, ticket="", variant=""):
+    # variant "stopped" (Steve, 2026-09-11): keep the ORIGINAL colour dot and place the
+    # blue dot next to it โ€” additive marker, never a replacement. Reverts to the base dot
+    # alone as soon as the session is running again.
     if color == "none":
         return ""
-    return COLORS[color][0] + " " + " ยท ".join(p for p in (ticket, label) if p)
+    dot = COLORS[color][0] + (STOPPED_MARK if variant == "stopped" else "")
+    return dot + " " + " ยท ".join(p for p in (ticket, label) if p)
 
 
 def label_ticket(label):
@@ -371,9 +378,9 @@ class Store:
             ticket = r.get("ticket", "")
             if (ticket and not re.fullmatch(r"TK-\d+", ticket)) or not isinstance(r.get("ticket_at", 0), (int, float)):
                 return None, "invalid"
-            if r.get("variant", "") not in ("", "monitoring"):
+            if r.get("variant", "") not in ("", "monitoring", "stopped"):
                 return None, "invalid"
-            expected = status_title(r["state"], r["label"], ticket)
+            expected = status_title(r["state"], r["label"], ticket, r.get("variant", ""))
             if r["title"] != expected or (r["state"] == "none" and r["label"]):
                 return None, "invalid"
             return r, "canonical"
@@ -408,7 +415,7 @@ class Store:
     def set(self, owner, color, label="", *, issued_ns=None, ticket_update=None,
             variant="", deferential=False):
         issued_ns = issued_ns if issued_ns is not None else issued_clock()
-        if color not in COLORS or not valid_label(label) or variant not in ("", "monitoring"):
+        if color not in COLORS or not valid_label(label) or variant not in ("", "monitoring", "stopped"):
             raise StatusError("Invalid status or label")
         label, embedded_ticket = label_ticket(label)
         if embedded_ticket:
@@ -444,9 +451,14 @@ class Store:
             record = {
                 "version": VERSION, "owner": dataclasses.asdict(owner),
                 "state": color, "label": label,
-                "title": status_title(color, label, ticket["id"]),
+                "title": status_title(color, label, ticket["id"],
+                                     variant if (color == "green" or variant == "stopped") else ""),
                 "ticket": ticket["id"], "ticket_at": ticket["at"],
-                "ticket_source": ticket["source"], "variant": variant if color == "green" else "",
+                "ticket_source": ticket["source"],
+                # "stopped" is colour-AGNOSTIC: it is an additive ๐Ÿ”ต marker beside ANY base
+                # dot, and the blocked colours (purple/yellow/orange) are its whole point.
+                # "monitoring" stays green-only because it is the teal TINT of green.
+                "variant": variant if (color == "green" or variant == "stopped") else "",
                 "revision": previous["revision"] + 1 if previous else 1,
                 "event_id": uuid.uuid4().hex, "issued_ns": issued_ns,
                 "updated_at": dt.datetime.now(dt.timezone.utc).isoformat(),
@@ -483,6 +495,41 @@ class Store:
             # Never refresh timestamps, rewrite mirrors, or resurrect cleared state.
             return record
 
+    def set_variant(self, owner, variant):
+        """Toggle ONLY the variant (e.g. the additive ๐Ÿ”ต stopped marker) on an existing
+        status โ€” colour, label, ticket and timestamps are preserved. This is what the
+        flasher pulses, so a crashed loop can never corrupt the real dot: the worst case
+        is the marker left on or off beside an otherwise-correct base colour."""
+        if variant not in ("", "monitoring", "stopped"):
+            raise StatusError("Invalid variant")
+        with self.lock(owner):
+            record, reason = self.load(owner)
+            if record is None:
+                raise StatusError("Cannot set variant on unknown status: " + reason)
+            self.assert_owner(owner)
+            color = record["state"]
+            if variant == "monitoring" and color != "green":
+                variant = ""
+            record["variant"] = variant
+            record["title"] = status_title(color, record["label"], record.get("ticket", ""), variant)
+            record["revision"] = record.get("revision", 0) + 1
+            record["event_id"] = uuid.uuid4().hex
+            record["issued_ns"] = issued_clock()
+            record["updated_at"] = dt.datetime.now(dt.timezone.utc).isoformat()
+            record["mirror_errors"] = []
+            self.assert_owner(owner)
+            self.painter(owner, record)
+            # The legacy .dot mirror is what allcolordots and dot-screen-router actually
+            # read โ€” updating only the JSON would leave every consumer showing the old
+            # title while the engine reported success.
+            for directory in self.legacy.values():
+                try:
+                    atomic_write(directory / (owner.tty + ".dot"), record["title"])
+                except OSError as exc:
+                    record["mirror_errors"].append(str(exc))
+            atomic_write(self.path(owner), json.dumps(record, indent=2) + "\n")
+            return record
+
     def row(self, owner, title=""):
         r, reason = self.read(owner, title)
         ticket = self.ticket_info(owner, r)
@@ -499,7 +546,7 @@ class Store:
             result.update(color="none", label="โšช " + (ticket["id"] or "TK REQUIRED") + " ยท " + labels.get(reason, "Status not set"))
             return result
         label, _ = label_ticket(r["label"])
-        result.update(color=r["state"], label=status_title(r["state"], label, ticket["id"] or "TK REQUIRED") or "โšช " + (ticket["id"] or "TK REQUIRED") + " ยท Status cleared",
+        result.update(color=r["state"], label=status_title(r["state"], label, ticket["id"] or "TK REQUIRED", r.get("variant", "")) or "โšช " + (ticket["id"] or "TK REQUIRED") + " ยท Status cleared",
                       updated_at=r.get("updated_at"), revision=r.get("revision"))
         warnings = []
         live_color = color_of(title)
@@ -586,6 +633,8 @@ def scan(store, rows=None, sessions=None):
 def main(argv=None):
     parser = argparse.ArgumentParser(description=__doc__)
     sub = parser.add_subparsers(dest="command", required=True)
+    sv = sub.add_parser("set-variant")
+    sv.add_argument("variant", nargs="?", default="", choices=["", "monitoring", "stopped"])
     for name in ("set", "clear", "repaint", "current", "start", "ticket", "status", "headers"):
         cmd = sub.add_parser(name)
         if name == "set":
@@ -593,6 +642,9 @@ def main(argv=None):
             cmd.add_argument("label", nargs="?", default="")
             cmd.add_argument("--all", choices=["claude", "codex"])
             cmd.add_argument("--monitoring", action="store_true")
+            cmd.add_argument("--stopped", action="store_true",
+                             help="keep the base colour dot and place \U0001F535 next to it "
+                                  "(any stop that requires Steve's input)")
             cmd.add_argument("--deferential", action="store_true",
                              help="automatic paint: yield to a sticky semantic dot "
                                   "(orange/purple/yellow) instead of overwriting it")
@@ -644,6 +696,12 @@ def main(argv=None):
             raise StatusError("; ".join(failures))
         return 0
     caller = current_owner(rows)
+    if args.command == "set-variant":
+        owner = Owner.detect()
+        record = STORE.set_variant(owner, args.variant)
+        print(f'/terminal-status โ†’ /dev/{owner.tty} {record["title"] or "CLEARED"}')
+        return 0
+
     if args.command == "current":
         print(json.dumps(dataclasses.asdict(caller)))
         return 0
@@ -702,7 +760,8 @@ def main(argv=None):
             record = store.repaint(owner)
         else:
             record = store.set(owner, color, label,
-                               variant="monitoring" if getattr(args, "monitoring", False) else "",
+                               variant=("stopped" if getattr(args, "stopped", False)
+                                        else "monitoring" if getattr(args, "monitoring", False) else ""),
                                deferential=getattr(args, "deferential", False))
         if not getattr(args, "quiet", False):
             print(f'/terminal-status โ†’ /dev/{owner.tty} {record["title"] or "CLEARED"}')

โ† a56bd8c colors: add lightblue = ANY STOP THAT REQUIRES STEVE'S INPUT  ยท  back to Terminal Status  ยท  terminal-status: add lightblue to PRIORITY (unblock scan cra c40a4b0 โ†’