feat(steev): Wave 8 PAUSE-walk — apply Q4-Q10 + bte leak fix + proton-tools SKILL.md

Q4: confirm personal-scope discriminators (chat_facing, delegates_to=[ceo-planb], sovereign_only=false)
Q5: drop google-workspace cred — builtin manages own OAuth via Hermes hub (not credctl vault)
Q6: split proton-bridge-imap → proton-bridge-imap-user + proton-bridge-imap-pass (vault exact-match)
Q7: rename perplexity-api → perplexity (vault exact-match)
Q8: add 3 proton vault entries (account-email, account-password, mailbox-password)
Q9: install.sh F6 — MCP allowlist materialization; wires 3 proton MCPs, removes bte (hard-rule leak)
Q10: macOS-only externals annotated os_constraint:darwin; install.sh F7 emits INFO on non-Darwin

credbridge.sh: drop google-workspace case, rewrite proton-bridge to use 2 vault entries, rename perplexity case
Disclosure §7 rewritten with 6 credentials matching vault exact-name policy (DISCLOSURE-SCHEMA §4.5)
Disclosure §12 PAUSE table marked all 8 rows RESOLVED (rows 1-7 Wave 8, row 8 Wave 7)

Untracked skills/proton-tools/SKILL.md (90 lines, declared in manifest since Wave 4) — committed for clone-ability

Verified:
  hermes -p steev skills list → 6 enabled (matches disclosure.skills declaration)
  hermes -p steev mcp list → 3 entries (proton-calendar, proton-email, proton-contacts); bte removed
  F7 on Linux host correctly suppresses macOS-only externals

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Svrnty
2026-05-24 18:13:40 -04:00
parent 959b8c8871
commit 2491d48151
5 changed files with 253 additions and 67 deletions
+64
View File
@@ -310,8 +310,72 @@ HOOK_EOF
echo " F4 installed: $HOOK_DST"
fi
# F6 — MCP server materialization (Wave 8 Q9)
# Reads manifest.optional_tools (mcp_<server-name-with-underscores> aliases),
# maps to runtime MCP server names (hyphenated), copies global config block
# into per-profile config.yaml. Removes non-declared MCPs (closes bte leak).
if [ "$DRY" = 1 ]; then
echo "DRY: F6 materialize MCP allowlist → $PROFILE_CFG"
elif command -v yq >/dev/null 2>&1 && [ -f "$HERMES_HOME/config.yaml" ]; then
# Declared MCP set (mcp_proton_calendar → proton-calendar etc).
DECLARED_MCPS=$(yq -r '.optional_tools[]?' "$REPO/manifest.yaml" 2>/dev/null | sed 's/^mcp_//; s/_/-/g')
if [ -z "$DECLARED_MCPS" ]; then
echo " F6: no optional_tools declared — skip"
else
mkdir -p "$(dirname "$PROFILE_CFG")"
[ -f "$PROFILE_CFG" ] || : > "$PROFILE_CFG"
F6_ADDED=0; F6_REMOVED=0; F6_MISSING=0
# Set the per-profile mcp_servers block from the declared list. Existing
# entries NOT in declared list are dropped (denylist enforcement).
GLOBAL_CFG="$HERMES_HOME/config.yaml"
python3 - "$GLOBAL_CFG" "$PROFILE_CFG" "$DECLARED_MCPS" <<'PY'
import sys, yaml
gcfg, pcfg, declared_str = sys.argv[1], sys.argv[2], sys.argv[3]
declared = [s.strip() for s in declared_str.splitlines() if s.strip()]
g = yaml.safe_load(open(gcfg).read()) or {}
p = yaml.safe_load(open(pcfg).read()) or {}
g_mcps = g.get('mcp_servers', {}) or {}
new_block = {}
missing = []
for name in declared:
if name in g_mcps:
new_block[name] = g_mcps[name]
else:
missing.append(name)
prev = set((p.get('mcp_servers') or {}).keys())
new = set(new_block.keys())
added = sorted(new - prev)
removed = sorted(prev - new)
p['mcp_servers'] = new_block
open(pcfg, 'w').write(yaml.safe_dump(p, sort_keys=False, allow_unicode=True))
for n in added: print(f" F6 + {n}")
for n in removed: print(f" F6 - {n} (denied)")
for n in missing: print(f" F6 ⚠ {n} (declared but not in global mcp_servers — skipped)")
print(f" F6 wrote mcp_servers: {len(new_block)} entr{'y' if len(new_block)==1 else 'ies'}")
PY
fi
else
echo " WARN: F6 yq/global config missing — skipping MCP materialization"
fi
# F7 — macOS-only externals OS-gate (Wave 8 Q10)
# Reads expected_external_skills entries with os_constraint: darwin and emits
# an INFO line on non-Darwin hosts. No install action (these are external
# prereqs, not provisioned by this installer); annotation is the audit record.
HOST_OS="$(uname -s 2>/dev/null || echo Unknown)"
if [ "$DRY" = 1 ]; then
echo "DRY: F7 OS-gate check (host=$HOST_OS)"
elif command -v yq >/dev/null 2>&1; then
MACOS_ONLY=$(yq -r '.expected_external_skills[] | select(type == "!!map") | select(.os_constraint == "darwin") | .name' "$REPO/manifest.yaml" 2>/dev/null || true)
if [ -n "$MACOS_ONLY" ] && [ "$HOST_OS" != "Darwin" ]; then
echo " F7 INFO: macOS-only externals declared but host=$HOST_OS — unavailable:"
while IFS= read -r s; do [ -n "$s" ] && echo " - $s"; done <<< "$MACOS_ONLY"
fi
fi
echo ""
echo "== done =="
echo " verify skills: hermes -p steev skills list | grep steev-agent"
echo " verify mcp servers: hermes -p steev mcp list"
echo " verify assignee registered: hermes kanban assignees | grep steev"
echo " start gateway (when ready): hermes profile gateway start steev"