@agentikos/omega-os 0.19.37 → 0.19.39
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/bin/omega-os.js +6 -1
- package/bootstrap/lib/steps.sh +43 -0
- package/install.sh +5 -0
- 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__/cli.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/paperclip_bridge.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/prompt_audit.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/cli.py +73 -0
- package/omega/Agentik_Engine/omega_engine/paperclip_bridge.py +110 -0
- package/omega/Agentik_Engine/omega_engine/prompt_audit.py +395 -0
- package/omega/Agentik_Engine/omega_engine/tmux.py +16 -0
- package/omega/Agentik_Engine/omega_engine/tui.py +269 -67
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_paperclip_status.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_paperclip_status.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_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_installer_wiring.py +130 -0
- package/omega/Agentik_Engine/tests/test_paperclip_status.py +142 -0
- package/omega/Agentik_Engine/tests/test_prompt_audit.py +199 -0
- package/omega/Agentik_Engine/tests/test_tui_runtime.py +106 -0
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/docs/AUDIT-V0.19.38.md +90 -0
- package/omega/Agentik_SSOT/docs/AUDIT-V0.19.39.md +161 -0
- package/omega/Agentik_SSOT/rules/audit-gates.md +189 -0
- package/omega/Agentik_SSOT/rules/constitution.md +7 -0
- package/omega/Agentik_SSOT/rules/orchestration.md +215 -0
- package/omega/Agentik_SSOT/rules/prompt-protocols.md +219 -0
- package/omega/Agentik_SSOT/rules/scope-safety.md +197 -0
- package/omega/Agentik_SSOT/rules/three-laws.md +214 -0
- package/omega/Agentik_SSOT/rules/verified-completion.md +216 -0
- package/package.json +1 -1
package/bin/omega-os.js
CHANGED
|
@@ -36,7 +36,12 @@ console.log(" Omega OS — npx bootstrap");
|
|
|
36
36
|
console.log(" -> handing off to install.sh");
|
|
37
37
|
console.log("");
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
// Drop the literal `--` separator if npx/npm forwarded it. Without this,
|
|
40
|
+
// `npx -y @agentikos/omega-os@latest -- --full` lands in install.sh as
|
|
41
|
+
// `install.sh -- --full`, and the case-block rejects the unknown `--`.
|
|
42
|
+
const rawArgs = process.argv.slice(2);
|
|
43
|
+
const args = rawArgs.filter((a) => a !== "--");
|
|
44
|
+
|
|
40
45
|
const result = spawnSync("bash", [installer, ...args], {
|
|
41
46
|
stdio: "inherit",
|
|
42
47
|
cwd: pkgRoot,
|
package/bootstrap/lib/steps.sh
CHANGED
|
@@ -461,6 +461,49 @@ PY
|
|
|
461
461
|
return $?
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
# --- 38 -----------------------------------------------------------------------
|
|
465
|
+
#
|
|
466
|
+
# step_personas — seed the canonical OmegaOS context + every LLM's
|
|
467
|
+
# expected filename for both chat sessions.
|
|
468
|
+
#
|
|
469
|
+
# Without this step, the canonical OMEGAOS-CONTEXT.md and the per-LLM
|
|
470
|
+
# persona files (CLAUDE.md / GEMINI.md / AGENTS.md / QWEN.md /
|
|
471
|
+
# .opencode/CONTEXT.md / .continue/CONTEXT.md / CONVENTIONS.md /
|
|
472
|
+
# HERMES.md) only land the FIRST time the user spawns AISB-chat or
|
|
473
|
+
# Hermès-chat. Eager seeding lets the operator inspect + edit the
|
|
474
|
+
# canonical at install time and guarantees `omega doctor` sees every
|
|
475
|
+
# persona file before the first session.
|
|
476
|
+
#
|
|
477
|
+
# Idempotent — re-runs only write files whose content actually differs
|
|
478
|
+
# from the canonical.
|
|
479
|
+
step_personas() {
|
|
480
|
+
PYTHONPATH="$OMEGA_HOME/Agentik_Engine" python3 - <<PY 2>>"$LOG_FILE"
|
|
481
|
+
import os
|
|
482
|
+
from pathlib import Path
|
|
483
|
+
os.environ["OMEGA_HOME"] = "$OMEGA_HOME"
|
|
484
|
+
home = Path("$OMEGA_HOME")
|
|
485
|
+
from omega_engine.personas import (
|
|
486
|
+
ensure_canonical, write_all_personas, canonical_path, supported_llm_ids,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
src = ensure_canonical(home)
|
|
490
|
+
print(f" canonical: {src.relative_to(home)} ({src.stat().st_size} bytes)")
|
|
491
|
+
|
|
492
|
+
# Mirror to BOTH chat-context dirs so every LLM has its persona ready
|
|
493
|
+
# from day one — no first-spawn lazy materialization.
|
|
494
|
+
for label in ("aisb-master", "hermes"):
|
|
495
|
+
ctx = home / "Agentik_Coding" / "chat-contexts" / label
|
|
496
|
+
written = write_all_personas(home, ctx)
|
|
497
|
+
# Count EVERY persona file (root + subdir like .opencode/CONTEXT.md).
|
|
498
|
+
files = sorted(str(p.relative_to(ctx))
|
|
499
|
+
for p in ctx.rglob("*.md"))
|
|
500
|
+
print(f" {label}/: {len(files)} persona files ({', '.join(files)})")
|
|
501
|
+
|
|
502
|
+
print(f" supported LLMs: {len(supported_llm_ids())}")
|
|
503
|
+
PY
|
|
504
|
+
return $?
|
|
505
|
+
}
|
|
506
|
+
|
|
464
507
|
# --- 40 -----------------------------------------------------------------------
|
|
465
508
|
#
|
|
466
509
|
# step_clis — install system CLIs + Printing Press CLI library.
|
package/install.sh
CHANGED
|
@@ -62,6 +62,10 @@ while [ $# -gt 0 ]; do
|
|
|
62
62
|
fi
|
|
63
63
|
;;
|
|
64
64
|
-h|--help) awk 'NR==1 && /^#!/ {next} /^#/ {sub(/^#[ ]?/, ""); print; next} {exit}' "$0"; exit 0 ;;
|
|
65
|
+
# Accept the literal `--` separator as a no-op so recipes like
|
|
66
|
+
# `npx -y @agentikos/omega-os@latest -- --full` survive even if the
|
|
67
|
+
# JS launcher's filter is bypassed.
|
|
68
|
+
--) shift ;;
|
|
65
69
|
*) die "unknown argument: $1" ;;
|
|
66
70
|
esac
|
|
67
71
|
done
|
|
@@ -182,6 +186,7 @@ STEPS=(
|
|
|
182
186
|
"35-providers:step_providers"
|
|
183
187
|
"36-tmux-config:step_tmux_config"
|
|
184
188
|
"37-hermes-brief:step_hermes_brief"
|
|
189
|
+
"38-personas:step_personas"
|
|
185
190
|
# v0.19.21 — MCP install dropped from the default sequence. MCPs are
|
|
186
191
|
# token-expensive (each call pays the protocol round-trip + the
|
|
187
192
|
# server's system prompt overhead). We replace with system CLIs +
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -440,6 +440,79 @@ def cmd_doctor(args: argparse.Namespace) -> int:
|
|
|
440
440
|
except Exception as exc: # noqa: BLE001
|
|
441
441
|
line("FAIL", f"agent suite check failed: {exc}")
|
|
442
442
|
|
|
443
|
+
# 7a-bis. Multi-LLM personas — canonical + per-LLM mirrors for the
|
|
444
|
+
# two chat contexts (AISB-master + Hermès). Step 38-personas should
|
|
445
|
+
# have materialized these at install time; if they're missing the
|
|
446
|
+
# user can re-run `omega menu-tui` → "Re-seed personas".
|
|
447
|
+
section("personas")
|
|
448
|
+
try:
|
|
449
|
+
from omega_engine.personas import canonical_path, supported_llm_ids
|
|
450
|
+
canon = canonical_path(home)
|
|
451
|
+
if canon.exists():
|
|
452
|
+
line("ok", f"canonical: {canon.relative_to(home)} ({canon.stat().st_size}B)")
|
|
453
|
+
else:
|
|
454
|
+
line("warn",
|
|
455
|
+
f"canonical missing at {canon.relative_to(home)} — "
|
|
456
|
+
"spawn AISB-chat once or re-run install step 38-personas")
|
|
457
|
+
# Each chat context should have at least one persona file per LLM
|
|
458
|
+
# subgroup. We count both root *.md and subdir CONTEXT.md.
|
|
459
|
+
for label in ("aisb-master", "hermes"):
|
|
460
|
+
ctx = home / "Agentik_Coding" / "chat-contexts" / label
|
|
461
|
+
if not ctx.is_dir():
|
|
462
|
+
line("warn", f"chat-contexts/{label}/ not seeded yet")
|
|
463
|
+
continue
|
|
464
|
+
files = sorted(p.relative_to(ctx).as_posix()
|
|
465
|
+
for p in ctx.rglob("*.md") if p.is_file())
|
|
466
|
+
if files:
|
|
467
|
+
line("ok",
|
|
468
|
+
f"chat-contexts/{label}/: {len(files)} persona file(s) "
|
|
469
|
+
f"({', '.join(files[:4])}{'...' if len(files) > 4 else ''})")
|
|
470
|
+
else:
|
|
471
|
+
line("warn",
|
|
472
|
+
f"chat-contexts/{label}/ exists but has no persona files")
|
|
473
|
+
line("ok", f"supported LLM persona ids: {len(supported_llm_ids())}")
|
|
474
|
+
except Exception as exc: # noqa: BLE001
|
|
475
|
+
line("FAIL", f"personas check failed: {exc}")
|
|
476
|
+
|
|
477
|
+
# 7c. Prompt audit — each AISB role's prompt must reference the
|
|
478
|
+
# Three Laws + LMC protocol + done.json contract. Otherwise the
|
|
479
|
+
# agent runs blind and orchestration breaks at the first dispatch.
|
|
480
|
+
section("prompts")
|
|
481
|
+
try:
|
|
482
|
+
from omega_engine.prompt_audit import audit_aisb_suite
|
|
483
|
+
rep = audit_aisb_suite(home)
|
|
484
|
+
if not rep.per_agent:
|
|
485
|
+
line("warn", "no AISB prompts found — step 25-aisb-suite may have been skipped")
|
|
486
|
+
else:
|
|
487
|
+
for r in rep.per_agent:
|
|
488
|
+
status = "ok" if r.score >= 80 else ("warn" if r.score >= 60 else "FAIL")
|
|
489
|
+
line(status, f"{r.agent_id}: {r.score}/100"
|
|
490
|
+
+ (f" — missing: {', '.join(r.violations[:2])}" if r.violations else ""))
|
|
491
|
+
avg_status = "ok" if rep.average_score >= 80 else "warn"
|
|
492
|
+
line(avg_status, f"average suite score: {rep.average_score:.1f}/100")
|
|
493
|
+
if rep.missing_critical:
|
|
494
|
+
line("warn", f"weak prompts (<60): {', '.join(rep.missing_critical)}")
|
|
495
|
+
except Exception as exc: # noqa: BLE001
|
|
496
|
+
line("FAIL", f"prompt audit failed: {exc}")
|
|
497
|
+
|
|
498
|
+
# 7d. Orchestration chain — AISB → Oracle → Worker → Checker must
|
|
499
|
+
# all be wired and share the LMC protocol vocabulary.
|
|
500
|
+
section("orchestration")
|
|
501
|
+
try:
|
|
502
|
+
from omega_engine.prompt_audit import orchestration_health
|
|
503
|
+
oh = orchestration_health(home)
|
|
504
|
+
for k, v in (("aisb_master_present", "AISB master prompt"),
|
|
505
|
+
("oracle_present", "Oracle role prompt"),
|
|
506
|
+
("workers_role_present", "Worker-class prompts"),
|
|
507
|
+
("checker_present", "Checker prompts (Seraph/Smith)"),
|
|
508
|
+
("lmc_protocol_present", "LMC protocol document")):
|
|
509
|
+
line("ok" if oh.get(k) else "warn", v)
|
|
510
|
+
overlap = oh.get("shared_vocab_overlap", 0.0)
|
|
511
|
+
line("ok" if overlap >= 0.6 else "warn",
|
|
512
|
+
f"shared `.done.json` vocab: {overlap*100:.0f}% of agents")
|
|
513
|
+
except Exception as exc: # noqa: BLE001
|
|
514
|
+
line("FAIL", f"orchestration check failed: {exc}")
|
|
515
|
+
|
|
443
516
|
# 7b. Per-project vaults
|
|
444
517
|
section("project vaults")
|
|
445
518
|
try:
|
|
@@ -26,6 +26,7 @@ from __future__ import annotations
|
|
|
26
26
|
import json
|
|
27
27
|
import os
|
|
28
28
|
import shutil
|
|
29
|
+
import socket
|
|
29
30
|
import subprocess
|
|
30
31
|
import time
|
|
31
32
|
from dataclasses import asdict, dataclass, field
|
|
@@ -584,3 +585,112 @@ def start_server(bind: str = "loopback", *, detach: bool = True) -> int:
|
|
|
584
585
|
)
|
|
585
586
|
return proc.pid
|
|
586
587
|
return subprocess.call(args)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
# ---------------------------------------------------------------------------
|
|
591
|
+
# Live status probe — is the Paperclip dashboard actually running?
|
|
592
|
+
# ---------------------------------------------------------------------------
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
@dataclass
|
|
596
|
+
class PaperclipStatus:
|
|
597
|
+
"""Snapshot of whether the Paperclip dashboard daemon is alive.
|
|
598
|
+
|
|
599
|
+
Consumed by the TUI to render ●/○ next to Paperclip menu items so the
|
|
600
|
+
operator can tell at a glance whether the dashboard is reachable.
|
|
601
|
+
"""
|
|
602
|
+
|
|
603
|
+
running: bool
|
|
604
|
+
pid: int | None # process PID if alive (None for port-scan hits)
|
|
605
|
+
port: int | None # port the dashboard listens on (8080 default)
|
|
606
|
+
url: str | None # http://host:port if running, else None
|
|
607
|
+
detection: str # "pidfile" | "port-scan" | "none"
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
def is_running(omega_home: Path | str | None = None,
|
|
611
|
+
*,
|
|
612
|
+
port: int = 8080,
|
|
613
|
+
host: str = "127.0.0.1") -> PaperclipStatus:
|
|
614
|
+
"""Probe the Paperclip daemon — running or not?
|
|
615
|
+
|
|
616
|
+
Detection strategy (cheap → expensive, returns on first hit):
|
|
617
|
+
1. Read ``$PAPERCLIP_HOME/run/dashboard.pid`` (default ``~/.paperclip``).
|
|
618
|
+
If file exists AND ``os.kill(pid, 0)`` succeeds → running.
|
|
619
|
+
2. Else try TCP connect to ``<host>:<port>`` with a 0.2s timeout.
|
|
620
|
+
If accept → running but no pidfile (caller may warn).
|
|
621
|
+
3. Else → not running.
|
|
622
|
+
|
|
623
|
+
Never raises. Never blocks more than ~0.3s total.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
omega_home: Accepted for API symmetry with the rest of the bridge;
|
|
627
|
+
the actual pidfile lives under ``$PAPERCLIP_HOME`` (resolved
|
|
628
|
+
via :func:`paperclip_home`), not under ``$OMEGA_HOME``.
|
|
629
|
+
port: TCP port to probe in the fallback path. Default 8080.
|
|
630
|
+
host: Loopback host to probe. Default 127.0.0.1.
|
|
631
|
+
|
|
632
|
+
Returns:
|
|
633
|
+
:class:`PaperclipStatus` — never None.
|
|
634
|
+
"""
|
|
635
|
+
del omega_home # signature consistency only; pidfile lives under PAPERCLIP_HOME
|
|
636
|
+
|
|
637
|
+
# ---- 1. Pidfile check (cheapest) -----------------------------------
|
|
638
|
+
pidfile = paperclip_home() / "run" / "dashboard.pid"
|
|
639
|
+
if pidfile.exists():
|
|
640
|
+
try:
|
|
641
|
+
pid_text = pidfile.read_text().strip()
|
|
642
|
+
pid = int(pid_text)
|
|
643
|
+
except (OSError, ValueError):
|
|
644
|
+
pid = None
|
|
645
|
+
if pid is not None and pid > 0:
|
|
646
|
+
alive = False
|
|
647
|
+
try:
|
|
648
|
+
os.kill(pid, 0)
|
|
649
|
+
alive = True
|
|
650
|
+
except ProcessLookupError:
|
|
651
|
+
alive = False
|
|
652
|
+
except PermissionError:
|
|
653
|
+
# PID exists but is owned by another user — still proves
|
|
654
|
+
# SOMETHING is alive at that PID, so treat as running.
|
|
655
|
+
alive = True
|
|
656
|
+
except OSError:
|
|
657
|
+
alive = False
|
|
658
|
+
if alive:
|
|
659
|
+
return PaperclipStatus(
|
|
660
|
+
running=True,
|
|
661
|
+
pid=pid,
|
|
662
|
+
port=port,
|
|
663
|
+
url=f"http://localhost:{port}",
|
|
664
|
+
detection="pidfile",
|
|
665
|
+
)
|
|
666
|
+
# Stale pidfile — fall through to port scan.
|
|
667
|
+
|
|
668
|
+
# ---- 2. Port scan fallback (~0.2s) ---------------------------------
|
|
669
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
670
|
+
try:
|
|
671
|
+
sock.settimeout(0.2)
|
|
672
|
+
try:
|
|
673
|
+
sock.connect((host, port))
|
|
674
|
+
return PaperclipStatus(
|
|
675
|
+
running=True,
|
|
676
|
+
pid=None,
|
|
677
|
+
port=port,
|
|
678
|
+
url=f"http://localhost:{port}",
|
|
679
|
+
detection="port-scan",
|
|
680
|
+
)
|
|
681
|
+
except (OSError, socket.timeout):
|
|
682
|
+
pass
|
|
683
|
+
finally:
|
|
684
|
+
try:
|
|
685
|
+
sock.close()
|
|
686
|
+
except OSError:
|
|
687
|
+
pass
|
|
688
|
+
|
|
689
|
+
# ---- 3. Not running -------------------------------------------------
|
|
690
|
+
return PaperclipStatus(
|
|
691
|
+
running=False,
|
|
692
|
+
pid=None,
|
|
693
|
+
port=None,
|
|
694
|
+
url=None,
|
|
695
|
+
detection="none",
|
|
696
|
+
)
|