From 89458ff4bc0cf3e20373b8f77a0f352ed47a487e Mon Sep 17 00:00:00 2001 From: Micha M <52825236+mimed95@users.noreply.github.com> Date: Sat, 18 Apr 2026 11:05:15 +0000 Subject: [PATCH] harness: tag episodic entries with active profile The portable brain is designed to be mounted by any harness, and many harnesses (Hermes Agent with `--profile`, others in the list that support multi-identity) run several isolated agents against a single brain. Without a profile field on each episodic entry, the dream cycle clusters across all of them as one stream: a lesson graduated from a quant-focused agent's trial-and-error can end up rendered as "agent learned X" alongside a leisure-focused agent's unrelated discovery. Per-agent retrospectives are impossible. This adds a `profile` field to the episodic `source` block: "source": { "skill": "", "profile": "", # new "run_id": "", "commit_sha": "" } Resolution order: 1. `AGENT_PROFILE` env var (canonical; any harness can export this). 2. `HERMES_HOME` basename under `/profiles/` (Hermes-specific fallback so existing Hermes installs Just Work without touching adapter code). 3. "default" when neither applies. No breaking changes: consumers that ignore `source["profile"]` see the same behaviour as before. Cluster.py and promote.py can now partition by profile when that sharpens the review-queue signal; existing code that reads `source` as an opaque blob keeps working. Tested four cases: - default (no env): "default" - AGENT_PROFILE set: value used verbatim - HERMES_HOME under /profiles/fin: "fin" - HERMES_HOME at base: "default" --- .agent/harness/hooks/_provenance.py | 43 ++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/.agent/harness/hooks/_provenance.py b/.agent/harness/hooks/_provenance.py index 0228697..65a0b00 100644 --- a/.agent/harness/hooks/_provenance.py +++ b/.agent/harness/hooks/_provenance.py @@ -5,6 +5,7 @@ _CACHED_COMMIT = None _CACHED_RUN_ID = None +_CACHED_PROFILE = None def run_id(): @@ -14,6 +15,41 @@ def run_id(): return _CACHED_RUN_ID +def profile(): + """Return the active harness profile name, or "default" when unknown. + + Harnesses that run multiple isolated agent identities against the same + portable brain (e.g. Hermes's --profile flag spawning distinct + specialist agents) should set ``AGENT_PROFILE`` to the active name so + every episodic entry is tagged. Enables cross-profile clustering and + per-specialist retrospectives in the dream cycle. + + Fallback detection covers known harnesses without code changes there: + * ``AGENT_PROFILE`` - canonical, any harness. + * ``HERMES_HOME`` - if it points under ``<...>/profiles/`` + use that name; otherwise "default". + """ + global _CACHED_PROFILE + if _CACHED_PROFILE is not None: + return _CACHED_PROFILE + + explicit = os.environ.get("AGENT_PROFILE", "").strip() + if explicit: + _CACHED_PROFILE = explicit + return _CACHED_PROFILE + + hermes_home = os.environ.get("HERMES_HOME", "").rstrip("/") + if hermes_home: + if "/profiles/" in hermes_home: + _CACHED_PROFILE = hermes_home.rsplit("/", 1)[-1] + else: + _CACHED_PROFILE = "default" + return _CACHED_PROFILE + + _CACHED_PROFILE = "default" + return _CACHED_PROFILE + + def commit_sha(): global _CACHED_COMMIT if _CACHED_COMMIT is None: @@ -30,4 +66,9 @@ def commit_sha(): def build_source(skill): - return {"skill": skill, "run_id": run_id(), "commit_sha": commit_sha()} + return { + "skill": skill, + "profile": profile(), + "run_id": run_id(), + "commit_sha": commit_sha(), + }