Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codec_chat.html
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@
</style>
</head>
<body>
<script src="/static/codec-shell.js?v=611c650d" data-page="chat" data-title="Chat" data-status data-model-slot></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="chat" data-title="Chat" data-status data-model-slot></script>
<div class="app cs-main" id="appContainer">
<div class="messages" id="messages" role="log" aria-live="polite" aria-label="Conversation"></div>

Expand Down
2 changes: 1 addition & 1 deletion codec_cortex.html
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
</style>
</head>
<body>
<script src="/static/codec-shell.js?v=611c650d" data-page="cortex" data-title="Cortex"></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="cortex" data-title="Cortex"></script>
<div class="cs-main cortex-main">
<div id="stats"></div>
<div id="viewSwitch">
Expand Down
2 changes: 1 addition & 1 deletion codec_dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@
</style>
</head>
<body>
<script src="/static/codec-shell.js?v=611c650d" data-page="home" data-title="Today" data-status></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="home" data-title="Today" data-status></script>

<!-- ── Connect your AI (first run) ─────────────────────────────────────────
Shown until CODEC has a VERIFIED brain. A fresh paid install had no way
Expand Down
2 changes: 1 addition & 1 deletion codec_tasks.html
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@
</style>
</head>
<body>
<script src="/static/codec-shell.js?v=611c650d" data-page="tasks" data-title="Tasks" data-status></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="tasks" data-title="Tasks" data-status></script>
<div class="cs-main cs-scroll">
<div class="container">
<div class="tabs" role="tablist" aria-label="Tasks sections">
Expand Down
2 changes: 1 addition & 1 deletion codec_vibe.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
</style>
</head>
<body>
<script src="/static/codec-shell.js?v=611c650d" data-page="vibe" data-title="Vibe" data-status></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="vibe" data-title="Vibe" data-status></script>
<div class="ov" id="ov" onclick="cS()"></div>
<div class="sd" id="sd" role="dialog" aria-modal="true" aria-label="Projects" data-dialog="sh">
<div style="padding:14px 16px;border-bottom:1px solid var(--bd);display:flex;align-items:center;justify-content:space-between"><h2 style="font-family:var(--mn);font-size:var(--fs-13);color:var(--ac)">PROJECTS</h2><button type="button" onclick="cS()" aria-label="Close projects" data-dialog-close style="background:0;border:0;color:var(--tx2);cursor:pointer;display:flex;padding:0"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg></button></div>
Expand Down
2 changes: 1 addition & 1 deletion codec_voice.html
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@
</style>
</head>
<body id="body">
<script src="/static/codec-shell.js?v=611c650d" data-page="voice" data-title="Voice" data-status></script>
<script src="/static/codec-shell.js?v=95fbf3b8" data-page="voice" data-title="Voice" data-status></script>
<div class="call-container cs-main">

<!-- The orb: its size follows the level. Press and hold it to talk. -->
Expand Down
2 changes: 1 addition & 1 deletion docs/known-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions routes/triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions static/codec-shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -1471,9 +1471,9 @@
list.innerHTML = (d.global_enabled === false ? '<p class="cs-ib-meta">All triggers are off on this Mac (TRIGGERS_ENABLED).</p>' : '') +
ts.map(function (t) {
var state = t.killed ? 'Turned off' : (t.muted ? 'Muted' : 'Active');
return '<div class="cs-ib cs-trig-row"><div class="cs-ib-head"><span class="cs-ib-title">' + esc(t.summary || t.skill_name) +
return '<div class="cs-ib cs-trig-row"><div class="cs-ib-head"><span class="cs-ib-title">' + esc(t.label || t.summary || t.skill_name) +
'</span><span class="cs-ib-when">' + esc(state) + '</span></div>' +
'<p class="cs-ib-meta">' + esc(t.skill_name) + ' · ' + esc(String(t.type || '').replace(/_/g, ' ')) + '</p>' +
'<p class="cs-ib-meta">' + esc(t.skill_name) + (t.summary ? ' · rule: ' + esc(t.summary) : '') + '</p>' +
'<div class="cs-ib-acts">' +
'<button type="button" class="cs-dbtn" data-t="mute" data-key="' + esc(t.trigger_key) + '" data-on="' + (t.muted ? 1 : 0) + '">' + (t.muted ? 'Unmute' : 'Mute') + '</button>' +
'<button type="button" class="cs-dbtn" data-t="kill" data-key="' + esc(t.trigger_key) + '" data-on="' + (t.killed ? 1 : 0) + '">' + (t.killed ? 'Turn on' : 'Turn off') + '</button>' +
Expand Down
11 changes: 11 additions & 0 deletions tests/test_watching.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading