Source code for check_skeleton_remote

"""Ad-hoc diagnostic: render the system prompt and inspect its JSON skeleton.

Builds a minimal :class:`PromptContextBuilder` context for a hard-coded test
message and channel, renders ``system_prompt.j2`` with
:class:`PromptRenderer`, then parses the rendered output as JSON and prints
the top-level structure (verifying the ``ROOT`` key is present and well
formed). Run directly (``python check_skeleton_remote.py``) to debug template
rendering or JSON-validity regressions in the prompt skeleton.
"""

import os
import sys
import json
import asyncio
import logging
from unittest.mock import MagicMock

sys.path.append("/root/stargazer-v3")

from prompt_context import PromptContextBuilder
from prompt_renderer import PromptRenderer
from platforms.base import IncomingMessage
from config import Config

[docs] async def main(): """Render the system prompt for a fixed test message and dump its JSON shape. The async entry point for this diagnostic. It loads ``Config``, fabricates a hard-coded ``IncomingMessage`` and a ``MagicMock`` platform, builds the prompt context via :class:`PromptContextBuilder`, then sanitizes that context so it will serialize: any ``MagicMock`` values are blanked, a couple of required fields (``hosting_provider``, ``current_time``) are pinned to deterministic test values, and the SWORD overlay variables are popped so the raw skeleton is rendered. It then renders ``system_prompt.j2`` with :class:`PromptRenderer`, parses the result with ``json.loads``, and prints the top-level keys plus the structure under ``ROOT`` (or the rendered prefix when ``ROOT`` is missing). On any render/parse failure it prints the exception and the sorted context keys to aid debugging. Side effects are limited to building context (which may read config/Redis-backed state) and writing to stdout. Invoked only from this module's ``__main__`` block via :func:`asyncio.run`. """ cfg = Config.load() msg = IncomingMessage( platform="discord", channel_id="1424991476668170351", user_id="user1", user_name="user1", text="hello", is_addressed=True ) builder = PromptContextBuilder(cfg) platform = MagicMock() platform.name = "discord" platform.bot_identity = {"platform": "discord", "user_id": "bot123", "display_name": "Stargazer"} ctx = await builder.build(msg, platform) # Clean/mock context to avoid Jinja undefined/MagicMock serialization issues for k, v in list(ctx.items()): if isinstance(v, MagicMock): ctx[k] = "" # Explicitly set required fields to avoid undefined errors ctx["hosting_provider"] = "test-provider" ctx["current_time"] = "2026-05-29T14:10:00Z" # Remove overlay variables so we get raw skeleton ctx.pop("_sword_pseudo_origins", None) ctx.pop("_sword_overlay_active", None) renderer = PromptRenderer("/root/stargazer-v3/system_prompt.j2") try: prompt = renderer.render(ctx) parsed = json.loads(prompt) print("Parsed JSON type:", type(parsed)) print("Top-level keys:", list(parsed.keys())) if "ROOT" in parsed: print("ROOT type:", type(parsed["ROOT"])) if isinstance(parsed["ROOT"], list): print("ROOT list len:", len(parsed["ROOT"])) for item in parsed["ROOT"]: if isinstance(item, dict): print(" Item keys:", list(item.keys())) else: print("ROOT NOT FOUND in parsed JSON!") print("Rendered prompt start:") print(prompt[:500]) except Exception as e: print("Rendering or parsing failed:", e) print("Context keys:", sorted(list(ctx.keys())))
if __name__ == "__main__": asyncio.run(main())