From b949a11f2036d831d7c1615900007a2b9f1aace0 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 28 Feb 2026 15:40:32 +0100 Subject: [PATCH] fix(cli): auto-create topic when registering a brand-new domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit register-project now creates a topic automatically if the domain has no active topic yet, instead of exiting with an error. This makes the "create domain → register project" flow self-contained. Co-Authored-By: Claude Sonnet 4.6 --- state-hub/custodian_cli.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/state-hub/custodian_cli.py b/state-hub/custodian_cli.py index 962edba..4a9dd38 100644 --- a/state-hub/custodian_cli.py +++ b/state-hub/custodian_cli.py @@ -97,13 +97,24 @@ def cmd_register(args: argparse.Namespace) -> None: print(f"ERROR: Unknown domain '{domain}'. Valid: {', '.join(valid_domains)}") sys.exit(1) - # ── Step 3: Topic ID lookup ──────────────────────────────────────────────── + # ── Step 3: Topic ID lookup (auto-create if new domain) ─────────────────── print(f"==> Looking up topic for domain '{domain}' ...") topics = _api_get("/topics/?status=active") match = next((t for t in topics if t.get("domain_slug") == domain), None) if not match: - print(f"ERROR: No active topic found for domain '{domain}'.") - sys.exit(1) + print(f" No topic found — creating one for domain '{domain}' ...") + slug = re.sub(r"[^a-z0-9]+", "-", domain.lower()).strip("-") + try: + match = _api_post("/topics/", { + "slug": slug, + "title": project_name, + "domain": domain, + "status": "active", + }) + print(f" Topic created: {match['title']} ({match['id']})") + except Exception as e: + print(f"ERROR: Could not create topic for domain '{domain}': {e}") + sys.exit(1) topic_id = match["id"] print(f" topic_id: {topic_id}")