Files
state-hub/scripts/register_project.sh
tegwick ad87153f2f Implement registration UX wishlist W1–W6 (260224)
W1: Document user-scope MCP config location in ~/.claude/CLAUDE.md —
    adds verification and re-registration commands, warns against
    settings.json (saves ~12K tokens per registration session).

W2: scripts/register_project.sh + make register-project —
    5-step automation: API health → topic lookup → MCP check →
    CLAUDE.md from template → progress event.

W3: state-hub/scripts/project_claude_md.template —
    parameterised CLAUDE.md with {PROJECT_NAME}/{DOMAIN}/{TOPIC_ID}
    placeholders; used by register_project.sh.

W4: Add custodian_topic_id + domain to all 6 canon project charters —
    lets agents grep for topic IDs without touching the API.

W5: state-hub/mcp_server/TOOLS.md — compact 30-line tool reference
    card; replaces reading the full server.py (~350 lines).

W6: Switch .mcp.json to absolute path + PYTHONPATH env so cwd is not
    required; add scripts/patch_mcp_cwd.py for post-registration fix.
    Update ~/.claude.json to match (cwd kept for belt-and-suspenders).

W7 (SessionStart hook) deferred: no SessionStart hook type in Claude
    Code; PreToolUse with empty matcher fires before every tool call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 22:22:53 +01:00

146 lines
5.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# register_project.sh — register a new project with the Custodian State Hub
#
# Usage: scripts/register_project.sh <domain> <project_path>
# domain: one of custodian|railiance|markitect|coulomb_social|personhood|foerster_capabilities
# project_path: absolute path to the project directory
#
# Example:
# scripts/register_project.sh railiance /home/worsch/railiance
#
# What it does:
# 1. Verify the API is reachable
# 2. Look up the topic ID for the domain
# 3. Check that state-hub is in ~/.claude.json; warn if missing
# 4. Write $project_path/CLAUDE.md from the template (skip if exists)
# 5. POST a progress event recording the registration
set -euo pipefail
DOMAIN="${1:-}"
PROJECT_PATH="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
STATE_HUB_DIR="$(dirname "$SCRIPT_DIR")"
API_BASE="${API_BASE:-http://127.0.0.1:8000}"
# ── Validate args ──────────────────────────────────────────────────────────────
if [[ -z "$DOMAIN" || -z "$PROJECT_PATH" ]]; then
echo "Usage: $0 <domain> <project_path>"
echo " domain: custodian|railiance|markitect|coulomb_social|personhood|foerster_capabilities"
echo " project_path: absolute path to project directory"
exit 1
fi
if [[ ! -d "$PROJECT_PATH" ]]; then
echo "ERROR: project_path does not exist: $PROJECT_PATH"
exit 1
fi
PROJECT_NAME="$(basename "$PROJECT_PATH")"
# ── Step 1: API health check ───────────────────────────────────────────────────
echo "==> Checking API at $API_BASE ..."
if ! curl -sf "$API_BASE/state/health" > /dev/null; then
echo "ERROR: State Hub API is not reachable."
echo " Start it: cd $STATE_HUB_DIR && make api"
echo " (requires postgres: make db first)"
exit 1
fi
echo " API OK"
# ── Step 2: Look up topic ID ───────────────────────────────────────────────────
echo "==> Looking up topic for domain '$DOMAIN' ..."
TOPICS_JSON="$(curl -sf "$API_BASE/topics/?status=active")"
TOPIC_ID="$(echo "$TOPICS_JSON" | python3 -c "
import json, sys
topics = json.load(sys.stdin)
match = next((t for t in topics if t.get('domain') == sys.argv[1]), None)
if not match:
print('NOT_FOUND')
else:
print(match['id'])
" "$DOMAIN")"
if [[ "$TOPIC_ID" == "NOT_FOUND" ]]; then
echo "ERROR: No active topic found for domain '$DOMAIN'."
echo " Known domains: custodian railiance markitect coulomb_social personhood foerster_capabilities"
exit 1
fi
echo " topic_id: $TOPIC_ID"
# ── Step 3: Check MCP registration ────────────────────────────────────────────
echo "==> Checking MCP server registration ..."
MCP_OK="$(python3 -c "
import json
from pathlib import Path
f = Path.home() / '.claude.json'
if not f.exists():
print('MISSING_FILE')
else:
d = json.loads(f.read_text())
servers = d.get('mcpServers', {})
print('OK' if 'state-hub' in servers else 'NOT_REGISTERED')
")"
if [[ "$MCP_OK" == "MISSING_FILE" ]]; then
echo "WARNING: ~/.claude.json not found. MCP server is not registered."
echo " To register:"
echo " MСPCFG=\$(cat $STATE_HUB_DIR/../.mcp.json | python3 -c \"import json,sys; print(json.dumps(json.load(sys.stdin)['mcpServers']['state-hub']))\")"
echo " claude mcp add-json -s user state-hub \"\$MCPCFG\""
echo " python3 $SCRIPT_DIR/patch_mcp_cwd.py"
elif [[ "$MCP_OK" == "NOT_REGISTERED" ]]; then
echo "WARNING: 'state-hub' not found in ~/.claude.json."
echo " To register, see CLAUDE.md MCP Server Registration section."
else
echo " MCP OK"
fi
# ── Step 4: Write CLAUDE.md ────────────────────────────────────────────────────
CLAUDE_MD="$PROJECT_PATH/CLAUDE.md"
TEMPLATE="$SCRIPT_DIR/project_claude_md.template"
if [[ -f "$CLAUDE_MD" ]]; then
echo "==> CLAUDE.md already exists at $CLAUDE_MD — skipping."
else
echo "==> Writing CLAUDE.md to $CLAUDE_MD ..."
sed \
-e "s|{PROJECT_NAME}|$PROJECT_NAME|g" \
-e "s|{DOMAIN}|$DOMAIN|g" \
-e "s|{TOPIC_ID}|$TOPIC_ID|g" \
"$TEMPLATE" > "$CLAUDE_MD"
echo " Written."
fi
# ── Step 5: Record progress event ─────────────────────────────────────────────
echo "==> Recording registration event ..."
EVENT_JSON="$(python3 -c "
import json
payload = {
'topic_id': '$TOPIC_ID',
'event_type': 'milestone',
'summary': 'Project registered with State Hub: $PROJECT_NAME ($DOMAIN)',
'author': 'custodian',
'detail': {
'project_path': '$PROJECT_PATH',
'claude_md': '$CLAUDE_MD',
'domain': '$DOMAIN',
},
}
print(json.dumps(payload))
")"
curl -sf -X POST "$API_BASE/progress/" \
-H "Content-Type: application/json" \
-d "$EVENT_JSON" > /dev/null
echo " Event recorded."
echo ""
echo "Registration complete!"
echo " Project: $PROJECT_NAME"
echo " Domain: $DOMAIN"
echo " Topic ID: $TOPIC_ID"
echo " CLAUDE.md: $CLAUDE_MD"
echo ""
echo "Next: restart Claude Code for the MCP server to be available in this project."