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:
+64
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user