From 23709ab8a994bab49b39a0e089d09077087a4c57 Mon Sep 17 00:00:00 2001 From: Mickael Farina Date: Wed, 7 Oct 2026 13:58:16 +0700 Subject: [PATCH] Automatic triggers: a readable title instead of the raw pattern The 'CODEC is watching' menu titled each trigger with its raw rule, for example clipboard~https?://[^\s<>'"]+. The trigger list now sends a label (the skill and when it starts: "Clipboard url fetch: when you copy matching text") and the page shows it as the title, with the rule on the detail line. Pages restamped for the new codec-shell.js. Co-Authored-By: Claude Opus 5.5 --- codec_chat.html | 2 +- codec_cortex.html | 2 +- codec_dashboard.html | 2 +- codec_tasks.html | 2 +- codec_vibe.html | 2 +- codec_voice.html | 2 +- docs/known-issues.md | 2 +- routes/triggers.py | 16 ++++++++++++++++ static/codec-shell.js | 4 ++-- tests/test_watching.py | 11 +++++++++++ 10 files changed, 36 insertions(+), 9 deletions(-) diff --git a/codec_chat.html b/codec_chat.html index 95dbf4c..af52faa 100644 --- a/codec_chat.html +++ b/codec_chat.html @@ -431,7 +431,7 @@ - +
diff --git a/codec_cortex.html b/codec_cortex.html index 1154fd7..86fe122 100644 --- a/codec_cortex.html +++ b/codec_cortex.html @@ -182,7 +182,7 @@ - +
diff --git a/codec_dashboard.html b/codec_dashboard.html index 1b5abc7..57915d0 100644 --- a/codec_dashboard.html +++ b/codec_dashboard.html @@ -666,7 +666,7 @@ - + diff --git a/docs/known-issues.md b/docs/known-issues.md index 2e7c59d..8aa5c9e 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -427,7 +427,7 @@ waits on a model call (not traced yet). Pages are unreachable until then. Fix: find that call and run it after startup, in the background, with a short timeout. Found in the Mac merge pass. Revisit: the next item that touches dashboard startup. -## Automatic triggers show their raw pattern as the title (2026-10-07) +## Automatic triggers show their raw pattern as the title (2026-10-07) — FIXED (a sentence per type; the rule moved to the detail line) The 'CODEC is watching' menu's Automatic triggers list (P3.7) titles each trigger with `codec_triggers`' summary, which is the raw match rule, for example diff --git a/routes/triggers.py b/routes/triggers.py index af17eb7..06dce14 100644 --- a/routes/triggers.py +++ b/routes/triggers.py @@ -32,6 +32,21 @@ router = APIRouter(prefix="/api/triggers", tags=["triggers"]) +# A readable title for the pages; the raw rule stays in "summary". +_TYPE_SENTENCE = { + "window_title_match": "when a window title matches", + "clipboard_pattern": "when you copy matching text", + "file_change": "when matching files change", + "time": "on a schedule", + "compound": "when several conditions match", +} + + +def _plain_label(trig) -> str: + name = str(trig.skill_name).replace("_", " ").strip() + return f"{name[:1].upper() + name[1:]}: {_TYPE_SENTENCE.get(trig.type, 'when its rule matches')}" + + def _trigger_summary(trig) -> dict: """Render a Trigger to a JSON-safe dict for the API.""" from codec_triggers import _resolve_mute, cooldown_remaining, is_killed @@ -41,6 +56,7 @@ def _trigger_summary(trig) -> dict: "skill_name": trig.skill_name, "type": trig.type, "summary": trig.short_summary(), + "label": _plain_label(trig), "cooldown_seconds": trig.cooldown_seconds, "cooldown_remaining": cooldown_remaining(trig.key, trig.cooldown_seconds), "require_confirmation": trig.require_confirmation, diff --git a/static/codec-shell.js b/static/codec-shell.js index 3136bee..b81a1c8 100644 --- a/static/codec-shell.js +++ b/static/codec-shell.js @@ -1471,9 +1471,9 @@ list.innerHTML = (d.global_enabled === false ? '

All triggers are off on this Mac (TRIGGERS_ENABLED).

' : '') + ts.map(function (t) { var state = t.killed ? 'Turned off' : (t.muted ? 'Muted' : 'Active'); - return '
' + esc(t.summary || t.skill_name) + + return '
' + esc(t.label || t.summary || t.skill_name) + '' + esc(state) + '
' + - '

' + esc(t.skill_name) + ' · ' + esc(String(t.type || '').replace(/_/g, ' ')) + '

' + + '

' + esc(t.skill_name) + (t.summary ? ' · rule: ' + esc(t.summary) : '') + '

' + '
' + '' + '' + diff --git a/tests/test_watching.py b/tests/test_watching.py index bc0df88..2c1c4c4 100644 --- a/tests/test_watching.py +++ b/tests/test_watching.py @@ -235,3 +235,14 @@ def test_the_eye_shows_and_pauses_under_jsdom(): assert d["items"][3:] == ["What CODEC sees now", "Automatic triggers", "Observer settings"] assert d["paused"] == ['{"minutes":15}'] assert d["after"][0] is True and re.match(r"Watching paused until \d", d["after"][1]) + + +def test_triggers_get_a_readable_title(obs): + trig = SimpleNamespace(key="k2", skill_name="clipboard_url_fetch", type="clipboard_pattern", + short_summary=lambda: "clipboard~https?://[^\\s]+", cooldown_seconds=60, + require_confirmation=True, destructive=False) + d = obs.rt._trigger_summary(trig) + assert d["label"] == "Clipboard url fetch: when you copy matching text", "a sentence, not the raw pattern" + assert d["summary"].startswith("clipboard~"), "the raw rule is still sent, for the detail line" + shell = (REPO / "static" / "codec-shell.js").read_text(encoding="utf-8") + assert "esc(t.label || t.summary || t.skill_name)" in shell and "' · rule: ' + esc(t.summary)" in shell