fix(sync): wire org skill pull into the runtime; scrub internal jargon

Two defects found by manual testing on the branch.

1. ORG SYNC NEVER RAN. The org pull/mirror/gating machinery was fully
   implemented and unit-tested but had ZERO runtime callers —
   maybe_pull_org_skills() was referenced only inside a comment, and
   `hermes sync` had no org path at all. Every code path fell through to
   personal sync (refs/user/<sub>/), so org skills never loaded and the
   feature looked like 'everything syncs to my personal org' even with a
   valid org token. The unit tests could not catch this: they invoked the
   functions directly, which is exactly the gap they left open.

   - cli.py session startup now calls maybe_pull_org_skills() alongside the
     personal maybe_pull_skills(), fail-quiet.
   - Auto-pull is gated on real org membership: resolve_org_identity()
     requires an org role on the token, only issued for multi-member orgs,
     so a solo account never reaches the network.
   - `hermes sync pull` refreshes the org mirror too (one pull, both
     surfaces) and reports what it refreshed.
   - `hermes sync status` exposes org_available/org_id/org_role/org_skills
     plus a plain-language summary, so a user can tell whether the org
     workflow applies instead of it being invisible.

2. INTERNAL JARGON LEAKED TO USERS. Help text and errors exposed internal
   milestone/spec coordinates: 'Propose a skill ... (M2)', 'Personal skill
   sync (HSP/1)', 'DEV-PHASE gate closed: your token lacks
   tool_gateway_admin', 'contract §4.3', and an inert message describing our
   internal personal-vs-multi-member design split. All rewritten in user
   language. Feature-local comments/docstrings lost their internal
   coordinates (§N, M1/M2, design.md, PR numbers) while keeping the
   explanatory prose. Pre-existing issue references elsewhere in the tree
   were deliberately left untouched.

Tests: 4 new guards, including two that assert the CALL SITES exist so the
org pull cannot silently become dead code again (verified failing when the
wiring is removed) and one that fails if user-facing help leaks jargon.
344 passed across the sync/skills/prompt suites.

Verified against live staging with a real org token: sync status reports
org_available=true, org_role=OWNER; sync pull performs the org refresh; the
.active_org marker is written with the org id from the token.
This commit is contained in:
Ben Barclay
2026-07-27 16:40:16 +10:00
parent 78598d091a
commit 797c52b571
7 changed files with 201 additions and 68 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ EXCLUDED_SKILL_DIRS = frozenset(
# archive workflow preserves a complete old skill package under references/.
SKILL_SUPPORT_DIRS = frozenset(("references", "templates", "assets", "scripts"))
# ── M2 org-shared skills (hsp-1-contract.md §11) ───────────────────────────
# ── Org-shared skills (sync contract) ───────────────────────────
# Org mirrors live under ~/.hermes/skills/_org/<org_id>/. Resolution is
# TOKEN-GATED via a marker file the sync client writes after verifying the
# token (skills_sync_client.pull_org_skills): only the marked org's mirror is