forked from jason/echo
Phase 2: identity plumbing — group/member config, author: attribution
Config schema {owner,endpoint,key} -> {group, member, endpoint, key}:
- member (kebab-case slug, validated) is REQUIRED — who this machine
writes as; group is the descriptive team name. CHORUS_GROUP/
CHORUS_MEMBER env, config set --group/--member, doctor + config show
both with sources, NOT-CONFIGURED (78) without a valid member.
- capture stamps author: <member> on every note (_build_note); bootstrap
gains {{MEMBER}} substitution and stamps the seeded anchors; all 8
scaffold templates + canonical frontmatter docs gain author:.
- New missing-author lint check: agent_written notes must carry author:
(bootstrap marker exempt — plugin-owned).
- Lock owner is now <member>-<client>-<pid> (auto_owner); offline-queue
records carry a member field for audit.
- build.py --bake-key bakes group/member/endpoint/key (--group/--member;
member required + slug-validated) for per-member artifacts.
- Manifest -> 2.0.0-alpha.2; rebuilt chorus-memory.plugin.
Verified: 25/25 unit (+config/member checks), scaffold suite (+6 new
member/config assertions), routing-sync, 4 mock e2e (+capture-stamps-
author), run_eval metrics unchanged, +8 phase-2 smoke checks green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -76,7 +76,7 @@ class Harness:
|
||||
return None if body == "<<MISSING>>" else body
|
||||
|
||||
def run(self, script, *args, env_extra=None, base=None):
|
||||
env = dict(os.environ, CHORUS_BASE=base or self.base, CHORUS_KEY=KEY,
|
||||
env = dict(os.environ, CHORUS_BASE=base or self.base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member",
|
||||
CHORUS_VERIFY="1", CHORUS_TODAY=TODAY, CHORUS_STATE_DIR=self.state_dir,
|
||||
**(env_extra or {}))
|
||||
return subprocess.run([sys.executable, str(script), *args],
|
||||
|
||||
@@ -52,7 +52,7 @@ class Harness:
|
||||
return None if body == "<<MISSING>>" else body
|
||||
|
||||
def chorus(self, *args):
|
||||
env = dict(os.environ, CHORUS_BASE=self.base, CHORUS_KEY=KEY, CHORUS_VERIFY="1",
|
||||
env = dict(os.environ, CHORUS_BASE=self.base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_VERIFY="1",
|
||||
CHORUS_TODAY="2026-06-21")
|
||||
return subprocess.run([sys.executable, str(args[0]), *args[1:]],
|
||||
capture_output=True, text=True, env=env)
|
||||
@@ -80,6 +80,8 @@ def main():
|
||||
note = h.ground("resources/people/bob-smith.md")
|
||||
check("capture person creates note", note is not None and "type: person" in note, r.stderr)
|
||||
check("capture stamps agent_written", note and "agent_written: true" in note)
|
||||
check("capture stamps author with configured member",
|
||||
note and "author: eval-member" in note)
|
||||
idx = h.ground("_agent/index/entities.json")
|
||||
check("index records entity", idx and "bob-smith" in idx and '"bob"' in idx)
|
||||
|
||||
@@ -91,7 +93,7 @@ def main():
|
||||
# 3. capture a company whose body mentions Bob Smith -> auto bidirectional link
|
||||
r = subprocess.run([sys.executable, str(CHORUS), "capture", "MPM", "--kind", "company", "-"],
|
||||
input="Bob Smith is the principal here.\n", capture_output=True, text=True,
|
||||
env=dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_TODAY="2026-06-21"))
|
||||
env=dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_TODAY="2026-06-21"))
|
||||
mpm = h.ground("resources/companies/mpm.md")
|
||||
bob = h.ground("resources/people/bob-smith.md")
|
||||
check("auto-link forward (mpm -> bob)", mpm and "[[resources/people/bob-smith]]" in mpm, r.stdout + r.stderr)
|
||||
@@ -140,7 +142,7 @@ def main():
|
||||
'{"schema":1,"updated":"2026-06-21","entities":{"ext-entity":'
|
||||
'{"path":"resources/concepts/ext-entity.md","kind":"concept","title":"Ext",'
|
||||
'"aliases":[],"last_seen":"2026-06-21"}}}')
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_TODAY="2026-06-21", PYTHONPATH=str(SCRIPTS))
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_TODAY="2026-06-21", PYTHONPATH=str(SCRIPTS))
|
||||
snippet = ("import chorus_index as ix, chorus_concurrency as c; "
|
||||
"c.atomic_index_update(lambda d: ix.upsert(d,'mine',"
|
||||
"'resources/concepts/mine.md','concept','Mine'))")
|
||||
@@ -184,7 +186,7 @@ def main():
|
||||
r = subprocess.run([sys.executable, str(CHORUS), "capture", "Bob Smith", "-", "--kind", "person"],
|
||||
input="met at expo\nsecond line survives\nthird line too\n",
|
||||
capture_output=True, text=True,
|
||||
env=dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_TODAY="2026-06-21"))
|
||||
env=dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_TODAY="2026-06-21"))
|
||||
bob3 = h.ground("resources/people/bob-smith.md") or ""
|
||||
check("v1.5 update keeps the dated bullet", "- 2026-06-21: met at expo" in bob3, r.stdout + r.stderr)
|
||||
check("v1.5 update keeps EVERY body line",
|
||||
@@ -304,7 +306,7 @@ def main():
|
||||
transcript = tdir / "t.jsonl"
|
||||
turns = [json.dumps({"type": "user", "message": {"content": f"user turn {i}"}}) for i in range(6)]
|
||||
transcript.write_text("\n".join(turns), encoding="utf-8")
|
||||
hook_env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_STATE_DIR=str(tdir))
|
||||
hook_env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_STATE_DIR=str(tdir))
|
||||
payload = json.dumps({"session_id": "s1", "transcript_path": str(transcript),
|
||||
"stop_hook_active": False})
|
||||
HOOK_STOP = SCRIPTS / "chorus_hook_stop.py"
|
||||
|
||||
@@ -59,7 +59,7 @@ def main():
|
||||
state = tempfile.mkdtemp()
|
||||
|
||||
def chorus(base, *args):
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_STATE_DIR=state,
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_STATE_DIR=state,
|
||||
CHORUS_VERIFY="0", CHORUS_TODAY="2026-06-22")
|
||||
return subprocess.run([sys.executable, str(CHORUS), *args], capture_output=True, text=True, env=env)
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ def main():
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
|
||||
def chorus(*args):
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_VERIFY="0")
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_VERIFY="0")
|
||||
return subprocess.run([sys.executable, str(CHORUS), *args], capture_output=True, text=True, env=env)
|
||||
|
||||
def ground(path):
|
||||
|
||||
@@ -51,7 +51,7 @@ def main():
|
||||
return getattr(e, "code", 0), ""
|
||||
|
||||
def chorus(*args, stdin=None):
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_VERIFY="1", CHORUS_TODAY="2026-06-22")
|
||||
env = dict(os.environ, CHORUS_BASE=base, CHORUS_KEY=KEY, CHORUS_MEMBER="eval-member", CHORUS_VERIFY="1", CHORUS_TODAY="2026-06-22")
|
||||
return subprocess.run([sys.executable, str(CHORUS), *args], input=stdin,
|
||||
capture_output=True, text=True, env=env)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user