@agentikos/omega-os 0.19.39 → 0.19.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bootstrap/lib/common.sh +19 -10
- package/bootstrap/templates/aisb/architect.md +27 -1
- package/bootstrap/templates/aisb/construct.md +27 -1
- package/bootstrap/templates/aisb/keymaker.md +27 -1
- package/bootstrap/templates/aisb/link.md +27 -1
- package/bootstrap/templates/aisb/lmc-protocol.md +27 -1
- package/bootstrap/templates/aisb/merovingian.md +27 -1
- package/bootstrap/templates/aisb/morpheus.md +27 -1
- package/bootstrap/templates/aisb/neo.md +27 -1
- package/bootstrap/templates/aisb/niobe.md +27 -1
- package/bootstrap/templates/aisb/oracle.md +27 -1
- package/bootstrap/templates/aisb/pythia.md +36 -0
- package/bootstrap/templates/aisb/seraph.md +27 -1
- package/bootstrap/templates/aisb/smith.md +27 -1
- package/bootstrap/templates/aisb/zion.md +27 -1
- package/omega/Agentik_Engine/omega_engine/__init__.py +1 -1
- package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tui.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/tmux.py +45 -26
- package/omega/Agentik_Engine/omega_engine/tui.py +25 -20
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_prompt_audit.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_prompt_audit.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_palette.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_palette.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tui_runtime.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tui_runtime.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/test_install_ux.py +87 -2
- package/omega/Agentik_Engine/tests/test_prompt_audit.py +82 -0
- package/omega/Agentik_Engine/tests/test_tmux_palette.py +94 -0
- package/omega/Agentik_Engine/tests/test_tui_runtime.py +50 -0
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/docs/AUDIT-V0.19.40.md +163 -0
- package/package.json +1 -1
|
@@ -583,7 +583,7 @@ set -s escape-time 10
|
|
|
583
583
|
# session (AISB / oracle / worker / dev / linear / home / other) without
|
|
584
584
|
# leaving tmux.
|
|
585
585
|
# ════════════════════════════════════════════════════════════════════
|
|
586
|
-
bind-key Z display-popup -E -w
|
|
586
|
+
bind-key Z display-popup -E -w 100% -h 100% "omega tmux menu"
|
|
587
587
|
|
|
588
588
|
# Prefix+S — native session list (tmux's built-in choose-tree)
|
|
589
589
|
bind-key S choose-tree -Zs
|
|
@@ -591,18 +591,28 @@ bind-key S choose-tree -Zs
|
|
|
591
591
|
# Option+/ → session switcher (fzf popup, pick any live tmux session)
|
|
592
592
|
# Option+z → Omega action menu (spawn Omega if missing + switch-client)
|
|
593
593
|
# macOS Option key → enable "Use Option as Meta" in your terminal.
|
|
594
|
-
bind-key -n M-/ display-popup -E -
|
|
594
|
+
bind-key -n M-/ display-popup -E -w 100% -h 100% "omega tmux switcher"
|
|
595
595
|
bind-key -n M-z run-shell -b "tmux has-session -t Omega 2>/dev/null || tmux new-session -d -s Omega -n menu -c $HOME 'omega menu-tui'; tmux switch-client -t Omega"
|
|
596
596
|
|
|
597
597
|
# ════════════════════════════════════════════════════════════════════
|
|
598
|
-
#
|
|
598
|
+
# Pixel/CRT amber theme (tmux-claude inspired)
|
|
599
|
+
# xterm colour137 ≈ #af8700 — amber/gold on whatever your terminal bg is.
|
|
600
|
+
# Theme-neutral: inherits terminal background, works in light + dark.
|
|
599
601
|
# ════════════════════════════════════════════════════════════════════
|
|
600
|
-
set -g status-style "
|
|
601
|
-
set -g status-left
|
|
602
|
-
set -g status-right
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
602
|
+
set -g status-style "fg=default"
|
|
603
|
+
set -g status-left ' #[fg=colour137,bold]Ω #S #[fg=default,nobold]• #[fg=colour137]#(omega tmux count 2>/dev/null) sess #[fg=default]• #[fg=colour137]%H:%M '
|
|
604
|
+
set -g status-right '#[fg=default]TS #[fg=colour137]#(omega tmux count 2>/dev/null) #[fg=default]• #[fg=colour137]Ω '
|
|
605
|
+
|
|
606
|
+
# Hide the window list (tmux-claude clean look).
|
|
607
|
+
setw -g window-status-format ''
|
|
608
|
+
setw -g window-status-current-format ''
|
|
609
|
+
setw -g window-status-separator ''
|
|
610
|
+
|
|
611
|
+
# Pane borders — amber on active, inherit on inactive.
|
|
612
|
+
set -g pane-border-style "fg=default"
|
|
613
|
+
set -g pane-active-border-style "fg=colour137"
|
|
614
|
+
set -g message-style "fg=colour137,bg=default,bold"
|
|
615
|
+
set -g mode-style "fg=default,bg=colour137"
|
|
606
616
|
"""
|
|
607
617
|
|
|
608
618
|
|
|
@@ -681,7 +691,7 @@ set -g @scroll-without-changing-pane on
|
|
|
681
691
|
# Prefix+Z — OmegaOS session picker
|
|
682
692
|
# Opens a tmux popup with `omega tmux menu`.
|
|
683
693
|
# ════════════════════════════════════════════════════════════════════
|
|
684
|
-
bind-key Z display-popup -E -w
|
|
694
|
+
bind-key Z display-popup -E -w 100% -h 100% "omega tmux menu"
|
|
685
695
|
|
|
686
696
|
# Prefix+S — native choose-tree
|
|
687
697
|
bind-key S choose-tree -Zs
|
|
@@ -709,30 +719,39 @@ bind-key r source-file ~/.tmux.conf \\; display-message "tmux.conf reloaded"
|
|
|
709
719
|
# ────────────────────────────────────────────────────────────────────
|
|
710
720
|
# popup -E runs the command in a tmux popup overlay (modal). The popup
|
|
711
721
|
# closes when the command exits, returning the user to their previous
|
|
712
|
-
# pane. -
|
|
713
|
-
bind-key -n M-/ display-popup -E -
|
|
722
|
+
# pane. -w 100% -h 100% gives a full-screen popup (tmux-claude style).
|
|
723
|
+
bind-key -n M-/ display-popup -E -w 100% -h 100% "omega tmux switcher"
|
|
714
724
|
bind-key -n M-z run-shell -b "tmux has-session -t Omega 2>/dev/null || tmux new-session -d -s Omega -n menu -c $HOME 'omega menu-tui'; tmux switch-client -t Omega"
|
|
715
725
|
|
|
716
726
|
# ════════════════════════════════════════════════════════════════════
|
|
717
|
-
#
|
|
727
|
+
# Pixel/CRT amber theme (tmux-claude inspired)
|
|
718
728
|
# ════════════════════════════════════════════════════════════════════
|
|
719
|
-
#
|
|
720
|
-
#
|
|
721
|
-
#
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
729
|
+
# xterm colour137 ≈ #af8700 — amber/gold. Theme-neutral: status bar
|
|
730
|
+
# inherits the terminal background, so it looks right in any color
|
|
731
|
+
# scheme (dark, light, solarized, etc.).
|
|
732
|
+
#
|
|
733
|
+
# Bullets `•` everywhere as separators, accent colour137 for values,
|
|
734
|
+
# default fg for labels. Window list HIDDEN (tmux-claude clean look) —
|
|
735
|
+
# the operator switches via Option+/ or `omega tmux menu` instead.
|
|
736
|
+
set -g status-style "fg=default"
|
|
737
|
+
set -g status-left ' #[fg=colour137,bold]Ω #S #[fg=default,nobold]• #[fg=colour137]#(omega tmux count 2>/dev/null) sess #[fg=default]• #[fg=colour137]%H:%M '
|
|
738
|
+
set -g status-right '#[fg=default]CPU #[fg=colour137]#(awk "{print int(\\$1*100/$(nproc))}" /proc/loadavg 2>/dev/null || echo --)% #[fg=default]• #[fg=colour137]Ω v#(cat $OMEGA_HOME/Agentik_SSOT/VERSION 2>/dev/null || echo dev) '
|
|
725
739
|
set -g status-interval 5
|
|
726
|
-
set -g status-left-length
|
|
740
|
+
set -g status-left-length 60
|
|
727
741
|
set -g status-right-length 60
|
|
728
742
|
|
|
729
|
-
#
|
|
730
|
-
|
|
731
|
-
|
|
743
|
+
# Hide the window list (tmux-claude clean look).
|
|
744
|
+
setw -g window-status-format ''
|
|
745
|
+
setw -g window-status-current-format ''
|
|
746
|
+
setw -g window-status-separator ''
|
|
747
|
+
|
|
748
|
+
# Pane borders — amber on active, inherit on inactive.
|
|
749
|
+
set -g pane-border-style "fg=default"
|
|
750
|
+
set -g pane-active-border-style "fg=colour137"
|
|
732
751
|
|
|
733
|
-
# Message + copy-mode prompts —
|
|
734
|
-
set -g message-style "bg
|
|
735
|
-
set -g mode-style "bg
|
|
752
|
+
# Message + copy-mode prompts — amber on terminal bg.
|
|
753
|
+
set -g message-style "fg=colour137,bg=default,bold"
|
|
754
|
+
set -g mode-style "fg=default,bg=colour137"
|
|
736
755
|
"""
|
|
737
756
|
|
|
738
757
|
|
|
@@ -441,11 +441,16 @@ def _arrow_menu() -> int:
|
|
|
441
441
|
OMEGA_BIN = str(HOME / "Agentik_Tools" / "bin" / "omega")
|
|
442
442
|
|
|
443
443
|
# ANSI escapes — used via fzf --ansi.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
# Pixel/CRT amber palette — colour137 family.
|
|
445
|
+
# Inherits terminal background (no cream); accent = amber gold.
|
|
446
|
+
AMBER = "\033[38;5;137m" # xterm 256 colour137 = amber gold
|
|
447
|
+
AMBER_BR = "\033[38;5;215m" # brighter amber for active/highlighted rows
|
|
448
|
+
MUTED = "\033[38;5;240m" # dim gray
|
|
449
|
+
BOLD = "\033[1m"
|
|
450
|
+
DIM = "\033[2m"
|
|
451
|
+
RST = "\033[0m"
|
|
452
|
+
# Backward-compat alias — existing code may reference ORANGE.
|
|
453
|
+
ORANGE = AMBER
|
|
449
454
|
|
|
450
455
|
def _label(name: str, hint: str = "") -> str:
|
|
451
456
|
"""Two-column label: name on the left, hint dimmed on the right."""
|
|
@@ -469,7 +474,7 @@ def _arrow_menu() -> int:
|
|
|
469
474
|
# a short "MENU" section. Reasoning: the user spends 99% of their
|
|
470
475
|
# time in conversations — the menu should reflect that, not bury the
|
|
471
476
|
# chats below 6 sections of admin options.
|
|
472
|
-
DOT_ON = f"{
|
|
477
|
+
DOT_ON = f"{AMBER}●{RST}" # alive
|
|
473
478
|
DOT_OFF = f"{MUTED}○{RST}" # not running
|
|
474
479
|
|
|
475
480
|
def _dot(alive: bool) -> str:
|
|
@@ -700,20 +705,20 @@ def _arrow_menu() -> int:
|
|
|
700
705
|
"--pointer=▶",
|
|
701
706
|
"--marker=●",
|
|
702
707
|
"--color="
|
|
703
|
-
"bg
|
|
704
|
-
"fg
|
|
705
|
-
"bg+:#
|
|
706
|
-
"fg
|
|
707
|
-
"hl
|
|
708
|
-
"hl
|
|
709
|
-
"prompt
|
|
710
|
-
"pointer
|
|
711
|
-
"marker
|
|
712
|
-
"header
|
|
713
|
-
"border
|
|
714
|
-
"info
|
|
715
|
-
"spinner
|
|
716
|
-
"gutter
|
|
708
|
+
"bg:-1,"
|
|
709
|
+
"fg:default,"
|
|
710
|
+
"bg+:#1c1c1c,"
|
|
711
|
+
"fg+:colour215,"
|
|
712
|
+
"hl:colour137,"
|
|
713
|
+
"hl+:colour215,"
|
|
714
|
+
"prompt:colour137,"
|
|
715
|
+
"pointer:colour137,"
|
|
716
|
+
"marker:colour215,"
|
|
717
|
+
"header:colour137,"
|
|
718
|
+
"border:colour137,"
|
|
719
|
+
"info:colour137,"
|
|
720
|
+
"spinner:colour137,"
|
|
721
|
+
"gutter:-1"],
|
|
717
722
|
input="\n".join(lines), capture_output=True, text=True,
|
|
718
723
|
)
|
|
719
724
|
except (KeyboardInterrupt, subprocess.SubprocessError):
|
|
Binary file
|
|
Binary file
|
package/omega/Agentik_Engine/tests/__pycache__/test_prompt_audit.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/omega/Agentik_Engine/tests/__pycache__/test_tui_runtime.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -18,8 +18,14 @@ COMMON_SH = REPO_ROOT / "bootstrap" / "lib" / "common.sh"
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def _bash(snippet: str, *, env: dict[str, str] | None = None,
|
|
21
|
-
stdin: str = "") -> tuple[int, str, str]:
|
|
22
|
-
"""Run a bash snippet that sources common.sh; return (rc, stdout, stderr).
|
|
21
|
+
stdin: str = "", raw: bool = False) -> tuple[int, str, str]:
|
|
22
|
+
"""Run a bash snippet that sources common.sh; return (rc, stdout, stderr).
|
|
23
|
+
|
|
24
|
+
raw=True disables Python's universal-newlines translation so callers can
|
|
25
|
+
distinguish CR (\\r — progress-bar overwrite) from LF (\\n — newline).
|
|
26
|
+
Without it, `text=True` collapses both into "\\n" and tests that count
|
|
27
|
+
newlines lose the signal they need.
|
|
28
|
+
"""
|
|
23
29
|
base_env = {**os.environ}
|
|
24
30
|
base_env.setdefault("OMEGA_REPO", str(REPO_ROOT))
|
|
25
31
|
base_env.setdefault("OMEGA_HOME", "/tmp/omega-ux-pytest")
|
|
@@ -40,6 +46,14 @@ def _bash(snippet: str, *, env: dict[str, str] | None = None,
|
|
|
40
46
|
"C_BOLD=''; C_CYAN=''; C_GREEN=''; C_YELLOW=''; C_RED=''; C_MAGENTA=''; C_BLUE=''\n"
|
|
41
47
|
+ snippet
|
|
42
48
|
)
|
|
49
|
+
if raw:
|
|
50
|
+
proc = subprocess.run(
|
|
51
|
+
["bash", "-c", code],
|
|
52
|
+
env=base_env, capture_output=True, input=stdin.encode("utf-8"),
|
|
53
|
+
timeout=15,
|
|
54
|
+
)
|
|
55
|
+
return proc.returncode, proc.stdout.decode("utf-8", "replace"), \
|
|
56
|
+
proc.stderr.decode("utf-8", "replace")
|
|
43
57
|
proc = subprocess.run(
|
|
44
58
|
["bash", "-c", code],
|
|
45
59
|
env=base_env, capture_output=True, text=True, input=stdin,
|
|
@@ -131,6 +145,77 @@ class TestPathSetup(unittest.TestCase):
|
|
|
131
145
|
self.assertEqual(rc_path.read_text(), "# only this\n")
|
|
132
146
|
|
|
133
147
|
|
|
148
|
+
class TestProgressBarCountingDiscipline(unittest.TestCase):
|
|
149
|
+
"""Regression tests for the v0.19.x progress-bar double-count bug.
|
|
150
|
+
|
|
151
|
+
`run_step` calls `_full_progress` TWICE per step ("run" then "ok"). The
|
|
152
|
+
old implementation incremented STEP_COUNT on EVERY call, which with
|
|
153
|
+
STEP_TOTAL=21 drove the counter to 42, the bar to 200%, and the "current
|
|
154
|
+
>= total → newline" branch fired four+ times — so the user saw the
|
|
155
|
+
progress bar spawn fresh lines mid-install instead of overwriting one
|
|
156
|
+
single line. The fix: only "ok"/"skip" count as real progress; "run"
|
|
157
|
+
just re-paints the bar with the in-progress step name.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def test_full_progress_counts_only_ok_and_skip(self):
|
|
161
|
+
rc, out, _ = _bash(
|
|
162
|
+
"export STEP_TOTAL=10\n"
|
|
163
|
+
"_full_progress a run\n"
|
|
164
|
+
"_full_progress a ok\n"
|
|
165
|
+
"_full_progress b run\n"
|
|
166
|
+
"_full_progress b skip\n"
|
|
167
|
+
"echo STEP_COUNT=$STEP_COUNT\n"
|
|
168
|
+
)
|
|
169
|
+
self.assertEqual(rc, 0)
|
|
170
|
+
# Two runs + one ok + one skip → count should be 2 (only ok+skip count).
|
|
171
|
+
self.assertIn("STEP_COUNT=2", out)
|
|
172
|
+
|
|
173
|
+
def test_no_premature_newline_in_middle_of_run(self):
|
|
174
|
+
# STEP_TOTAL=2 so the second "ok" hits the boundary; nothing before
|
|
175
|
+
# that may emit a newline. With the old code, the boundary fired on
|
|
176
|
+
# the very FIRST "ok" (count had ticked to 2 already because run+ok
|
|
177
|
+
# = +2 instead of +1), producing a stray mid-install newline.
|
|
178
|
+
# raw=True so Python doesn't fold \r into \n via universal-newlines.
|
|
179
|
+
rc, out, _ = _bash(
|
|
180
|
+
"export STEP_TOTAL=2\n"
|
|
181
|
+
"_full_progress a run\n"
|
|
182
|
+
"_full_progress a ok\n"
|
|
183
|
+
"_full_progress b run\n"
|
|
184
|
+
"_full_progress b ok\n",
|
|
185
|
+
raw=True,
|
|
186
|
+
)
|
|
187
|
+
self.assertEqual(rc, 0)
|
|
188
|
+
# Frames are separated by \r (carriage return → overwrite the line),
|
|
189
|
+
# NOT \n. Exactly one \n — emitted ONLY after the final "ok" crosses total.
|
|
190
|
+
self.assertEqual(out.count("\n"), 1,
|
|
191
|
+
f"expected 1 trailing newline, got {out.count(chr(10))}: {out!r}")
|
|
192
|
+
# Carriage returns prove the frames overwrote rather than scrolled.
|
|
193
|
+
self.assertGreaterEqual(out.count("\r"), 3)
|
|
194
|
+
# Final frame must read 2/2 100% — not 3/2 150% or 4/2 200% like the bug.
|
|
195
|
+
self.assertIn("2/2", out)
|
|
196
|
+
self.assertIn("100%", out)
|
|
197
|
+
self.assertNotIn("3/2", out)
|
|
198
|
+
self.assertNotIn("4/2", out)
|
|
199
|
+
self.assertNotIn("150%", out)
|
|
200
|
+
self.assertNotIn("200%", out)
|
|
201
|
+
|
|
202
|
+
def test_run_phase_shows_in_progress_step_name(self):
|
|
203
|
+
# The "run" phase should re-paint with the step name being attempted
|
|
204
|
+
# so the user sees what's currently happening, even though the count
|
|
205
|
+
# hasn't bumped yet.
|
|
206
|
+
rc, out, _ = _bash(
|
|
207
|
+
"export STEP_TOTAL=5\n"
|
|
208
|
+
"_full_progress mystep run\n",
|
|
209
|
+
raw=True,
|
|
210
|
+
)
|
|
211
|
+
self.assertEqual(rc, 0)
|
|
212
|
+
self.assertIn("mystep", out)
|
|
213
|
+
# Count is still 0 because nothing has finished yet.
|
|
214
|
+
self.assertIn("0/5", out)
|
|
215
|
+
# And critically — no newline during a "run" frame.
|
|
216
|
+
self.assertEqual(out.count("\n"), 0)
|
|
217
|
+
|
|
218
|
+
|
|
134
219
|
class TestPostInstallCard(unittest.TestCase):
|
|
135
220
|
def test_card_includes_status_and_next_steps(self):
|
|
136
221
|
# omega CLI isn't on PATH inside the test sandbox → readiness=UNKNOWN
|
|
@@ -195,5 +195,87 @@ class TestAuditAisbSuiteAgainstRealRepo(unittest.TestCase):
|
|
|
195
195
|
self.assertLessEqual(overlap, 1.0)
|
|
196
196
|
|
|
197
197
|
|
|
198
|
+
class TestEnrichedRolePromptsRegression(unittest.TestCase):
|
|
199
|
+
"""v0.19.40 — every AISB role prompt was enriched with a uniform
|
|
200
|
+
`THREE LAWS + Operating Contract` block (Three Laws + LMC protocol
|
|
201
|
+
ref + .done.json contract + done-marker + fresh-context handoff).
|
|
202
|
+
The audit went from 52.0/100 average → 98.3/100. These tests lock in
|
|
203
|
+
that quality floor so a future template edit can't silently drop a
|
|
204
|
+
role below the contract."""
|
|
205
|
+
|
|
206
|
+
def test_every_aisb_role_scores_at_least_80(self):
|
|
207
|
+
if not TEMPLATES.is_dir():
|
|
208
|
+
self.skipTest("AISB templates not present in repo")
|
|
209
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
210
|
+
home = _seed_real_aisb(Path(tmp))
|
|
211
|
+
report = audit_aisb_suite(home)
|
|
212
|
+
below = [(r.agent_id, r.score) for r in report.per_agent if r.score < 80]
|
|
213
|
+
self.assertEqual(below, [],
|
|
214
|
+
f"v0.19.40 contract requires every role ≥80/100. "
|
|
215
|
+
f"Regression: {below} — re-enrich the failing role with "
|
|
216
|
+
f"the THREE LAWS + Operating Contract block.")
|
|
217
|
+
|
|
218
|
+
def test_average_suite_score_at_least_85(self):
|
|
219
|
+
if not TEMPLATES.is_dir():
|
|
220
|
+
self.skipTest("AISB templates not present in repo")
|
|
221
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
222
|
+
home = _seed_real_aisb(Path(tmp))
|
|
223
|
+
report = audit_aisb_suite(home)
|
|
224
|
+
self.assertGreaterEqual(
|
|
225
|
+
report.average_score, 85.0,
|
|
226
|
+
f"v0.19.40 baseline: 98.3 average. Floor: 85. "
|
|
227
|
+
f"Got {report.average_score:.1f} — investigate which roles "
|
|
228
|
+
f"lost contract references.")
|
|
229
|
+
|
|
230
|
+
def test_done_json_vocab_overlap_at_least_80_percent(self):
|
|
231
|
+
"""Before v0.19.40 only 33% of roles referenced `.done.json`
|
|
232
|
+
in their on-disk file (the rest relied on the loader to concat
|
|
233
|
+
lmc-protocol.md at spawn). The enrichment brought it to 100%."""
|
|
234
|
+
if not TEMPLATES.is_dir():
|
|
235
|
+
self.skipTest("AISB templates not present in repo")
|
|
236
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
237
|
+
home = _seed_real_aisb(Path(tmp))
|
|
238
|
+
oh = orchestration_health(home)
|
|
239
|
+
self.assertGreaterEqual(
|
|
240
|
+
oh["shared_vocab_overlap"], 0.80,
|
|
241
|
+
f"`.done.json` vocab overlap must stay ≥80% — "
|
|
242
|
+
f"got {oh['shared_vocab_overlap']*100:.0f}%. "
|
|
243
|
+
f"A role file lost its done.json reference.")
|
|
244
|
+
|
|
245
|
+
def test_every_role_references_lmc_protocol(self):
|
|
246
|
+
"""The LMC protocol must be named in every role file (not just
|
|
247
|
+
implicit via the loader's concat). Direct grep check."""
|
|
248
|
+
if not TEMPLATES.is_dir():
|
|
249
|
+
self.skipTest("AISB templates not present in repo")
|
|
250
|
+
import re as _re
|
|
251
|
+
lmc_re = _re.compile(
|
|
252
|
+
r"(lmc[\s\-_]*(protocol|gate)?|lead[\s\-]+manager[\s\-]+checker|"
|
|
253
|
+
r"lmc-protocol\.md)",
|
|
254
|
+
_re.IGNORECASE,
|
|
255
|
+
)
|
|
256
|
+
missing = []
|
|
257
|
+
for md in sorted(TEMPLATES.glob("*.md")):
|
|
258
|
+
if not lmc_re.search(md.read_text()):
|
|
259
|
+
missing.append(md.name)
|
|
260
|
+
self.assertEqual(missing, [],
|
|
261
|
+
f"Every AISB role must reference the LMC protocol — "
|
|
262
|
+
f"missing in: {missing}")
|
|
263
|
+
|
|
264
|
+
def test_every_role_references_three_laws(self):
|
|
265
|
+
"""Three Laws must be present (not just two). Pre-v0.19.40
|
|
266
|
+
most roles only had LAW 1 + LAW 2. Now LAW 3 is mandatory."""
|
|
267
|
+
if not TEMPLATES.is_dir():
|
|
268
|
+
self.skipTest("AISB templates not present in repo")
|
|
269
|
+
missing_third = []
|
|
270
|
+
for md in sorted(TEMPLATES.glob("*.md")):
|
|
271
|
+
text = md.read_text()
|
|
272
|
+
# Match LAW 3 or 'Third Law' or 'law 3' — same regex as the audit.
|
|
273
|
+
if "LAW 3" not in text and "Third Law" not in text.lower():
|
|
274
|
+
missing_third.append(md.name)
|
|
275
|
+
self.assertEqual(missing_third, [],
|
|
276
|
+
f"Every AISB role must reference LAW 3 (autonomous execution). "
|
|
277
|
+
f"Missing in: {missing_third}")
|
|
278
|
+
|
|
279
|
+
|
|
198
280
|
if __name__ == "__main__":
|
|
199
281
|
unittest.main()
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Regression tests for the bundled tmux palette.
|
|
2
|
+
|
|
3
|
+
We swapped the Claude-cream/orange paper theme (#FAFAF7 / #D97757) for
|
|
4
|
+
the tmux-claude pixel/CRT amber palette (xterm colour137 ≈ #af8700).
|
|
5
|
+
These tests pin the new palette so a future drift back to the old
|
|
6
|
+
theme fails loudly.
|
|
7
|
+
|
|
8
|
+
Pinned behaviour:
|
|
9
|
+
|
|
10
|
+
1. The pro config uses ``colour137`` (the amber accent) in multiple
|
|
11
|
+
places — status bar, pane borders, message style.
|
|
12
|
+
2. The old Claude paper palette (#FAFAF7 cream + #D97757 orange) is
|
|
13
|
+
completely gone from the pro config.
|
|
14
|
+
3. The window list is hidden (tmux-claude clean look — the operator
|
|
15
|
+
navigates via Option+/ or `omega tmux menu`, not the window bar).
|
|
16
|
+
4. The popup keybinds use the full-screen ``-w 100% -h 100%`` sizing
|
|
17
|
+
from tmux-claude (the old config used the smaller 80%/90% boxes).
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import sys
|
|
22
|
+
import unittest
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
HERE = Path(__file__).resolve().parent
|
|
26
|
+
sys.path.insert(0, str(HERE.parent))
|
|
27
|
+
|
|
28
|
+
from omega_engine.tmux import _PRO_CONFIG # noqa: E402
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TestTmuxClaudePalette(unittest.TestCase):
|
|
32
|
+
def test_pro_config_uses_colour137(self):
|
|
33
|
+
"""Amber accent ``colour137`` must show up in at least 4 places.
|
|
34
|
+
|
|
35
|
+
Typically: status-left accent, status-right accent, pane-active
|
|
36
|
+
border, message-style — plus possibly mode-style. We assert >= 4
|
|
37
|
+
so a partial revert still trips the test.
|
|
38
|
+
"""
|
|
39
|
+
n = _PRO_CONFIG.count("colour137")
|
|
40
|
+
self.assertGreaterEqual(
|
|
41
|
+
n, 4,
|
|
42
|
+
f"_PRO_CONFIG must reference colour137 at least 4 times "
|
|
43
|
+
f"(status accents + active border + message/mode style); "
|
|
44
|
+
f"found {n}",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def test_no_claude_cream_orange_palette(self):
|
|
48
|
+
"""The old paper theme (#FAFAF7 + #D97757) must be gone."""
|
|
49
|
+
self.assertNotIn(
|
|
50
|
+
"#FAFAF7", _PRO_CONFIG,
|
|
51
|
+
"Old Claude cream bg #FAFAF7 must not appear in _PRO_CONFIG",
|
|
52
|
+
)
|
|
53
|
+
self.assertNotIn(
|
|
54
|
+
"#D97757", _PRO_CONFIG,
|
|
55
|
+
"Old Claude orange accent #D97757 must not appear in _PRO_CONFIG",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def test_window_status_hidden(self):
|
|
59
|
+
"""Window list is hidden — both empty format strings present."""
|
|
60
|
+
self.assertIn(
|
|
61
|
+
"window-status-format ''", _PRO_CONFIG,
|
|
62
|
+
"Inactive window list must be hidden (window-status-format '')",
|
|
63
|
+
)
|
|
64
|
+
self.assertIn(
|
|
65
|
+
"window-status-current-format ''", _PRO_CONFIG,
|
|
66
|
+
"Active window must be hidden too (window-status-current-format '')",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def test_popup_keybinds_use_full_screen(self):
|
|
70
|
+
"""The M-/ session switcher popup uses full-screen sizing."""
|
|
71
|
+
self.assertIn(
|
|
72
|
+
"-w 100% -h 100%", _PRO_CONFIG,
|
|
73
|
+
"Popup keybinds must use full-screen tmux-claude sizing "
|
|
74
|
+
"(-w 100% -h 100%)",
|
|
75
|
+
)
|
|
76
|
+
# Specifically the M-/ binding (the canonical session switcher).
|
|
77
|
+
# We grep the relevant line to make sure 100%/100% is wired there
|
|
78
|
+
# — not just present elsewhere by coincidence.
|
|
79
|
+
m_slash_lines = [
|
|
80
|
+
ln for ln in _PRO_CONFIG.splitlines() if "M-/" in ln
|
|
81
|
+
]
|
|
82
|
+
self.assertTrue(
|
|
83
|
+
m_slash_lines,
|
|
84
|
+
"_PRO_CONFIG must keep the M-/ popup binding",
|
|
85
|
+
)
|
|
86
|
+
self.assertTrue(
|
|
87
|
+
any("-w 100% -h 100%" in ln for ln in m_slash_lines),
|
|
88
|
+
"M-/ popup binding must use -w 100% -h 100% "
|
|
89
|
+
"(full-screen tmux-claude style)",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
unittest.main(verbosity=2)
|
|
@@ -269,6 +269,56 @@ class TestChatFirstRedesign(unittest.TestCase):
|
|
|
269
269
|
self.assertIn("paperclip_bridge", src)
|
|
270
270
|
|
|
271
271
|
|
|
272
|
+
class TestPixelPalette(unittest.TestCase):
|
|
273
|
+
"""Pixel/CRT amber palette — colour137 family. Locks in the
|
|
274
|
+
replacement of the Claude cream/orange palette with a retro-CRT
|
|
275
|
+
amber accent that inherits the terminal background, matching the
|
|
276
|
+
look-and-feel reference from agentik-os/tmux-claude."""
|
|
277
|
+
|
|
278
|
+
def test_amber_constant_defined(self):
|
|
279
|
+
"""`AMBER` must be declared in `_arrow_menu` — it's the new
|
|
280
|
+
primary accent color (xterm 256 colour137 = amber gold)."""
|
|
281
|
+
import inspect
|
|
282
|
+
from omega_engine.tui import _arrow_menu
|
|
283
|
+
src = inspect.getsource(_arrow_menu)
|
|
284
|
+
self.assertIn("AMBER", src,
|
|
285
|
+
"_arrow_menu must declare AMBER (the new colour137 accent)")
|
|
286
|
+
|
|
287
|
+
def test_colour137_in_fzf_args(self):
|
|
288
|
+
"""The fzf `--color=` block must use the xterm `colour137`
|
|
289
|
+
named amber — that's the look-and-feel reference."""
|
|
290
|
+
import inspect
|
|
291
|
+
from omega_engine.tui import _arrow_menu
|
|
292
|
+
src = inspect.getsource(_arrow_menu)
|
|
293
|
+
self.assertIn("colour137", src,
|
|
294
|
+
"fzf --color= block must use colour137 (amber gold) — "
|
|
295
|
+
"the pixel/CRT palette references it explicitly")
|
|
296
|
+
|
|
297
|
+
def test_no_claude_cream_orange_in_fzf(self):
|
|
298
|
+
"""The old Claude cream `#FAFAF7` background must NOT appear in
|
|
299
|
+
`_arrow_menu` anymore — the new palette inherits the terminal
|
|
300
|
+
background (`bg:-1`) for a transparent retro feel."""
|
|
301
|
+
import inspect
|
|
302
|
+
from omega_engine.tui import _arrow_menu
|
|
303
|
+
src = inspect.getsource(_arrow_menu)
|
|
304
|
+
self.assertNotIn("#FAFAF7", src,
|
|
305
|
+
"_arrow_menu must NOT contain Claude cream #FAFAF7 — "
|
|
306
|
+
"the new palette inherits the terminal background")
|
|
307
|
+
|
|
308
|
+
def test_orange_aliased_to_amber(self):
|
|
309
|
+
"""Backward-compat: `ORANGE` must alias `AMBER` so existing
|
|
310
|
+
references (`_section`, `_label`, prompts) keep working with
|
|
311
|
+
only a color change, no logic change."""
|
|
312
|
+
import inspect
|
|
313
|
+
from omega_engine.tui import _arrow_menu
|
|
314
|
+
src = inspect.getsource(_arrow_menu)
|
|
315
|
+
# Tolerate any reasonable spacing around `=`.
|
|
316
|
+
import re
|
|
317
|
+
self.assertRegex(src, r"ORANGE\s*=\s*AMBER",
|
|
318
|
+
"ORANGE must alias AMBER (backward-compat for existing "
|
|
319
|
+
"_section/_label/prompt code)")
|
|
320
|
+
|
|
321
|
+
|
|
272
322
|
class TestOmegaWindowAliveHelper(unittest.TestCase):
|
|
273
323
|
"""tmux.omega_window_alive() — the helper the chat-first TUI uses
|
|
274
324
|
to know whether AISB-chat / Hermès-chat are running."""
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.19.
|
|
1
|
+
0.19.40
|