{"owner":"Q00","repo":"ouroboros","hasSkills":true,"totalSkillsCount":77,"totalTokensCount":46675,"categories":["anthropic-skill","root-instruction","claude-rule","plugin-manifest","codex-rule","marketplace","project-spec","subagent-persona"],"hasMcp":false,"mcpConfig":null,"found":["skills/welcome/SKILL.md","skills/status/SKILL.md","skills/update/SKILL.md","skills/tutorial/SKILL.md","skills/unstuck/SKILL.md","skills/setup/SKILL.md","skills/seed/SKILL.md","skills/run/SKILL.md","skills/publish/SKILL.md","skills/qa/SKILL.md","skills/ralph/SKILL.md","skills/resume-session/SKILL.md","skills/pm/SKILL.md","skills/ooo/SKILL.md","skills/interview/SKILL.md","skills/help/SKILL.md","skills/evolve/SKILL.md","skills/evaluate/SKILL.md","skills/config/SKILL.md","skills/cancel/SKILL.md","skills/brownfield/SKILL.md","skills/auto/SKILL.md",".claude-plugin/skills/welcome/SKILL.md",".claude-plugin/skills/update/SKILL.md",".claude-plugin/skills/unstuck/SKILL.md",".claude-plugin/skills/tutorial/SKILL.md",".claude-plugin/skills/status/SKILL.md",".claude-plugin/skills/setup/SKILL.md",".claude-plugin/skills/seed/SKILL.md",".claude-plugin/skills/run/SKILL.md",".claude-plugin/skills/resume-session/SKILL.md",".claude-plugin/skills/ralph/SKILL.md",".claude-plugin/skills/qa/SKILL.md",".claude-plugin/skills/publish/SKILL.md",".claude-plugin/skills/pm/SKILL.md",".claude-plugin/skills/interview/SKILL.md",".claude-plugin/skills/help/SKILL.md",".claude-plugin/skills/evolve/SKILL.md",".claude-plugin/skills/evaluate/SKILL.md",".claude-plugin/skills/config/SKILL.md",".claude-plugin/skills/cancel/SKILL.md",".claude-plugin/skills/brownfield/SKILL.md",".claude-plugin/skills/auto/SKILL.md","tests/fixtures/router/skills/frontmatter-body/run/SKILL.md","AGENTS.md","CLAUDE.md","llms.txt","llms-full.txt",".codex-plugin/plugin.json",".codex/config.toml",".codex/hooks.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json","docs/architecture.md",".agents/plugins/marketplace.json","src/ouroboros/agents/advocate.md","src/ouroboros/agents/analysis-agent.md","src/ouroboros/agents/architect.md","src/ouroboros/agents/breadth-keeper.md","src/ouroboros/agents/code-executor.md","src/ouroboros/agents/codebase-explorer.md","src/ouroboros/agents/consensus-reviewer.md","src/ouroboros/agents/contrarian.md","src/ouroboros/agents/evaluator.md","src/ouroboros/agents/hacker.md","src/ouroboros/agents/judge.md","src/ouroboros/agents/ontologist.md","src/ouroboros/agents/ontology-analyst.md","src/ouroboros/agents/qa-judge.md","src/ouroboros/agents/research-agent.md","src/ouroboros/agents/researcher.md","src/ouroboros/agents/seed-architect.md","src/ouroboros/agents/seed-closer.md","src/ouroboros/agents/semantic-evaluator.md","src/ouroboros/agents/simplifier.md","src/ouroboros/agents/socratic-interviewer.md","tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json"],"skills":{"skills/welcome/SKILL.md":"---\nname: welcome\ndescription: \"First-touch experience for new Ouroboros users\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:welcome\n\nInteractive onboarding for new Ouroboros users.\n\n## Usage\n\n```\n/ouroboros:welcome              # First-time or update onboarding\n/ouroboros:welcome --skip       # Skip welcome, mark as shown\n/ouroboros:welcome --force      # Force re-run welcome even if shown\n```\n\n## Instructions\n\nAsk every question with the active runtime's `ask_user` capability, in the\nuser's language. The Korean labels below are the canonical wording.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Pre-Check: Already Completed?\n\nRun the resolver, this section's blocks, and the migration check below in one\nshell call, then print the result with\n`printf 'completed=%s setup=%s codex=%s migration=%s\\n' \"$WELCOME_COMPLETED\" \"${SETUP_READY:-}\" \"${CODEX_READY:-}\" \"${LEGACY_CODEX_MODEL_MIGRATION_REQUIRED:-}\"`.\n\nRead the completion marker (legacy `welcomeShown: true` also counts):\n\n```bash\nWELCOME_COMPLETED=$(ouroboros_python - <<'PY'\nimport json, os\ntry:\n    prefs = json.load(open(os.path.expanduser('~/.ouroboros/prefs.json'), encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprint(prefs.get('welcomeCompleted') or ('legacy-welcomeShown' if prefs.get('welcomeShown') else ''))\nPY\n)\n```\n\nBefore honoring that completion marker, determine whether setup is ready for\nthe active runtime.\nA previously completed welcome must never hide the setup gate from a user who\nchose **나중에** or whose setup was later removed.\n\nClaude Code is ready when `~/.ouroboros/config.yaml` has\n`orchestrator.runtime_backend` in `{claude, claude_mcp}` and `llm.backend:\nclaude`. The marketplace plugin owns its MCP registration, so host-owned\n`~/.claude/mcp.json` is never part of readiness:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  SETUP_READY=\"true\"\nfi\n```\n\nIf `SETUP_READY` is not true, check Codex. It is ready when both backends are\n`codex`, the Codex CLI (`OUROBOROS_CODEX_CLI_PATH`, else\n`orchestrator.codex_cli_path`, else `codex` on PATH) is runnable, and\n`mcp_servers\\.ouroboros` in `$CODEX_HOME/config.toml` (any TOML key spelling)\nhas a runnable `command` or a non-blank `url`:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  CODEX_READY=\"true\"\nfi\n```\n\n### Legacy Codex Model Migration\n\nOlder configurations saved `gpt-5` into all four stage-model fields. That is\nnow an explicit pin that stops Codex App/CLI model changes from taking effect.\nNever rewrite a possible user pin silently. When Codex is ready, detect that\nexact legacy shape (or an interrupted migration) once:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$HOME/.ouroboros/prefs.json\" <<'PY'\nfrom __future__ import annotations\n\nimport json\nimport sys\nfrom pathlib import Path\n\nconfig_path, prefs_path = map(Path, sys.argv[1:])\n\ndef yaml_mapping(source: str) -> dict[str, dict[str, str]]:\n    parsed: dict[str, dict[str, str]] = {}\n    section: str | None = None\n    for raw_line in source.splitlines():\n        if not raw_line.strip() or raw_line.lstrip().startswith(\"#\"):\n            continue\n        indent = len(raw_line) - len(raw_line.lstrip())\n        key, separator, raw_value = raw_line.strip().partition(\":\")\n        if not separator:\n            continue\n        value = raw_value.strip().split(\" #\", 1)[0].strip().strip(\"'\\\"\")\n        if indent == 0:\n            section = key.strip(\"'\\\"\")\n            parsed.setdefault(section, {})\n        elif section is not None:\n            parsed[section][key.strip(\"'\\\"\")] = value\n    return parsed\n\ntry:\n    config = yaml_mapping(config_path.read_text(encoding=\"utf-8\"))\nexcept OSError:\n    raise SystemExit(1)\ntry:\n    prefs = json.loads(prefs_path.read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\n\nstage_values = (\n    config.get(\"clarification\", {}).get(\"default_model\"),\n    config.get(\"execution\", {}).get(\"default_model\"),\n    config.get(\"evaluation\", {}).get(\"semantic_model\"),\n    config.get(\"resilience\", {}).get(\"reflect_model\"),\n)\nlegacy_gpt5 = all(value == \"gpt-5\" for value in stage_values)\npartial_automatic_migration = (\n    any(value == \"gpt-5\" for value in stage_values)\n    and any(value == \"default\" for value in stage_values)\n    and all(value in {\"gpt-5\", \"default\"} for value in stage_values)\n)\nhandled = prefs.get(\"codexModelMigration\") in {\"automatic-v1\", \"kept-gpt-5-v1\"}\nraise SystemExit(0 if (legacy_gpt5 or partial_automatic_migration) and not handled else 1)\nPY\nthen\n  LEGACY_CODEX_MODEL_MIGRATION_REQUIRED=\"true\"\nfi\n```\n\nIf `CODEX_READY` and `LEGACY_CODEX_MODEL_MIGRATION_REQUIRED` are both true, ask\n\"현재 설정은 모든 단계에서 gpt-5를 고정해 두고 있어요. Codex에서 선택한 모델을 자동으로 사용하도록 바꿀까요?\"\n(header `모델 설정`) with these options:\n\n- **Codex 선택으로 전환하기 (권장)**: App이나 CLI에서 바꾼 모델을 모든 단계가 자동으로 따라가요.\n  Atomically rewrite the four pins:\n\n```bash\nouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nfrom __future__ import annotations\n\nimport os\nimport sys\nimport tempfile\nfrom pathlib import Path\n\npath = Path(sys.argv[1])\noriginal = path.read_text(encoding=\"utf-8\")\nreplacements = {\n    (\"clarification\", \"default_model\"): \"default\",\n    (\"execution\", \"default_model\"): \"default\",\n    (\"evaluation\", \"semantic_model\"): \"default\",\n    (\"resilience\", \"reflect_model\"): \"default\",\n}\nseen: set[tuple[str, str]] = set()\nsection: str | None = None\noutput: list[str] = []\nfor line in original.splitlines(keepends=True):\n    stripped = line.strip()\n    indent = len(line) - len(line.lstrip())\n    key = stripped.split(\":\", 1)[0].strip(\"'\\\"\") if \":\" in stripped else \"\"\n    if indent == 0 and \":\" in stripped:\n        section = key\n    target = (section or \"\", key)\n    if indent > 0 and target in replacements:\n        newline = \"\\n\" if line.endswith(\"\\n\") else \"\"\n        prefix = line[:indent]\n        comment = \"\"\n        value_part = line.strip().split(\":\", 1)[1]\n        if \" #\" in value_part:\n            comment = \" #\" + value_part.split(\" #\", 1)[1].rstrip(\"\\n\")\n        output.append(f\"{prefix}{key}: {replacements[target]}{comment}{newline}\")\n        seen.add(target)\n    else:\n        output.append(line)\nmissing = set(replacements) - seen\nif missing:\n    raise SystemExit(f\"Cannot migrate Codex model pins; missing keys: {sorted(missing)}\")\nupdated = \"\".join(output)\nfd, tmp_name = tempfile.mkstemp(prefix=\".config.yaml.\", dir=str(path.parent))\ntry:\n    with os.fdopen(fd, \"w\", encoding=\"utf-8\") as tmp:\n        tmp.write(updated)\n        tmp.flush()\n        os.fsync(tmp.fileno())\n    os.replace(tmp_name, path)\nfinally:\n    try:\n        os.unlink(tmp_name)\n    except FileNotFoundError:\n        pass\nPY\n```\n\n  `default` sends no model pin to Codex; it is not a model named \"default\".\n  Confirm the rewrite succeeded before recording the decision. An interrupted\n  rewrite leaves a partial `gpt-5`/`default` state that the next check offers\n  again.\n- **gpt-5 고정 유지하기**: 지금처럼 모든 단계를 gpt-5로 계속 실행해요. Do not\n  change `config.yaml`.\n\nFor either choice, merge exactly one `codexModelMigration` marker into\n`~/.ouroboros/prefs.json`, keeping existing keys:\n\n```bash\nouroboros_python - \"automatic-v1\" <<'PY'\nimport json, os, sys\npath = os.path.expanduser('~/.ouroboros/prefs.json')\ntry:\n    prefs = json.load(open(path, encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprefs['codexModelMigration'] = sys.argv[1]\nos.makedirs(os.path.dirname(path), exist_ok=True)\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nPass `kept-gpt-5-v1` instead of `automatic-v1` for the keep choice. If welcome\nwas already completed, confirm briefly and exit; do not also ask the generic\nwelcome question.\n\n### Routing After the Pre-Check\n\n- **Completed, `SETUP_READY` or `CODEX_READY` true, no `--force`**: ask\n  \"Ouroboros welcome was already completed on $WELCOME_COMPLETED. What would\n  you like to do?\" with **Skip** (continue to work, recommended; exit) and\n  **Re-run welcome** (continue to Step 1).\n- **Completed but neither ready**: skip that prompt and go to the Setup Gate.\n- **`--skip`**: write the completion prefs (Step 4), print\n  `Ouroboros welcome skipped. Run /ouroboros:welcome --force to re-run onboarding.`,\n  and exit.\n\n### Setup Gate: First Use\n\nUse the readiness the Pre-Check printed; a global `config.yaml` alone is not\nenough unless it names a runtime these gates recognize. To recheck after a\nsetup run (or when the Pre-Check did not run), use these standalone gates,\nwhich print their verdict. Claude Code:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"SETUP_READY\"\nelse\n  echo \"SETUP_REQUIRED\"\nfi\n```\n\nIf that printed `SETUP_READY`, skip the Codex gate and continue to Step 1.\nOtherwise check Codex:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"CODEX_READY\"\nelse\n  echo \"CODEX_SETUP_REQUIRED\"\nfi\n```\n\nIf neither is ready (`SETUP_REQUIRED` and `CODEX_SETUP_REQUIRED`, including a\nconfig that names a runtime neither gate recognizes), ask\n\"Ouroboros를 처음 사용하시네요. 시작하기 전에 실행 환경을 설정할까요?\"\n(header `Ouroboros 시작하기`):\n\n- **설정하고 시작하기 (권장)**: 한 번만 설정하면 바로 사용할 수 있어요. Run the\n  setup for the active host yourself; never ask the user to copy a command the\n  host can run. In Codex App or Codex CLI, run `ouroboros setup --runtime codex`\n  when the executable is installed. For a Marketplace-plugin-only install run\n  `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ouroboros setup --runtime codex`\n  instead. In Claude Code, follow `../setup/SKILL.md`.\n- **나중에**: 지금은 기본 안내만 보고 나중에 설정할게요. Continue the welcome\n  flow without claiming MCP-backed features are ready.\n\nAfter a successful **Codex** setup, ask \"설정이 완료됐어요. 기본적으로 Codex에서\n선택한 모델을 사용합니다. 모델은 언제든 나중에 바꿀 수 있어요.\" (header `준비 완료`):\n\n- **바로 시작하기 (권장)**: 기본 모델로 바로 작업을 시작해요. Continue to Step 1.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. On the user's local Codex App\n  or CLI it opens the settings UI in their browser at a\n  temporary `localhost` address (not an external website). It offers **Use Codex default model** and\n  **Enter another model ID…** for a deliberate stage pin. Continue to Step 1\n  when the settings session ends.\n\nIn Claude Code, `../setup/SKILL.md` asks the equivalent model question itself;\ndo not ask it again. Do not show this gate again once a runtime is ready; the\nsettings UI stays available through `ooo config`.\n\n### Step 1: Banner\n\n```\nWelcome to Ouroboros!\n\nMost AI coding fails at the input, not the output.\nOuroboros exposes hidden assumptions BEFORE any code is written.\n\nInterview -> Seed -> Execute -> Evaluate\n    ^                            |\n    +---- Evolutionary Loop -----+\n```\n\nOrdinary Claude setup uses the default `[claude]` Agent SDK profile on MCP 1.x.\nNever inspect or mutate `~/.claude/mcp.json` as a health check. If Ouroboros\nMCP tools are not callable here, say that MCP-backed commands need a supported\nhost setup, which owns an isolated `[mcp]` launcher; `[claude-sdk]` and\n`[mcp]` are never installed together.\n\n### Step 2: Persona\n\nAsk \"What brings you to Ouroboros?\" with **New project idea** (crystallize a\nvague idea into a Seed), **Tired of rewriting prompts** (AI keeps building the\nwrong thing), and **Just exploring**. Reply in 1-2 personalized sentences.\n\n### Step 3: First Action\n\nShow the core commands: `ooo interview` (Socratic Q&A that exposes hidden\nassumptions), `ooo seed` (freeze answers into a Seed), `ooo run` (execute a\nSeed), `ooo evaluate` (verify against the acceptance criteria), `ooo unstuck`\n(lateral thinking), `ooo config` (settings), `ooo help` (full reference).\n\nAsk \"What would you like to do first?\":\n\n- **Start a project**: ask \"What do you want to build?\", then continue as `ooo interview`.\n- **Try the tutorial**: continue as `ooo tutorial`.\n- **Read the docs**: continue as `ooo help`.\n\nRun Step 4 before handing off, so completion is recorded even when the next\ncommand takes over the conversation.\n\n### Step 4: GitHub Star and Completion\n\nRun `gh auth status &>/dev/null && echo GH_OK || echo GH_MISSING`. If `GH_OK`\nand `star_asked` is not true in `~/.ouroboros/prefs.json`, ask \"If you're\nenjoying Ouroboros, would you like to star it on GitHub?\" with **Star on\nGitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`) and **Maybe later**.\n\nThen merge the completion fields into `~/.ouroboros/prefs.json`, keeping\nexisting keys. Prefix the command with `STAR_ASKED=true` when the star question\nwas asked, so it is never repeated:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\nfrom datetime import UTC, datetime\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs.update({\n    'welcomeShown': True,\n    'welcomeCompleted': datetime.now(UTC).isoformat(),\n})\nif os.environ.get('STAR_ASKED') == 'true':\n    prefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nBefore the handoff, mention that phrases like \"interview me\", \"I'm stuck\", or \"evaluate this\" also\nroute to the matching command; to watch `ooo run` or `ooo evolve` live, run\n`uvx --python '>=3.12' --from 'ouroboros-ai[tui]' ouroboros tui monitor` in a\nseparate terminal.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/status/SKILL.md":"---\nname: ouroboros-status\ndescription: \"Check session status and measure goal drift\"\naliases: [drift]\nmcp_tool: ouroboros_session_status\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:ouroboros-status\n\nCheck an execution session's status and, on request, measure drift from the Seed goal.\n\n```\n/ouroboros:ouroboros-status [session_id]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros session status\"` for `ouroboros_session_status` and `ouroboros_measure_drift`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\n### Steps\n\n1. Session: use the given `session_id`, else the most recent one in the conversation, else ask the user.\n\n2. Call `ouroboros_session_status` MCP tool:\n   ```\n   Tool: ouroboros_session_status\n   Arguments:\n     session_id: <session ID>\n   ```\n\n3. If the user asks about drift (or says \"am I drifting?\"), also call `ouroboros_measure_drift`:\n   ```\n   Tool: ouroboros_measure_drift\n   Arguments:\n     session_id: <session ID>\n     current_output: <current execution output or file contents>\n     seed_content: <original seed YAML>\n     constraint_violations: []  (any known violations)\n     current_concepts: []       (concepts in current output)\n   ```\n\n4. Show the status and progress, and the drift report as the tool renders it (weights, threshold, breakdown, suggestions). When combined drift exceeds 0.3 (status `EXCEEDED`), warn and suggest `ooo interview` to re-clarify or `ooo evolve` to course-correct; otherwise suggest continuing with `ooo run` or `ooo evaluate`.\n\n## Fallback (no MCP server)\n\nTell the user session tracking needs the Ouroboros MCP server (`ooo setup`), and that without it they can compare the implementation against the Seed by hand.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/update/SKILL.md":"---\nname: update\ndescription: \"Check for updates and upgrade Ouroboros to the latest version\"\n---\n\n# /ouroboros:update\n\nUpgrade Ouroboros without changing the installation's manager, environment, or optional-dependency profile.\n\n```\nooo update\n/ouroboros:update\n```\n\n## Instructions\n\nThe native command is the single source of truth. Run it with the active runtime's `run_shell` capability.\n\n1. Run `ouroboros update --check`.\n   - **Up to date**: report the package result together with any Codex plugin version mismatch or unknown-status warning, then stop. Do not infer that every integration is current from the package version.\n   - **Update available**: ask the user (active runtime's `ask_user` capability) to choose **Update now** or **Skip**. On **Update now**, run `ouroboros update --yes`. When the user actively uses both Claude Code and Codex, run `ouroboros update --yes --runtime all` instead; it refreshes both host integrations without changing the configured execution backend. Show the command's result.\n\n2. If the check fails but `ouroboros update --help` works, report the native error and stop. Never substitute a manual upgrade, and never infer ownership from `uv tool list`, `pipx list`, PATH order, directory names, or the active agent runtime.\n\n3. If `ouroboros update --help` does not work, this is a legacy install that predates the receipt-bound updater. Fail closed: only a read-only `ouroboros --version` is allowed. Explain that the original manager, environment, and extras cannot be proven, and ask the user to rerun their exact original install command (including its `ouroboros-ai[...]` extras and custom manager root), or to do a fresh isolated install if they do not know it. Run no package upgrade, plugin refresh, or setup command on this path.\n\n4. After a successful update, relay the command's restart guidance (Claude may use `/reload-plugins` or restart; active Codex sessions need a restart) and any Codex plugin version diagnostic. A mismatch is advisory; preserve existing marketplace refs rather than automatically removing or advancing a pin. If project instruction content needs regeneration, suggest `ooo setup`; never edit project instruction files as part of the update.\n\nThe updater replays the environment's install receipt, so the Claude SDK and MCP 2 profiles are never combined or substituted. Other options: `--dry-run`, `--prerelease`; see `ouroboros update --help`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/tutorial/SKILL.md":"---\nname: tutorial\ndescription: \"Interactive tutorial teaching Ouroboros hands-on\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:tutorial\n\nInteractive tutorial that teaches Ouroboros through hands-on experience.\n\n## Usage\n\n```\nooo tutorial\n/ouroboros:tutorial\n```\n\n## Principles\n\n1. Show something useful in the first 30 seconds.\n2. Learn by doing: the user answers questions about their own idea.\n3. Reveal features gradually.\n4. Always end a phase with one specific next action.\n5. Match the audience: technical users get the run, evaluate, and evolve\n   details; non-technical users get the interview and plain language.\n\n## Flow (about 5 minutes)\n\n1. **Hook.** Promise that in five minutes their vague idea becomes a precise\n   specification, then ask what they want to build. If they have no idea, use a\n   task-management CLI as the example.\n2. **Interview.** Ask 3-4 Socratic questions about their idea (the problem it\n   solves, the main users, the one feature that makes it useful now). Point out\n   that each answer surfaced an assumption they had not stated.\n3. **Mini-Seed.** Summarize their answers in Seed vocabulary:\n\n   ```\n   Goal: <their goal, refined>\n   Constraints: <2-3 constraints they named>\n   Acceptance criteria: <2-3 checkable outcomes>\n   ```\n\n   Do not invent an ambiguity score. Explain that `ooo interview` measures\n   ambiguity and continues until it is low enough to freeze a real Seed.\n4. **The workflow.** `Interview → Seed → Execute → Evaluate`, with evaluation\n   feeding back into the next Seed generation:\n\n   ```\n   ooo interview \"your idea\"   # expose assumptions\n   ooo seed                    # freeze the Seed\n   ooo run                     # execute it\n   ooo evaluate                # verify against the acceptance criteria\n   ooo status                  # check drift\n   ```\n\n   `ooo unstuck` helps when blocked. `run`, `evaluate`, `evolve`, and `status`\n   need the Ouroboros MCP server (`ooo setup`).\n5. **Next step.** Offer: start a real project (`ooo interview \"your actual\n   project idea\"`), the full reference (`ooo help`), or setup (`ooo setup`).\n\nIf the user asks how this differs from prompting an AI assistant directly:\nwithout a spec, the assistant guesses and you rewrite the prompt until it\nmatches; with Ouroboros, the interview exposes hidden assumptions first, so the\nbuild starts from an agreed Seed. If it seems complicated, three commands cover\nmost use: `ooo interview`, `ooo seed`, `ooo run`.\n\nThe tutorial is done when the user has experienced the interview, understands\nwhat a Seed is, and has chosen a next step.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/unstuck/SKILL.md":"---\nname: unstuck\ndescription: \"Use when the user is stuck or going in circles: the same fix failed twice or more, 'nothing works', 'I've tried everything', or a consequential choice with no clear winner that is hard to undo or splits the team (which database, which architecture). Brings hacker, researcher, simplifier, architect, and contrarian perspectives and converges on one recommendation. Not for a first error or normal progress.\"\naliases: [stuck, lateral]\n---\n\n# /ouroboros:unstuck\n\nBreak through stagnation, or advise on a hard choice, with lateral thinking personas. **Solo** runs one persona; **debate** runs several in parallel and synthesizes them.\n\n## Usage\n\n```\nooo lateral                       # debate: all 5 lateral personas\nooo lateral <persona>             # solo: one persona\nooo lateral debate <p1> <p2> ...  # debate with explicit members\nooo lateral @all                  # debate preset (the only preset)\n```\n\n## Personas (lateral pool)\n\nStateless reframing lenses only; stateful roles (evaluator, qa-judge, ontologist, socratic-interviewer) have their own skills.\n\n| Persona | Lens | Use when |\n|---------|------|----------|\n| **hacker** | Make it work first, elegance later | Overthinking blocks progress |\n| **researcher** | What information are we missing? | The problem is unclear |\n| **simplifier** | Cut scope, return to MVP | Complexity is overwhelming |\n| **architect** | Restructure the approach entirely | The current design is wrong |\n| **contrarian** | Are we solving the wrong problem? | Assumptions need challenging |\n\nBesides direct `ooo lateral`, you MAY chain into this skill from another skill (for example as `socratic-interviewer` in `ooo interview`) when the current question needs multi-perspective deliberation; afterwards summarize the options, return to the parent flow, and let the user decide.\n\n## Instructions\n\n### Step 1: Parse args into a mode\n\n| Input | Mode | Members |\n|---|---|---|\n| no args, `debate`, or `@all` | debate | all 5 personas |\n| `<persona>` | solo | that persona |\n| `debate <p1> <p2> ...` | debate | the listed personas |\n| `@<unknown-preset>` | error | reject and list known presets |\n| `<unknown-persona>` | error | reject and list the 5 personas |\n| `<p1> <p2> ...` without `debate` | error | reject and suggest `ooo lateral debate <p1> <p2>` |\n\nValidate every persona name against the pool; never coerce silently. When a parent skill wants one persona but names none, omit `persona` and pass `stagnation_pattern` (`spinning`, `oscillation`, `no_drift`, `diminishing_returns`) if known; the server picks the persona (default contrarian).\n\nPick the lateral **mode** too. Use `mode=\"decision\"` when the user faces a consequential choice between options (which database, which architecture) rather than a stall; otherwise omit `mode` (default `unstuck`). In decision mode, `problem_context` describes the options and `current_approach` the currently favored one (or `undecided`), and an omitted persona means a full debate. Pass `research=true` only when the user explicitly asks for web-grounded research; it is slower and never the default.\n\n### Step 2: Gather required context before the MCP call\n\nThe tool hard-fails when `problem_context` or `current_approach` is empty, so resolve both first (solo and debate alike):\n\n1. Reuse session state from the parent skill or recent conversation: `problem_context` (what the user is stuck on, 1-3 sentences), `current_approach` (what was tried; `\"none yet, first attempt\"` is fine), and optional `failed_attempts`.\n2. If either field is unrecoverable, ask the user one combined question with the active runtime's `ask_user` capability: \"Two things I need before lateral thinking can run: (1) what are you stuck on right now, (2) what have you already tried? A sentence each is enough.\" Wait for the answer. Never fabricate these fields; `current_approach=\"not specified\"` is acceptable, invented content is not.\n\n### Step 3: Always call `ouroboros_lateral_think`\n\nEvery invocation routes through the MCP tool, solo and debate, in every runtime; never substitute a direct subagent fan-out.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros lateral\"` for `ouroboros_lateral_think`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision` (decision mode). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent (neither exposed nor loadable), stop and report that the MCP dispatch surface is broken; do not improvise solo or debate without it.\n\nCall it with:\n- **Solo**: `persona=<one>`, `problem_context`, `current_approach`, `failed_attempts`.\n- **Debate**: `personas=[...]`, `problem_context`, `current_approach`, `failed_attempts`.\n- Plus `mode`/`research` from Step 1, and `session_id` when running inside an interview or lateral session (it binds the fan-out so results submitted from another session are refused).\n\n### Step 4: Act on the response shape (the server picks it)\n\n| Mode | Plugin response | Inline response |\n|---|---|---|\n| Solo | one `_subagent` object | one `# Lateral Thinking: <approach>` block in `content` |\n| Debate | `_subagents` array (N objects) | N blocks joined by `\\n\\n---\\n\\n`, plus a hidden dispatch block carrying the same N payloads |\n\n**Inline dispatch block (debate, inline only).** Prefer the structured copy in the response meta when present. Otherwise take the text between `<!-- ouroboros-lateral-inline-dispatch-v1 base64\\n` and `\\n-->` at the end of `content`, base64-decode it, and parse the JSON. A host that did not declare subagent capability receives the neutral shape:\n\n```json\n{\"dispatch_mode\": \"host_decides\", \"host_action\": \"dispatch_subagents_if_supported\", \"execution_preference\": \"parallel\", \"fallback_strategy\": \"sequential\", \"persona_count\": N, \"payloads\": [...]}\n```\n\nAn explicitly sequential execution authority receives `dispatch_mode=\"sequential\"` with `legacy_dispatch_mode=\"inline_fallback\"`, which is compatibility metadata only. Never split the joined display text on `---`: user content can contain the separator.\n\n#### Shape A: plugin response (OpenCode plugin mode)\n\nThe plugin spawns the children itself. Await the single `_subagent` result (solo) or all `_subagents` results (debate), then present or synthesize. If the response is inline text with neither key, you are not in plugin mode: use Shape B.\n\n#### Shape B: inline response\n\nThe dispatch block distinguishes declared `host_driven`, capability-neutral `host_decides`, and explicit `sequential` execution. **Solo**: present the approach summary, reframing prompt, and questions to consider, then route back to the workflow.\n\n##### Debate, runtime supports sub-agent dispatch\n\n1. Show the visible markdown under a short \"what the lateral toolkit suggests\" header.\n2. With `host_action=\"spawn_subagents\"`, or `host_action=\"dispatch_subagents_if_supported\"` when the runtime has a native parallel primitive, use the active runtime's `orchestrate_subagents` capability: one isolated child per payload, launched together, each given its `prompt` verbatim plus its `context`.\n3. Await all children and correlate each result by `result_correlation_key` (normally `context.persona`).\n4. Optional Round 2 cross-attack, only when Round 1 answers diverge: give each persona short summaries of the others and ask \"Identify one weakness in each. 200 words max.\"\n5. Synthesize (below).\n\n##### Debate, constrained runtime without sub-agent dispatch\n\nIf the response is stamped with `dispatch_mode=\"sequential\"`, or with `dispatch_mode=\"host_decides\"` and the host has no native parallel primitive, process each recovered payload in order, correlate every result by `result_correlation_key`, and synthesize after the last one. If no payloads are recoverable (no meta copy and no dispatch block), present the handler's markdown as-is and synthesize from that text; there is no Round 2.\n\n##### Synthesize (debate, all shapes)\n\nIn decision mode, follow the synthesis contract the response carries: exactly one recommendation stated first, its grounds (citing only sources personas actually fetched), the strongest dissent, and flip conditions. After the user accepts, offer to persist it with `ouroboros_record_conductor_decision` as the contract describes.\n\nIn unstuck mode, present options, not a verdict:\n\n```\n## Debate result: N personas\n\n### Options\n- **Option A** (from <persona>): <one-liner>\n- **Option B** (from <persona>): <one-liner>\n\n### Disagreements\n- <persona X> vs <persona Y>: <what they disagree about>\n\n### Recommended (with reasoning)\n<your single best read, labeled as your recommendation>\n```\n\nIn both modes the choice is the user's: never auto-progress to the next workflow step on their behalf.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/setup/SKILL.md":"---\nname: setup\ndescription: \"Guided onboarding wizard for Ouroboros setup\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:setup\n\nGuided Ouroboros setup inside a Claude Code session.\n\n> Other runtimes (Codex, Copilot, OpenCode, and others) configure through the\n> CLI instead, for example `ouroboros setup --runtime codex` or\n> `ouroboros setup --runtime copilot`. See\n> [Getting Started](https://github.com/Q00/ouroboros/blob/main/docs/getting-started.md).\n\n## Usage\n\n```\nooo setup\n/ouroboros:setup\n/ouroboros:setup --uninstall\n```\n\nClaude setup confirms the runtime profile (the Claude Agent SDK on MCP 1.x)\nand optionally adds an Ouroboros reference block to the project's CLAUDE.md.\nIt deliberately leaves `~/.claude/mcp.json` untouched because marketplace\nplugin wiring owns that file. `[claude]` and its explicit `[claude-sdk]` alias\nuse MCP 1.x. The plugin launches `[mcp]` in a separate MCP 2 process with the\ndependency-free `[claude-cli]` worker.\n\n## Setup Wizard Flow\n\nAsk questions with the active runtime's `ask_user` capability unless a step\nsays otherwise.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Step 0.5: Community Support\n\nIf `star_asked` is not `true` in `~/.ouroboros/prefs.json`, ask \"Ouroboros is\nfree and open-source. A GitHub star helps other developers discover it. Star\nthe repo?\" with **Star on GitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`)\nand **Skip for now**. After any answer, merge `star_asked: true` into the\nprefs file, keeping existing keys:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\n### Step 1: Environment Detection\n\n```bash\nouroboros_python --version\nwhich uvx 2>/dev/null && uvx --version 2>/dev/null\nwhich claude 2>/dev/null\nuv python list 2>/dev/null | grep \"cpython-3.1[2-9]\"\n```\n\nThe resolver already rejects Python below 3.12 and falls back to a uv-managed\ninterpreter; that does not make the `[claude-sdk]` and MCP 2 profiles\nimport-compatible. Report what was found, then:\n\n| Environment | Action |\n|:------------|:-------|\n| Python >= 3.12 + Claude CLI | Ready: configure `[claude]` SDK/MCP 1 and skills |\n| uvx + Python >= 3.12 | MCP-capable elsewhere: use a supported CLI-backed runtime setup for isolated `ouroboros-ai[mcp]` |\n| Python < 3.12 only | Run `uv python install 3.12`, then re-run `ooo setup` |\n| No package runner or Ouroboros package | Install uv (below), then re-run `ooo setup` |\n\nPrefer package managers for uv: `pipx install uv`, `pip install --user uv`, or\n`brew install uv`; the vendor one-liner\n`curl -LsSf https://astral.sh/uv/install.sh | sh` is the last resort.\n\n**IMPORTANT**: Never install `[mcp,claude]`, `[mcp,claude-sdk]`, or `[all,mcp]`\ntogether and never write a direct\n`ouroboros` or `python -m ouroboros` MCP fallback. MCP 2 launchers must use an\nisolated `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ...` or\n`pipx run --spec 'ouroboros-ai[mcp]' ...` process. Only `[mcp,claude-cli]` is\nsupported because the CLI worker is out of process. Do not write\nan Ouroboros entry to `~/.claude/mcp.json`; the plugin owns that registration.\n\n### Step 1.5: Runtime Configuration\n\nWrite the Claude runtime selection to `~/.ouroboros/config.yaml`. The welcome\ngate and the CLI read it; nothing else in this wizard writes it. This step\nnever touches `~/.claude/mcp.json`.\n\nDefine `ouroboros_cli` in the same shell as each command below (shell state\ndoes not persist between commands):\n\n```bash\nouroboros_cli() {\n  if command -v ouroboros >/dev/null 2>&1; then\n    command ouroboros \"$@\"\n  else\n    uvx --isolated --python '>=3.12' --from 'ouroboros-ai' ouroboros \"$@\"\n  fi\n}\nouroboros_cli config show orchestrator\nouroboros_cli config show llm\n```\n\nThe welcome gate is ready only when `orchestrator.runtime_backend` is `claude`\nor `claude_mcp` AND `llm.backend` is `claude`. A missing file or section\ncounts as not set.\n\n- Both conditions hold: already configured. Skip to Step 2.\n- `runtime_backend` is `claude_mcp` but `llm.backend` is not `claude`: run\n  `ouroboros_cli setup --runtime claude-cli --non-interactive` (keeps the CLI\n  transport).\n- `runtime_backend` is another runtime (for example `codex`): ask the user\n  whether to switch the default runtime to Claude. If they decline, keep the\n  existing configuration and skip to Step 2.\n- Otherwise (`runtime_backend` is `claude` with another `llm.backend`, no\n  config, no `orchestrator` section), or after the user agrees to switch, run:\n\n```bash\nouroboros_cli setup --runtime claude --non-interactive\n```\n\nBoth setup commands set `llm.backend: claude`; `--runtime claude` sets\n`orchestrator.runtime_backend: claude` and `--runtime claude-cli` sets `claude_mcp`.\nIf it fails, show the error and continue the wizard; Step 4 reports the\nruntime as not configured.\n\n### Step 2: MCP Profile Boundary\n\nTell the user: the default Claude SDK profile stays on MCP 1.x, and the\nplugin-owned MCP server runs MCP 2 separately with the `[claude-cli]` worker.\n**Do not create, update, or remove `~/.claude/mcp.json`.** Existing entries may\nbe user-managed or belong to another compatible runtime. Advanced MCP\nworkflows require a host-managed isolated `[mcp]` launcher, which the Claude\nmarketplace plugin or another supported host setup owns.\n\n### Step 3: CLAUDE.md Integration (Optional)\n\nOffer **Integrate / Skip / Preview first** for adding this ~40-line reference\nblock (pipeline, command table, agent catalog) to the project's CLAUDE.md. On\n**Preview first**, show it:\n\n````markdown\n<!-- ooo:START -->\n<!-- ooo:VERSION:0.59.8 -->\n# Ouroboros — Specification-First AI Development\n\n> Before telling AI what to build, define what should be built.\n> As Socrates asked 2,500 years ago — \"What do you truly know?\"\n> Ouroboros turns that question into an evolutionary AI workflow engine.\n\nMost AI coding fails at the input, not the output. Ouroboros fixes this by\n**exposing hidden assumptions before any code is written**.\n\n1. **Socratic Clarity** — Question until ambiguity ≤ 0.2\n2. **Ontological Precision** — Solve the root problem, not symptoms\n3. **Evolutionary Loops** — Each evaluation cycle feeds back into better specs\n\n```\nInterview → Seed → Execute → Evaluate\n    ↑                           ↓\n    └─── Evolutionary Loop ─────┘\n```\n\n## ooo Commands\n\nEach command loads its agent/MCP on-demand. Details in each skill file.\n\n| Command | Loads |\n|---------|-------|\n| `ooo` | — |\n| `ooo interview` | `ouroboros:socratic-interviewer` |\n| `ooo seed` | `ouroboros:seed-architect` |\n| `ooo run` | MCP required |\n| `ooo evolve` | MCP: `evolve_step` |\n| `ooo evaluate` | `ouroboros:evaluator` |\n| `ooo unstuck` | `ouroboros:{persona}` |\n| `ooo status` | MCP: `session_status` |\n| `ooo setup` | — |\n| `ooo help` | — |\n\n## Agents\n\nLoaded on-demand — not preloaded.\n\n**Core**: socratic-interviewer, ontologist, seed-architect, evaluator,\nadvocate, contrarian, judge\n**Support**: hacker, simplifier, researcher, architect\n<!-- ooo:END -->\n````\n\nOn **Integrate**: back up CLAUDE.md to CLAUDE.md.bak, append the block, and\nconfirm.\n\n### Step 4: Verification\n\nConfirm (with the Step 1.5 `config show` commands) that the saved Ouroboros\nconfig selects the default Claude Agent SDK runtime\non MCP 1.x while `~/.claude/mcp.json` was not mutated by this setup. The\ndependency-free Claude CLI worker remains a distinct, explicit `[claude-cli]`\nselection for the isolated MCP 2 process.\n\n### Step 5: Success Summary\n\n```\nOuroboros Setup Complete!\n\nMode:                     Claude Agent SDK (MCP 1.x)\nMCP Server:               Host-owned (config not mutated)\nCLAUDE.md:                <integrated | skipped>\n\nNext: ooo interview \"your project idea\" | ooo tutorial | ooo help\n```\n\n### Step 5.1: Model Choice (Claude Code)\n\nOffer optional model control. Ask \"설정이 완료됐어요. 기본 모델 설정으로 바로\n시작할 수 있고, 모델은 언제든 나중에 바꿀 수 있어요.\" (header `모델 설정`):\n\n- **바로 시작하기 (권장)**: 기본 모델 설정으로 바로 작업을 시작해요. Continue to Step 5.5.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. In the local Claude Code\n  harness it opens the settings UI in the user's browser at a temporary\n  `localhost` address. They can reopen it any time with `ooo config`; this\n  choice never permanently locks a model.\n\n### Step 5.5: Brownfield Repository Scan\n\nRegister existing git repositories and linked worktrees in the Ouroboros DB so\ninterviews can use them as brownfield context. Use the MCP tool only, not the\nCLI or Python scripts.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros brownfield\"` for `ouroboros_brownfield` (both the scan and the later `set_defaults` call). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent, skip this step and continue to Step 6.\n\n1. Scan and register:\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"scan\" }\n   ```\n   The walk starts at `scan_root` (default: the user's home directory) and\n   goes at most two directory levels deep, skipping dot-prefixed and noisy\n   directories such as `node_modules`. Normal repos (`.git` directory) and\n   linked worktrees (`.git` file) reached by the walk are registered self-only.\n   Git worktree families are not expanded. Repos with no remote or any remote\n   name are eligible. Existing defaults are preserved.\n\n2. The scan response `text` already holds a numbered list with default\n   markers. **Do NOT make any additional MCP calls to list or query repos.**\n   Show every repo in a plain-text two-column grid inside a code block (not a\n   markdown table), keeping the `*` default markers exactly as returned:\n\n   ```\n   Scan complete. 8 repositories registered.\n\n    1. repo-alpha                   5. repo-epsilon\n    2. repo-bravo *                 6. repo-foxtrot\n   ```\n\n   If no repos were found, skip to Step 6.\n\n3. **Do NOT use the active runtime's `ask_user` dialog for this selection.** Text emitted between\n   tool calls is not guaranteed to render, so a dialog can appear without the\n   list, and option previews truncate long lists. Instead, end the turn with the repo grid as the final message, followed by the prompt:\n\n   - Defaults exist: `Current defaults: <names> (numbers <numbers>)`, then\n     `Reply with repo numbers to change defaults (e.g. \"6, 18, 19\"), \"keep\" to keep the current defaults, or \"none\" to clear them.`\n   - No defaults: `No defaults set. Reply with repo numbers to set defaults (e.g. \"6, 18, 19\"), or \"none\" to run interviews in greenfield mode.`\n\n4. On the next turn: numbers (any separator) select those IDs; \"keep\" skips\n   the MCP call and leaves defaults unchanged; \"none\" clears all; anything else\n   gets the prompt again (never guess). Then make ONE call that replaces all\n   defaults (`\"indices\": \"\"` for none):\n\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"set_defaults\", \"indices\": \"<comma-separated IDs>\" }\n   ```\n\n   Confirm the resulting defaults, or that interviews will run in greenfield\n   mode, and mention that `ooo setup` or `ooo brownfield` changes them later.\n\n### Step 6: First Project Nudge\n\nSuggest `ooo interview \"Build a CLI tool for [something you need]\"` or\n`ooo tutorial`.\n\n## Uninstall\n\nOn `--uninstall`, ask for confirmation, explaining that it removes only the\nOuroboros block from CLAUDE.md, not plugin files, seeds, or project data. If\nconfirmed:\n1. Leave `~/.claude/mcp.json` untouched\n2. Remove `<!-- ooo:START -->` to `<!-- ooo:END -->` block from CLAUDE.md (if exists)\n3. Confirm: \"Ouroboros plugin configuration removed. To remove plugin files, run: claude plugin uninstall ouroboros\"\n\n## Setup Troubleshooting\n\n- **\"No compatible Python found\"**: plugin mode works without a global Python\n  when uv is on PATH. Otherwise install Python 3.12 (`brew install\n  python@3.12`, `sudo apt install python3.12`, or python.org/downloads).\n- **\"uvx: command not found\"**: uvx is recommended, not required. For the\n  default Claude SDK runtime, `pip install 'ouroboros-ai[claude]'`\n  (`[claude-sdk]` is an explicit alias). Use `[claude-cli]` only for the\n  isolated MCP 2 server worker. Never combine `[claude]`, `[claude-sdk]`, or\n  `[all]` with `[mcp]`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/seed/SKILL.md":"---\nname: seed\ndescription: \"Use when goal, constraints, and success criteria are already settled and the user wants them frozen into a formal spec an agent can execute and verify: 'turn this into a spec', 'write it up as a Seed', or right after an interview. Returns an immutable Seed with acceptance criteria. Not for vague requests (use interview first).\"\naliases: [crystallize]\nmcp_tool: ouroboros_generate_seed\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:seed\n\nGenerate a validated Seed specification from an interview or from requirements this conversation already settled.\n\n## Required Skill Capabilities\n\n`ask_user` (the active runtime's user-question surface), `inspect_code`, `call_mcp`, `orchestrate_subagents` (lateral persona payloads), `run_shell` (audit-trail and prefs writes), `refine_answer` (confirm free-form decisions), `maintain_ledger` (QA scores, candidate decisions, rejected proposals).\n\n## Usage\n\n```\nooo seed [session_id]\n/ouroboros:seed [session_id]\n```\n\n## Instructions\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before running any shell snippet below, and call `ouroboros_python` with every argument quoted. It accepts only Python 3.12 or newer and falls back to uv.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros seed\"` for `ouroboros_generate_seed`; `\"+ouroboros qa\"` for `ouroboros_qa`; `\"+ouroboros lateral\"` for `ouroboros_lateral_think`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\nLoad `ouroboros_generate_seed` before choosing a path: if it is callable, use **Path A**; use **Path B** only when it is genuinely absent (no Ouroboros MCP server).\n\n**Delegated responses are not artifacts.** If any tool below returns `status: \"delegated_to_subagent\"` (with `dispatch_mode: \"plugin\"` and possibly an `_subagents` array), keep the returned session ID, wait for the plugin-managed subagent results, and parse the artifact (Seed YAML, QA verdict, or persona texts) from those results, never from the envelope or its prompts.\n\n### Path A: MCP Mode (Preferred)\n\n1. Pick the entrance:\n   - `session_id` given, or a recent `ouroboros_interview` session ID in the conversation: use the interview session (step 2).\n   - No interview, but THIS conversation already settled the goal, the constraints, and verifiable success criteria (a lateral decision, a brownfield scan, or plain discussion that converged): use the interview-less path below. Do not send the user to `ooo interview` to repeat what they already said.\n   - Otherwise ask the user which interview or requirements to seed.\n\n   **Interview-less path** (`session_context`):\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_context:\n       goal: <the user's own settled wording, verbatim, never your paraphrase>\n       acceptance_criteria: [<verifiable checks: a command, a visible behaviour, a measurable state>]\n       constraints: [<optional>]\n       decisions: [<optional; each becomes a constraint>]\n       project_type: greenfield | brownfield\n   ```\n   Every value enters the Seed byte-for-byte, so shell chains in an AC (`ruff check && pytest`) are allowed. If the response has `status: \"gap_questions_required\"`, ask the user exactly the listed questions, merge the answers into `session_context`, and call again; that is the whole interview.\n\n2. Interview session:\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_id: <interview session ID>\n   ```\n   The tool extracts requirements from persisted interview state, scores ambiguity (must be <= 0.2), and returns Seed YAML.\n\n3. If no Seed YAML results, stop and ask the user to resume generation or supply the artifact. Never fabricate a Seed.\n\n4. Run the Advisory QA Check below, then go to \"After Seed Generation\".\n\n### Path B: No MCP Server\n\n1. Read the `seed-architect` prompt and adopt that role: `$OUROBOROS_AGENTS_DIR/seed-architect.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n   ```bash\n   uvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" seed-architect.md\n   ```\n\n   else `src/ouroboros/agents/seed-architect.md` in a source checkout. Resolve every agent prompt this skill names the same way, substituting its file name.\n2. Recover the requirements before drafting; never invent missing context:\n   - With a `session_id`, use current-thread Q&A and corrections only when they belong to that session; if incomplete, use `inspect_code` / `run_shell` to find persisted or exported artifacts for that ID (for example under `~/.ouroboros/data/`). Keep a persisted transcript as evidence, but let explicit same-thread corrections supersede it.\n   - Without a `session_id`, use current-thread Q&A only when it forms one coherent interview.\n   - Otherwise ask for the transcript or a requirement summary, or suggest `ooo interview`. Never seed from an absent or mismatched transcript.\n3. Generate the Seed YAML, run the Advisory QA Check, then go to \"After Seed Generation\".\n\n### Advisory QA Check (single pass, non-blocking)\n\nRun QA **exactly once** on the generated Seed. The verdict is advisory and never blocks: the Seed is presented as final regardless of score, and there is no QA-until-PASS loop.\n\nGeneration (Path A tool or Path B role) runs **exactly once** and fixes the Seed's ontology. Any later revision is a direct YAML edit by you; never call `ouroboros_generate_seed` again (it takes no revision hints and would discard the ontology).\n\n**MCP QA mode:**\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the seed YAML>\n     quality_bar: \"Seed must be internally consistent, acceptance_criteria must be measurable and testable, constraints must be concrete (no vague terms), ontology_schema must cover all entities referenced in goal/criteria, and there must be no contradictions between fields. acceptance_criteria must also be parsimonious in the ontological sense: a criterion names a state of the finished work a user can see is true, while an implementation step names a means of reaching it, and only the first belongs in the list. Read each criterion beside its siblings — one intelligible only as a move toward a sibling is that sibling's means and belongs merged into the outcome it serves, and flagging that is as important as flagging a missing piece, since it commits the seed to an unverified path. How many criteria a goal has follows from that judgment, so weigh each criterion against its siblings.\"\n     artifact_type: \"document\"\n     pass_threshold: 0.90\n     seed_content: <the seed YAML>\n     qa_session_id: <reuse across passes>\n     iteration_history: <accumulated across passes>\n   ```\nThe 0.90 bar (stricter than the default 0.80) labels the verdict; it gates nothing.\n\n**Fallback QA mode** (QA tool absent): read the `qa-judge` prompt (resolved as in Path B step 1), adopt that role, and evaluate the Seed with the same quality bar and threshold. It returns JSON with lowercase `verdict` (`pass`/`revise`/`fail`), `score`, `dimensions`, `differences`, `suggestions`, `reasoning`; uppercase the verdict only for display and add no non-schema fields. There is no `qa_session_id`; keep pass history in the audit block.\n\nPresent, always in this order:\n1. `QA advisory: <PASS|REVISE|FAIL>, score X.XX (bar 0.90).`\n2. Below the bar: the top 2-3 suggestions as short advisory bullets (findings, not tasks). Apply none automatically.\n3. The complete Seed YAML in a fenced `yaml` block.\n4. For REVISE or FAIL, one opt-in line such as `Want a refinement pass on these findings? Otherwise the seed stands as-is.` For FAIL (< 0.40) also mention `ooo interview` (revisit requirements) or `ooo unstuck` (challenge assumptions). Then continue to \"After Seed Generation\"; the Seed is final unless the user opts in.\n\nOnly on an explicit opt-in, run one refinement pass (below), re-run QA once for an updated advisory line, and present the revised YAML. Each further pass needs a fresh explicit opt-in; never chain passes. Before each later QA call, append the previous verdict and the applied/rejected decisions to `iteration_history`.\n\n#### Refinement pass: Wonder → Reflect → Refine → Restate (opt-in)\n\nDiverge across independent sources, debate, let the user decide, then apply. No candidate is accepted by default, and you never apply a revision on your own (User Adoption Gate).\n\n**Wonder: collect proposals.**\n- **QA**: the verdict's `suggestions` (structural gaps in the YAML; QA cannot see the interview).\n- **Socratic lens** (`socratic-interviewer` prompt, resolved as in Path B step 1): check the Seed against interview evidence (persisted session state first, then this conversation) for 2-4 items: dropped or softened user constraints, rejected scope that crept back, flattened nuance, unagreed assumptions. Without evidence, record `no Socratic proposal: dialectic context unavailable`; never invent preferences. A QA/Socratic conflict goes to Reflect; neither side wins automatically.\n- **Lateral personas** (only if `ouroboros_lateral_think` is callable):\n  ```\n  Tool: ouroboros_lateral_think\n  Arguments:\n    problem_context: |\n      User opted into a refinement pass (QA advisory score X.XX, bar 0.90).\n      Current seed YAML:\n      <YAML>\n      QA suggestions:\n      - <suggestion 1>\n      Original user goal from interview: <recall>\n    current_approach: \"The seed as currently drafted (above).\"\n    persona: \"all\"\n    failed_attempts:\n      - <candidates rejected in earlier passes>\n  ```\n  Extract at most 1-2 concrete, discrete revisions from each persona's prose and drop abstract advice. If the response carries the `<!-- ouroboros-lateral-inline-dispatch-v1 base64 ... -->` sentinel and the runtime can dispatch isolated subagents, decode it and send each `payload.prompt` + `payload.context` through `orchestrate_subagents`; otherwise read the visible persona sections (split on section headers, not bare `---`). If the tool is absent, record `no lateral proposals: MCP lateral tool unavailable` and do not emulate personas.\n\n**Reflect: structure the debate.** Tag each candidate with its backing sources and a type (`expand`, `sharpen`, `remove`, `resolve_conflict`): convergent (two or more sources agree, strong), divergent (sources conflict; the user resolves it), singleton (weaker). Show a balance line such as `Balance: 4 expand / 2 sharpen / 1 remove` as information, not a warning.\n\n**Refine: user gate.** Ask single-choice `ask_user` questions only, conflicts first: one per conflict group (one option per resolution plus \"Leave unchanged\"), then strong revisions (\"apply all, review one by one, or skip\"), then singletons (\"review one by one or skip all\"). Every batch offers \"keep current seed\"; confirm free-form answers with `refine_answer`. Pass rejected candidates as `failed_attempts` on later lateral calls.\n\n**Restate: apply accepted items only.** Edit the existing YAML in place, keep fields that were already correct, and do not regenerate. If everything was skipped, the Seed stands unchanged.\n\n**Audit trail.** After each pass, append to `~/.ouroboros/seed-revisions/<revision_key>.md` (create the directory if needed): pass number, QA score, every candidate with its source tag and accepted/rejected decision, and the diff against the previous YAML. `revision_key` is the `session_id`, or, without one, `<slugified-goal>-YYYYMMDDTHHMMSSZ` derived once and reused for every pass. If the write fails, include the audit block in the response.\n\n## After Seed Generation\n\nAnnounce `Your seed has been crystallized!`\n\nThen read `~/.ouroboros/prefs.json`. If `star_asked` is not `true`, ask one single-choice question with `ask_user`: \"If Ouroboros helped clarify your thinking, a GitHub star supports continued development.\" with options:\n\n- **⭐ Star**: run `gh api -X PUT /user/starred/Q00/ouroboros`, then record `star_asked`.\n- **Not now**: record `star_asked`.\n\nOffer setup only when this Seed came from Path B (no Ouroboros MCP server): say that `ooo setup` enables `ooo run` and evaluation, and point the footer at it. After Path A, MCP already works: never suggest `ooo setup`; the footer points to `ooo run`.\n\nRecord `star_asked` with this snippet, which preserves existing keys such as `welcomeShown`, `welcomeCompleted`, and `welcomeVersion`:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nIf `star_asked` is already `true`, skip the question.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/run/SKILL.md":"---\nname: ouroboros-run\ndescription: \"Use when an Ouroboros Seed (a spec file with a goal and acceptance criteria, such as *.seed.yaml) already exists and the user wants it executed: 'run the seed', 'execute this spec', 'ooo run'. Executes it and verifies every acceptance criterion. Not for raw requests without a Seed (use interview or auto).\"\naliases: [execute]\nmcp_tool: ouroboros_start_execute_seed\nmcp_args:\n  seed_path: \"$1\"\n  cwd: \"$CWD\"\n---\n\n# /ouroboros:ouroboros-run\n\nExecute a Seed specification through the Ouroboros workflow engine as a background job. A completed run enqueues formal evaluation by default, and a rejection continues through a bounded Ralph loop.\n\n## Usage\n\n```\n/ouroboros:ouroboros-run [seed_file_or_content]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros execute\"` for `ouroboros_start_execute_seed`, `ouroboros_job_wait`, `ouroboros_job_result`, and `ouroboros_ac_tree_hud`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the **Fallback (No MCP Server)** section only when the tools are genuinely absent.\n\n### Execution Steps\n\n1. **Do not create or switch branches yourself.** For a background execution\n   job, `use_worktree` defaults to true: the server runs the task in its own\n   worktree and reports `worktree_path` / `worktree_branch` in the job result.\n   Tell the user the task was isolated only when those fields are present. A\n   `dispatch_mode=\"plugin\"` response delegates to a child session and carries\n   no worktree.\n\n2. **Get the Seed.** Read a given file path with the active runtime's `inspect_code` capability, use inline YAML directly, or otherwise take the most recently generated Seed in the conversation.\n\n   Before a fresh start, do not ask about an efficiency policy unless the user\n   raised it or `execution.default_policy` in `~/.ouroboros/config.yaml` is\n   explicitly `ask`. Otherwise omit both arguments: the server applies the\n   configured default (quality-first when nothing is configured), and its start\n   receipt names the running policy and the change command. If the user did\n   choose, or the config says `ask`, map the choice in outcome language:\n\n   - **Efficient execution**: start parallel/decomposed work economically and\n     strengthen the route only when recovery requires it. Send\n     `efficiency_mode=\"adaptive\"` and `frugality_assurance=\"observe\"`.\n   - **Quality-first execution**: keep child work at the parent starting tier.\n     Send `efficiency_mode=\"quality_first\"` and `frugality_assurance=\"off\"`.\n\n   `frugality_assurance=\"strict\"` is a separate explicit opt-in because it may\n   spend extra work on proof; never infer it from the efficiency choice. Do not\n   ask again on resume: the server restores the persisted policy and rejects a\n   resume-time change.\n\n3. **Start background execution:**\n   ```\n   Tool: ouroboros_start_execute_seed\n   Arguments:\n     seed_content: <the seed YAML>\n     efficiency_mode: <only when chosen: adaptive or quality_first>\n     frugality_assurance: <only when chosen: observe, off, or explicit strict>\n     session_id: <only when resuming an existing session>\n   ```\n   Omit `model_tier` by default so the runtime selects automatically. Include\n   `model_tier: <user choice>` only when the user explicitly requested a tier.\n   The call returns at once with `job_id`, `session_id`, and `execution_id`.\n\n4. **Hand off.** Relay the server's start receipt (IDs, backends, `Efficiency Mode` with any change command, dashboard). Then add:\n   - Live view: if `execution.tui_autolaunch: true` (or legacy top-level `tui_autolaunch: true`) is set, run `ouroboros tui open`; otherwise offer it once without blocking. If it prints a manual command (headless, SSH), relay that once.\n   - Observation: a confirmed read-only observer (step 5), or durable catch-up mode.\n   - This conversation stays available: the user can refine requirements, review code, or work on an unrelated task in an isolated worktree; check for active-worker conflicts before editing this run's workspace.\n\n5. **Delegate observation to exactly one observer.** The start result carries\n   `response.meta.job_observer`, a read-only observer contract with its own wait\n   and result tools, `instructions`, `restrictions`, and fallback. If the\n   structured meta is missing, recover the contract from the final\n   `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel and fail\n   closed: if there is more than one sentinel or it is not at the end of the\n   text, the bounded payload does not decode to an object whose only key is\n   `job_observer`, that contract fails canonical v1 validation (it must equal,\n   field for field, the v1 contract the server builds from its own `job_id`,\n   `cursor`, `session_id`, `execution_id`, and `follow_result_job_keys`, so a\n   changed tool, argument, or instruction, or an extra field, fails), its\n   `job_id` differs from the visible start receipt, or the structured and inline\n   contracts differ, do not spawn an observer and report a transport-integrity\n   failure. Never rebuild the contract from visible IDs.\n\n   With a valid contract and an independent child-session primitive, spawn\n   exactly one observer through the active runtime's `orchestrate_subagents`\n   capability and pass the contract unchanged. It owns the job cursor, follows\n   the contract (including `follow_result_job_keys` for chained evaluation and\n   Ralph), and stays read-only. Claim an observer only after the spawn returns\n   a live child ID/path. The main session must not poll the same job while the\n   observer owns it. If plugin mode already delegated the whole execution (no\n   `job_id`), follow that child's lifecycle instead.\n\n   - A `wait` call or a parent job-status poll is not a spawn. The contract's\n     `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name\n     the concrete spawn and wait mechanics; pass the contract unchanged in the\n     child message. After the live child ID returns, if the runtime cannot\n     wake a parent turn that already ended when the child posts (a child\n     message only queues for the parent), keep the parent turn open with the\n     host's child-wait primitive in waits of at most 60 seconds. Relay\n     meaningful updates and wait again until the terminal summary. User input may interrupt the wait; handle it and\n     resume unless the user asks to stop live observation or replaces the\n     request. Then end only the relay loop, keep the durable job running, and\n     offer next-turn or explicit-status catch-up. If the observer child fails,\n     is cancelled, or exits early, use that same catch-up instead of waiting\n     indefinitely. The relay loop must not poll Ouroboros job tools or touch the\n     observer's cursor.\n\n   If no child can be created, do not claim an observer or promise live\n   messages. The detached worker survives the stdio MCP turn: say progress is\n   durable and will be caught up on the next turn or an explicit status\n   request. Keep the turn open only when the user explicitly asked for live\n   watching (step 6).\n\n   **Relaying observer events.** Relay each meaningful event in 1-2 lines;\n   suppress unchanged heartbeats, raw tool output, commands, and reasoning.\n   - `run_configuration`: runtime/harness, starting model or tier when known,\n     efficiency mode, frugality assurance.\n   - `execution_plan`: total ACs, dependency/parallel levels, and the first\n     scheduled AC summaries.\n   - `discovery_summary`: bounded targets and purpose.\n   - `level_started` / `level_completed`, `ac_routing` / `harness_changed`\n     (\"currently running with\"), `ac_attempt_judged`: only real changes.\n   - `ac_accepted` / `ac_rejected`: the AC's final acceptance and compact\n     disposition evidence.\n   - `attention_required`: surface immediately (see Active Conductor below).\n   - Synapse `.queued` / `.delivering`: pending, not applied yet. `.applied` /\n     `.completed`: confirm and relay any bounded AC reply. `.rejected` /\n     `.delivery_uncertain`: surface immediately; never claim the AC changed\n     course.\n\n   These are English canonical host instructions: render every relay in the\n   user's current conversation language, keeping event codes and mode values\n   only when exact diagnostics help.\n\n6. **Fallback: live relay in the main session.** Only when there is no\n   observer contract or no child primitive, and the user explicitly asked to\n   keep watching this turn. Never run it beside a delegated observer;\n   otherwise end the turn and catch up from the same cursor next turn.\n   ```\n   Tool: ouroboros_job_wait\n   Arguments:\n     job_id: <job_id>\n     cursor: <latest cursor, or 0>\n     timeout_seconds: 180\n     view: \"summary\"\n     stream: \"linked\"\n     wait_for: \"attention_or_ac_change\"\n   ```\n   Replace the cursor from `response.meta.cursor` after every call. Treat\n   `response.meta` as the source of truth and `response.text` only as a hint.\n   If `response.meta.changed` is false, repeat silently; otherwise emit one\n   compact line (phase, AC/sub-AC counts, new current-work hint), never raw\n   JSON, the full tree, or an ETA. On `completed`, `failed`, `cancelled`, or\n   `interrupted`, say so explicitly and go to step 8.\n\n7. **Drill-down only.** Use `ouroboros_ac_tree_hud` when the user asks for\n   details or progress looks stuck, never in the routine loop. `view` is\n   `\"compact\"`, `\"summary\"`, or `\"tree\"` (add `max_nodes: 30`); treat\n   `unchanged cursor=<cursor>` as a silent no-op.\n   ```\n   Tool: ouroboros_ac_tree_hud\n   Arguments:\n     session_id: <session_id>\n     cursor: <cursor>\n     view: \"summary\"\n   ```\n\n8. **Fetch the final result in the polling owner** (the observer by default,\n   the main session only on the step 6 fallback):\n   ```\n   Tool: ouroboros_job_result\n   Arguments:\n     job_id: <job_id>\n   ```\n   Present status, session ID, and summary. Its QA verdict (skippable with\n   `skip_qa: true` at start) is not the formal 3-stage evaluator.\n\n   If the result meta has `chained_evaluate_job_id`, the polling owner follows\n   that job and fetches its result: render **APPROVED** when\n   `final_approved: true`, otherwise not approved with the failed ACs or\n   reason. If the evaluate job failed or timed out, keep the run success and\n   show `Next: ooo evaluate <session_id>` as the manual retry. If the\n   evaluation has `chained_ralph_job_id`, follow it too and report approval or\n   the bounded Ralph stop reason; a rejected first evaluation does not make\n   the run blocked.\n\n   Without `chained_evaluate_job_id`, show:\n   - **PASS**: `Next: ooo evaluate <session_id> for formal 3-stage verification`\n   - **REVISE**: the differences/suggestions, then `Next: Fix the issues above, then ooo run to retry -- or ooo unstuck if blocked`\n   - **FAIL/ESCALATE**: `Next: Review failures above, then ooo run to retry -- or ooo unstuck if blocked`\n\n### Synapse intent refinement\n\nSynapse is the `ouroboros_session_signal` channel that delivers bounded user intent to one running AC. When the user adds implementation intent during an active run, the main session picks the target; never ask the user for internal AC or session IDs.\n\n1. Call `ouroboros_session_signal_targets(execution_id=...)` with the `execution_id` from the start result or observer contract.\n2. Match the user's meaning against each target's `ac_content`, display path, and current HUD activity. Select one active target directly; with several, select only a materially more relevant one, and ask a short clarification only for a genuine tie.\n3. Additive implementation refinement: call `ouroboros_session_signal` with the target's exact scope/attempt/execution guards, `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, `fallback_mode=\"after_turn\"`, `expected_contract_version` when discovery supplies it, and one stable idempotency key for this user turn. If the target went stale, rediscover once instead of asking for IDs.\n4. Read-only question or assurance request: use `mode=\"inform\"` and `contract_effect=\"additive\"`, and omit `fallback_mode` (valid only for redirect). Relay the bounded reply from the completed event.\n5. Tell the user which AC was selected and the effective mode; say it was reflected only after `.applied` or `.completed`.\n\nNever use Synapse to change approved goals, ACs, constraints, or non-goals; those need an approved shared successor or replacement contract.\n\n### Active Conductor attention handling\n\n`recommended_host_actions` is the authoritative menu; never invent a mutating tool call.\n\n1. VERIFY with at most one short-lived read-only host child using the supplied evidence IDs. Without a verifier primitive, surface the attention and stop before mutation.\n2. DECIDE among the ordered menu actions only after engine-owned retry/routing is closed.\n3. LOG `phase=\"selected\"` through `ouroboros_record_conductor_decision` before ACT. A specification change in run mode needs explicit user approval with its receipt bound.\n4. ACT only when the menu names a currently registered MCP tool. A corrective successor preserves the approved contract unless the user approved the shared specification change.\n5. LOG exactly one terminal `completed`, `failed`, or `declined` outcome. Never silently retry a failed conductor action.\n\n## Fallback (No MCP Server)\n\nTell the user:\n\n```\nOuroboros MCP server is not configured.\nTo enable full execution mode, run: /ouroboros:setup\n\nWithout MCP, you can still:\n- Use /ouroboros:interview for requirement clarification\n- Use /ouroboros:seed to generate specifications\n- Manually implement the seed specification\n```\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/publish/SKILL.md":"---\nname: publish\ndescription: \"Publish Seed specification as GitHub Issues for team-based project management\"\n---\n\n# /ouroboros:publish\n\nConvert a Seed into a GitHub Epic issue plus Task issues. Works entirely through the `gh` CLI (no MCP), creates new issues only, and never modifies existing ones.\n\n```\nooo publish [seed_path]\n/ouroboros:publish [seed_path]\n```\n\n## Instructions\n\nRun commands with the active runtime's `run_shell` capability and ask every question with the active runtime's `ask_user` capability.\n\n### Step 1: Prerequisites\n\nRun `command -v gh`. If missing, tell the user to install it from https://cli.github.com/ and stop. Run `gh auth status`; if not authenticated, tell the user to run `gh auth login` and stop.\n\n### Step 2: Locate the Seed\n\nSeeds live in `~/.ouroboros/seeds/`: interview Seeds as `{seed_id}.yaml`, PM Seeds as `pm_seed_{id}.json`. In priority order:\n\n1. An explicit `.yaml` or `.json` path argument.\n2. The most recent files from `ls -t ~/.ouroboros/seeds/*.yaml ~/.ouroboros/seeds/*.json 2>/dev/null | head -5`; if several exist, ask the user to choose.\n3. A Seed path reported by `ooo seed` or `ooo pm` earlier in this conversation.\n\nIf none is found, tell the user to run `ooo seed` or `ooo pm` first, and stop.\n\n### Step 3: Parse the Seed\n\nDetect the format by extension. Omit any section whose field is missing or empty rather than failing.\n\nYAML Seed (`ooo interview` + `ooo seed`):\n\n| Field | Use |\n|-------|-----|\n| `goal` | Epic title and Goal section |\n| `constraints` | Constraints section |\n| `acceptance_criteria` | Epic checklist, distributed to Task issues |\n| `ontology_schema` | Ontology table (field, type, description) |\n| `evaluation_principles` | Evaluation Principles table (name, weight, description) |\n| `exit_conditions` | Exit Conditions (Definition of Done) |\n| `metadata.ambiguity_score` | Confidence indicator |\n| `metadata.seed_id` | Duplicate detection |\n\nJSON PM Seed (`ooo pm`, `PMSeed` schema):\n\n| Field | Use |\n|-------|-----|\n| `pm_id` | Duplicate detection |\n| `product_name` | Epic title prefix |\n| `goal` | Goal section |\n| `constraints` | Constraints section |\n| `success_criteria` | Acceptance Criteria checklist |\n| `user_stories` | User Stories, each as \"As a **{persona}**, I want to **{action}**, so that **{benefit}**.\" |\n| `deferred_items` | Deferred Items section |\n| `decide_later_items` | Open Questions section |\n| `assumptions` | Assumptions section |\n\n### Step 4: Target repository\n\nRun `gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null`. If it returns a repo, ask whether to publish there or to another `owner/repo`; otherwise ask for `owner/repo`. Store the answer as `TARGET_REPO`. **Every later `gh` command MUST include `-R <TARGET_REPO>`.**\n\n### Step 5: Duplicate check\n\n```bash\ngh issue list -R <TARGET_REPO> --label \"ouroboros\" --state all --search \"<seed_id or pm_id>\" --limit 5 --json number,title,state\n```\n\nThis finds earlier publishes because the Epic body records the Seed ID (Step 7). If matches exist, list them and ask whether to create anyway or cancel; on cancel, stop.\n\n### Step 6: Plan the issues\n\nGroup the acceptance criteria into logical implementation units (by feature area, layer, or dependency order); each unit becomes one Task. Show the plan (Epic goal summary, then each Task title and brief scope) and ask whether to create the issues or modify the plan. On modify, ask what to change, adjust, and show it again.\n\n### Step 7: Create the issues\n\n`gh issue create` prints the issue URL; take the number from its trailing digits (`grep -o '[0-9]*$'`). Pass bodies through a quoted heredoc (`--body \"$(cat <<'BODY' ... BODY)\"`).\n\n1. Create labels, ignoring \"already exists\":\n   ```bash\n   gh label create \"ouroboros\" -R <TARGET_REPO> --description \"Created by Ouroboros publish\" --color \"6f42c1\" 2>/dev/null || true\n   gh label create \"epic\" -R <TARGET_REPO> --description \"Epic / parent issue\" --color \"0075ca\" 2>/dev/null || true\n   gh label create \"task\" -R <TARGET_REPO> --description \"Implementation task\" --color \"008672\" 2>/dev/null || true\n   ```\n2. Epic: title `[Epic] <goal summary>`, labels `ouroboros,epic`. Body: the Step 3 sections in order (Goal, Constraints, Acceptance Criteria as `- [ ]` items, Ontology, Evaluation Principles, Exit Conditions, plus the PM-only sections), then this footer:\n   ```\n   ---\n\n   **Seed ID**: `<seed_id or pm_id>` | **Ambiguity Score**: <score> | **Seed**: `<seed_file_path>`\n   *Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n3. Each Task: title `[Task] <task title>`, labels `ouroboros,task`. Body: `Parent: #<epic>`, then Scope, Acceptance Criteria (`- [ ]` items for this unit), Test Checklist, Pass Criteria (measurable done conditions), then this footer:\n   ```\n   ---\n\n   *Part of [Epic] #<epic> | Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n4. Comment on the Epic (`gh issue comment <epic> -R <TARGET_REPO>`) with an \"Implementation Tasks\" checklist of `- [ ] #<task>: <title>` lines, noting progress is tracked by checking off tasks as their issues close.\n\n### Step 8: Summary\n\nShow `Published to <TARGET_REPO>:` with the Epic and its Tasks as a tree (`#<n> [Epic|Task] <title>`) and the link `https://github.com/<TARGET_REPO>/issues/<epic>`. Suggest next steps: assign tasks, track on a GitHub Projects board, run `ooo run` for AI-assisted implementation of individual tasks.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/qa/SKILL.md":"---\nname: qa\ndescription: \"General-purpose QA verdict for any artifact type\"\n---\n\n# /ouroboros:qa\n\nFast single-pass quality verdict with actionable suggestions for any artifact: code, documents, API responses, test output, or custom content. For formal three-stage verification of an execution, use `ooo evaluate`.\n\n```\nooo qa [file_path | artifact_text]\nooo qa                                     # recent execution output\n/ouroboros:qa [file_path | artifact_text]\n```\n\nThe QA Judge scores the artifact against a quality bar on Correctness, Completeness, Quality, Intent Alignment, and Domain-Specific dimensions:\n\n| Score | Verdict | Loop action |\n|-------|---------|-------------|\n| >= 0.80 | PASS | done |\n| 0.40 - 0.79 | REVISE | continue |\n| < 0.40 | FAIL | escalate |\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros qa\"` for `ouroboros_qa`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent; this skill works without MCP setup.\n\n### QA steps\n\n1. **Artifact**: a file path (read it with the active runtime's `inspect_code` capability), inline text, or else the most recent execution output; ask with `ask_user` if unclear.\n2. **Quality bar**: the Seed's acceptance criteria when a Seed is in context, else the user's stated bar; otherwise ask \"What does 'good' mean for this artifact?\"\n3. **Artifact type**: `code`, `test_output`, `document`, `api_response`, `screenshot`, or `custom`.\n\n3.5. **Acting verification fan-out** (behavior-bearing artifacts): a text judge can be fooled by a hopeful log line. Use the active runtime's `orchestrate_subagents` capability to launch, together, one probe child per acting modality the runtime exposes: a process probe (`run_shell`: run the command or app or smoke commands with bounded timeouts, capture exit codes and real output), a browser probe (HTTP services and web UIs: load them, exercise the primary flows, capture rendering and console/network errors), a computer-use probe (GUI/TUI: drive it like a user, screenshot observed states), and an artifact probe (`inspect_code`: declared files exist with real content, not placeholders). Each probe returns structured evidence only (commands, observed effects, screenshots/paths, pass/fail per behavior) and covers the applicable adversarial classes the QA tool lists. Skip a modality only when its tools are absent or it is meaningless for the artifact, and say which were skipped and why. Await all probes and pass the merged evidence as `reference`; prefer observed behavior over source text as the `artifact` when they disagree.\n\n4. **Call the tool**:\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the content to evaluate>\n     quality_bar: <what 'pass' means>\n     artifact_type: \"code\"  (or other type)\n     reference: <observed-behaviour evidence from step 3.5, plus any reference>\n     pass_threshold: 0.80  (adjustable)\n     seed_content: <seed YAML if available>\n   ```\n\n   **Plugin delegation**: a response with `status: \"delegated_to_subagent\"` and `dispatch_mode: \"plugin\"` carries no verdict. Its content is the bridge's dispatch notice and its `_subagent` prompt is the child's input, never a result. Keep `qa_session_id`, await the plugin-spawned child, and parse its JSON verdict (`score`, `verdict`, `dimensions`, `differences`, `suggestions`, `reasoning`). No `iteration_entry` comes back, so derive the loop action as the tool does (score >= `pass_threshold`: done; >= 0.40: continue; else escalate) and build the entry yourself (`iteration`, `score`, `verdict`, `loop_action`). If the child returns no parseable verdict, say so instead of presenting the envelope.\n\n5. **Present** the score and verdict prominently, then dimension scores, specific differences, and actionable suggestions. **Empirical evidence outranks the judge**: if the judge scores PASS but a probe observed the behavior failing, present REVISE/FAIL on that evidence and say so. If nothing could act, flag that behavior was not observed. Pick the next action from the verdict:\n   - **PASS (done)**: proceed; the artifact meets the quality bar\n   - **REVISE (continue)**: address the suggestions, then run `ooo qa` again\n   - **FAIL (escalate)**: `ooo interview` to re-examine requirements, or `ooo unstuck` to challenge assumptions\n\n### Iterative QA\n\nThe first call returns `qa_session_id` and `iteration_entry` in meta. On later calls pass `qa_session_id` and the accumulated `iteration_history`. Continue until the verdict is `pass` or `fail`.\n\n### Fallback (no Ouroboros MCP server)\n\nAdopt the `qa-judge` role yourself with the same prompt the MCP tool uses: `$OUROBOROS_AGENTS_DIR/qa-judge.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n```bash\nuvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" qa-judge.md\n```\n\nelse `src/ouroboros/agents/qa-judge.md` in a source checkout.\n\nIf none is reachable, judge on the dimensions and thresholds above and label the verdict as an unaligned fallback. Run the step 3.5 probes first for behavior-bearing artifacts, render the verdict in the same shape the MCP tool returns (score, verdict, threshold, dimensions, differences, suggestions, reasoning, loop action), and keep the iterative contract with a `qa-<uuid4_short>` session id and an iteration count held in the conversation.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/ralph/SKILL.md":"---\nname: ralph\ndescription: \"MCP-owned Ralph loop around background evolve_step jobs\"\nmcp_tool: ouroboros_ralph\nmcp_args:\n  lineage_id: \"$lineage_id\"\n---\n\n# /ouroboros:ralph\n\nMCP-owned Ralph loop around background `evolve_step` jobs. \"The boulder never stops.\"\n\n## Usage\n\n```\nooo ralph --lineage-id <lineage_id>\n/ouroboros:ralph --lineage-id <lineage_id>\n```\n\nThe `ouroboros_ralph` tool owns the loop (do not reimplement it): one background job runs repeated `evolve_step` generations until QA pass, convergence, a terminal evolution action, cancellation, or `max_generations`. Router dispatch reads only the named `--lineage-id` option, never trailing text.\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros ralph job\"` for `ouroboros_ralph`, `ouroboros_job_wait`, `ouroboros_job_status`, `ouroboros_job_result`, and `ouroboros_cancel_job`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tools are genuinely absent, stop and tell the user that Ralph requires the Ouroboros MCP runtime.\n\n### 1. Prepare lineage input\n\n- **Continue a lineage**: when the user gives an existing `lineage_id` and wants to continue it, reuse it and omit `seed_content` unless they supply an updated Seed.\n- **New run from Seed YAML**: use it as `seed_content` with a fresh `lineage_id` such as `ralph-<short-slug>-<uuid>`. Never reuse a Seed, interview, or session id as the lineage id, so separate runs over one Seed do not collide.\n- **Plain natural-language request**: never pass raw text as `seed_content` or freehand Seed YAML. Run `ooo interview` and `ooo seed` first (or reuse a validated Seed in context), then start with a fresh `lineage_id`. Without inputs the tool returns input guidance instead of a job.\n\n### 2. Start Ralph\n\nCall `ouroboros_ralph` with `lineage_id`, `seed_content` (generation 1 of a new lineage), `execute` (default `true`), `parallel` (default `true`), `skip_qa` (default `false`), `project_dir` when known, and `max_generations` (default `10`, also the hard max; lower it only on request).\n\n### 3. Handle the start response\n\n- **Job started** (`response.meta.job_id` present): keep `response.meta.cursor` and report:\n\n  ```\n  [Ralph] Started background loop: <job_id>\n  Lineage: <lineage_id>\n  Live view: <dashboard_url, or `ouroboros tui open`>\n\n  A read-only observer will post meaningful progress, attention, and terminal\n  events here. This conversation remains available for other safe work.\n  ```\n\n- **Observer handoff**: if `response.meta.job_observer` is missing, recover it from the final `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel; fail closed unless it passes canonical v1 validation and its job identity matches the visible start receipt, and use it only as an identity anchor, never to reconstruct tools or arguments. When the host supports an independent child session, spawn exactly one read-only observer and pass the contract unchanged. The observer exclusively owns job wait/result calls and the cursor; the main session keeps user conversation, explicit on-demand status, and user-requested cancellation. The main session must not poll the same job while the observer is active. It may refine requirements, do read-only review, or work in an unrelated isolated worktree; check active-worker conflicts before writing to Ralph's workspace.\n  - A `wait` call or a parent job-status poll is not a spawn; claim no observer until a live child ID/path returns. The contract's `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name the concrete spawn and wait mechanics. If the runtime cannot wake a parent turn that already ended when the child posts (a child message only queues for the parent), keep the parent turn open with the host's child-wait primitive in waits of at most 60 seconds while the observer is active. Relay meaningful updates and wait again until terminal.\n  - User input may interrupt the wait; handle it and resume waiting unless the user asks to stop live observation or replaces the request. Then end only the relay loop, keep the durable job running, and offer next-turn or explicit-status catch-up. Use the same fallback, instead of waiting indefinitely, if the observer child fails, is cancelled, or exits before a terminal summary. The relay loop must not poll the Ouroboros job or take cursor ownership.\n  - If spawn fails, promise no live relays: the detached worker continues after the stdio turn, and the main session catches up from durable events on the next interaction or explicit status request.\n- **Plugin delegation** (`response.meta.status == \"delegated_to_plugin\"`, `job_id` is `None`): a child session owns the loop. Never call job tools without a job id; treat the child session result as the terminal surface and summarize its completion/error state and lineage id.\n\n### 4. Monitor (polling owner only)\n\nThe observer is the default owner. Run this loop in the main session only when no independent child session exists and the user explicitly asked for live watching; otherwise catch up on the next turn. Never run both:\n\n- `ouroboros_job_wait(job_id, cursor, timeout_seconds=120, stream=\"linked\", wait_for=\"attention_or_ac_change\")` for long polling;\n  after every wait/status response, update `cursor = response.meta.cursor`\n- `ouroboros_job_status(job_id)` for a quick status check\n- `ouroboros_job_result(job_id)` when the job is terminal\n- `ouroboros_cancel_job(job_id)` if the user says stop/cancel\n\nRelay rules: 1-2 lines per change; surface `attention_required` and rejected or uncertain delivery immediately; distinguish Synapse `queued` from runtime-proven `applied`; never forward heartbeats, raw tool output, commands, or model reasoning. Report run configuration, AC count and parallel levels, first scheduled ACs, and verified AC completion; say \"currently running with\", since later generations may switch model or harness. When `lineage.generation.started` carries `ac_focus`, report what the generation is redoing from `active_ac_descriptions` and how many ACs stay frozen (for example \"Gen 7: reworking 2/5 ACs, 3 frozen on prior PASS evidence\"); if it is absent or every AC is active, say the full AC graph is running. Never quote verify commands or expected outputs.\n\nWhen the user asks a live AC a read-only question or adds intent, call `ouroboros_session_signal_targets` for the observed execution and pick the relevant AC without asking for internal IDs. Use `mode=\"inform\"` for questions and assurance, and omit `fallback_mode` in that mode. For implementation refinement use `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, and explicit `fallback_mode=\"after_turn\"` with the exact discovered guards, sent via `ouroboros_session_signal`. Shared goal, AC, constraint, or non-goal changes require an approved shared successor.\n\n### 5. On termination\n\nThe polling owner fetches the job result, then:\n- **Success / convergence**: summarize the final generation, QA verdict, and any `worktree_path` / `worktree_branch`. A Ralph `lineage_id` is not an execution `session_id`: offer `ooo evaluate <session_id>` only when a real execution session id is available from a separate run.\n- **Max generations / failure**: summarize the stop reason and suggest `ooo unstuck`, `ooo interview`, or a narrower Ralph retry.\n- **Cancelled**: confirm and keep the job id for later inspection.\n\n### Active Conductor decision policy\n\nFor `attention_required`, use at most one short-lived read-only verifier. If the host has no verifier primitive, surface the evidence and do not mutate. Otherwise VERIFY → DECIDE from `recommended_host_actions` → LOG `selected` with `ouroboros_record_conductor_decision` → ACT only a menu-listed registered tool → LOG exactly one `completed`, `failed`, or `declined` outcome. Ralph may apply a conductor directive only to the first and sole bounded successor generation (`max_generations=1`), and only when it is deterministic and non-relaxing. Never silently retry or weaken the approved shared contract.\n\nThese are English canonical host instructions. Render them, and every relay, naturally in the user's conversation language.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/resume-session/SKILL.md":"---\nname: resume-session\ndescription: \"List in-flight Ouroboros sessions and show the commands needed to re-attach after MCP disconnect\"\n---\n\n# /ouroboros:resume-session\n\nRecover in-flight Ouroboros sessions after an unexpected MCP server disconnect. The name avoids shadowing Claude Code's built-in `/resume`.\n\n```\nooo resume-session [--all]\n/ouroboros:resume-session\n```\n\n## Instructions\n\n1. Run with the active runtime's `run_shell` capability:\n\n   ```\n   ouroboros resume --list\n   ```\n\n   It reads the configured EventStore directly and read-only (no MCP server needed, nothing created or written) and lists `running` or `paused` sessions: the 20 most recent, or all with `--all`. `--list` prints the table and exits without the interactive prompt, which aborts when no terminal is attached. Exit code 2 means the EventStore exists but could not be read.\n\n2. If sessions are listed, show the table and ask which session to work with (active runtime's `ask_user` capability). Each row carries the `session_id`, `exec_id`, and Seed id used below.\n\n3. Give the matching re-attach path:\n\n   - Inspect persisted events (read-only, no MCP server):\n     ```\n     ouroboros status execution <exec_id> --events\n     ```\n   - Inspect interactively (read-only monitor; pick the session in the TUI):\n     ```\n     ouroboros tui monitor\n     ```\n   - Resume execution (needs the original Seed file; `--resume` takes the `session_id`):\n     ```\n     ouroboros run workflow --orchestrator --resume <session_id> <seed.yaml>\n     ```\n\n   Afterwards: `ooo evaluate` once the execution completes, or `ooo cancel <session_id>` if it is stuck.\n\nIf it reports \"No in-flight sessions found\", the execution completed, failed, or was cancelled, or the EventStore was never created; `ouroboros tui monitor` browses past sessions.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/pm/SKILL.md":"# pm\n\nPath: `skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/pm/SKILL.md)","skills/ooo/SKILL.md":"# ooo\n\nPath: `skills/ooo/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/ooo/SKILL.md)","skills/interview/SKILL.md":"# interview\n\nPath: `skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/interview/SKILL.md)","skills/help/SKILL.md":"# help\n\nPath: `skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/help/SKILL.md)","skills/evolve/SKILL.md":"# evolve\n\nPath: `skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evolve/SKILL.md)","skills/evaluate/SKILL.md":"# evaluate\n\nPath: `skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evaluate/SKILL.md)","skills/config/SKILL.md":"# config\n\nPath: `skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/config/SKILL.md)","skills/cancel/SKILL.md":"# cancel\n\nPath: `skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/cancel/SKILL.md)","skills/brownfield/SKILL.md":"# brownfield\n\nPath: `skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/brownfield/SKILL.md)","skills/auto/SKILL.md":"# auto\n\nPath: `skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/auto/SKILL.md)",".claude-plugin/skills/welcome/SKILL.md":"# welcome\n\nPath: `.claude-plugin/skills/welcome/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/welcome/SKILL.md)",".claude-plugin/skills/update/SKILL.md":"# update\n\nPath: `.claude-plugin/skills/update/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/update/SKILL.md)",".claude-plugin/skills/unstuck/SKILL.md":"# unstuck\n\nPath: `.claude-plugin/skills/unstuck/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/unstuck/SKILL.md)",".claude-plugin/skills/tutorial/SKILL.md":"# tutorial\n\nPath: `.claude-plugin/skills/tutorial/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/tutorial/SKILL.md)",".claude-plugin/skills/status/SKILL.md":"# status\n\nPath: `.claude-plugin/skills/status/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/status/SKILL.md)",".claude-plugin/skills/setup/SKILL.md":"# setup\n\nPath: `.claude-plugin/skills/setup/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/setup/SKILL.md)",".claude-plugin/skills/seed/SKILL.md":"# seed\n\nPath: `.claude-plugin/skills/seed/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/seed/SKILL.md)",".claude-plugin/skills/run/SKILL.md":"# run\n\nPath: `.claude-plugin/skills/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/run/SKILL.md)",".claude-plugin/skills/resume-session/SKILL.md":"# resume-session\n\nPath: `.claude-plugin/skills/resume-session/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/resume-session/SKILL.md)",".claude-plugin/skills/ralph/SKILL.md":"# ralph\n\nPath: `.claude-plugin/skills/ralph/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/ralph/SKILL.md)",".claude-plugin/skills/qa/SKILL.md":"# qa\n\nPath: `.claude-plugin/skills/qa/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/qa/SKILL.md)",".claude-plugin/skills/publish/SKILL.md":"# publish\n\nPath: `.claude-plugin/skills/publish/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/publish/SKILL.md)",".claude-plugin/skills/pm/SKILL.md":"# pm\n\nPath: `.claude-plugin/skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/pm/SKILL.md)",".claude-plugin/skills/interview/SKILL.md":"# interview\n\nPath: `.claude-plugin/skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/interview/SKILL.md)",".claude-plugin/skills/help/SKILL.md":"# help\n\nPath: `.claude-plugin/skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/help/SKILL.md)",".claude-plugin/skills/evolve/SKILL.md":"# evolve\n\nPath: `.claude-plugin/skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evolve/SKILL.md)",".claude-plugin/skills/evaluate/SKILL.md":"# evaluate\n\nPath: `.claude-plugin/skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evaluate/SKILL.md)",".claude-plugin/skills/config/SKILL.md":"# config\n\nPath: `.claude-plugin/skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/config/SKILL.md)",".claude-plugin/skills/cancel/SKILL.md":"# cancel\n\nPath: `.claude-plugin/skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/cancel/SKILL.md)",".claude-plugin/skills/brownfield/SKILL.md":"# brownfield\n\nPath: `.claude-plugin/skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/brownfield/SKILL.md)",".claude-plugin/skills/auto/SKILL.md":"# auto\n\nPath: `.claude-plugin/skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/auto/SKILL.md)","tests/fixtures/router/skills/frontmatter-body/run/SKILL.md":"# run\n\nPath: `tests/fixtures/router/skills/frontmatter-body/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/router/skills/frontmatter-body/run/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/AGENTS.md)","CLAUDE.md":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/CLAUDE.md)","llms.txt":"# LLM Index & Context Digest\n\nPath: `llms.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms.txt)","llms-full.txt":"# LLM Full Documentation Context\n\nPath: `llms-full.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms-full.txt)",".codex-plugin/plugin.json":"# codex-plugin Plugin Manifest\n\nPath: `.codex-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex-plugin/plugin.json)",".codex/config.toml":"# Codex Directive: config.toml\n\nPath: `.codex/config.toml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/config.toml)",".codex/hooks.json":"# Codex Directive: hooks.json\n\nPath: `.codex/hooks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/hooks.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/plugin.json)","docs/architecture.md":"# docs - System Architecture & Module Boundaries\n\nPath: `docs/architecture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/docs/architecture.md)",".agents/plugins/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.agents/plugins/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.agents/plugins/marketplace.json)","src/ouroboros/agents/advocate.md":"# Subagent: advocate\n\nPath: `src/ouroboros/agents/advocate.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/advocate.md)","src/ouroboros/agents/analysis-agent.md":"# Subagent: analysis-agent\n\nPath: `src/ouroboros/agents/analysis-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/analysis-agent.md)","src/ouroboros/agents/architect.md":"# Subagent: architect\n\nPath: `src/ouroboros/agents/architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/architect.md)","src/ouroboros/agents/breadth-keeper.md":"# Subagent: breadth-keeper\n\nPath: `src/ouroboros/agents/breadth-keeper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/breadth-keeper.md)","src/ouroboros/agents/code-executor.md":"# Subagent: code-executor\n\nPath: `src/ouroboros/agents/code-executor.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/code-executor.md)","src/ouroboros/agents/codebase-explorer.md":"# Subagent: codebase-explorer\n\nPath: `src/ouroboros/agents/codebase-explorer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/codebase-explorer.md)","src/ouroboros/agents/consensus-reviewer.md":"# Subagent: consensus-reviewer\n\nPath: `src/ouroboros/agents/consensus-reviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/consensus-reviewer.md)","src/ouroboros/agents/contrarian.md":"# Subagent: contrarian\n\nPath: `src/ouroboros/agents/contrarian.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/contrarian.md)","src/ouroboros/agents/evaluator.md":"# Subagent: evaluator\n\nPath: `src/ouroboros/agents/evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/evaluator.md)","src/ouroboros/agents/hacker.md":"# Subagent: hacker\n\nPath: `src/ouroboros/agents/hacker.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/hacker.md)","src/ouroboros/agents/judge.md":"# Subagent: judge\n\nPath: `src/ouroboros/agents/judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/judge.md)","src/ouroboros/agents/ontologist.md":"# Subagent: ontologist\n\nPath: `src/ouroboros/agents/ontologist.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontologist.md)","src/ouroboros/agents/ontology-analyst.md":"# Subagent: ontology-analyst\n\nPath: `src/ouroboros/agents/ontology-analyst.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontology-analyst.md)","src/ouroboros/agents/qa-judge.md":"# Subagent: qa-judge\n\nPath: `src/ouroboros/agents/qa-judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/qa-judge.md)","src/ouroboros/agents/research-agent.md":"# Subagent: research-agent\n\nPath: `src/ouroboros/agents/research-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/research-agent.md)","src/ouroboros/agents/researcher.md":"# Subagent: researcher\n\nPath: `src/ouroboros/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/researcher.md)","src/ouroboros/agents/seed-architect.md":"# Subagent: seed-architect\n\nPath: `src/ouroboros/agents/seed-architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-architect.md)","src/ouroboros/agents/seed-closer.md":"# Subagent: seed-closer\n\nPath: `src/ouroboros/agents/seed-closer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-closer.md)","src/ouroboros/agents/semantic-evaluator.md":"# Subagent: semantic-evaluator\n\nPath: `src/ouroboros/agents/semantic-evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/semantic-evaluator.md)","src/ouroboros/agents/simplifier.md":"# Subagent: simplifier\n\nPath: `src/ouroboros/agents/simplifier.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/simplifier.md)","src/ouroboros/agents/socratic-interviewer.md":"# Subagent: socratic-interviewer\n\nPath: `src/ouroboros/agents/socratic-interviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/socratic-interviewer.md)","tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json":"# github-pr-ops Plugin Manifest\n\nPath: `tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json)"},"files":{"skills/welcome/SKILL.md":"---\nname: welcome\ndescription: \"First-touch experience for new Ouroboros users\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:welcome\n\nInteractive onboarding for new Ouroboros users.\n\n## Usage\n\n```\n/ouroboros:welcome              # First-time or update onboarding\n/ouroboros:welcome --skip       # Skip welcome, mark as shown\n/ouroboros:welcome --force      # Force re-run welcome even if shown\n```\n\n## Instructions\n\nAsk every question with the active runtime's `ask_user` capability, in the\nuser's language. The Korean labels below are the canonical wording.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Pre-Check: Already Completed?\n\nRun the resolver, this section's blocks, and the migration check below in one\nshell call, then print the result with\n`printf 'completed=%s setup=%s codex=%s migration=%s\\n' \"$WELCOME_COMPLETED\" \"${SETUP_READY:-}\" \"${CODEX_READY:-}\" \"${LEGACY_CODEX_MODEL_MIGRATION_REQUIRED:-}\"`.\n\nRead the completion marker (legacy `welcomeShown: true` also counts):\n\n```bash\nWELCOME_COMPLETED=$(ouroboros_python - <<'PY'\nimport json, os\ntry:\n    prefs = json.load(open(os.path.expanduser('~/.ouroboros/prefs.json'), encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprint(prefs.get('welcomeCompleted') or ('legacy-welcomeShown' if prefs.get('welcomeShown') else ''))\nPY\n)\n```\n\nBefore honoring that completion marker, determine whether setup is ready for\nthe active runtime.\nA previously completed welcome must never hide the setup gate from a user who\nchose **나중에** or whose setup was later removed.\n\nClaude Code is ready when `~/.ouroboros/config.yaml` has\n`orchestrator.runtime_backend` in `{claude, claude_mcp}` and `llm.backend:\nclaude`. The marketplace plugin owns its MCP registration, so host-owned\n`~/.claude/mcp.json` is never part of readiness:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  SETUP_READY=\"true\"\nfi\n```\n\nIf `SETUP_READY` is not true, check Codex. It is ready when both backends are\n`codex`, the Codex CLI (`OUROBOROS_CODEX_CLI_PATH`, else\n`orchestrator.codex_cli_path`, else `codex` on PATH) is runnable, and\n`mcp_servers\\.ouroboros` in `$CODEX_HOME/config.toml` (any TOML key spelling)\nhas a runnable `command` or a non-blank `url`:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  CODEX_READY=\"true\"\nfi\n```\n\n### Legacy Codex Model Migration\n\nOlder configurations saved `gpt-5` into all four stage-model fields. That is\nnow an explicit pin that stops Codex App/CLI model changes from taking effect.\nNever rewrite a possible user pin silently. When Codex is ready, detect that\nexact legacy shape (or an interrupted migration) once:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$HOME/.ouroboros/prefs.json\" <<'PY'\nfrom __future__ import annotations\n\nimport json\nimport sys\nfrom pathlib import Path\n\nconfig_path, prefs_path = map(Path, sys.argv[1:])\n\ndef yaml_mapping(source: str) -> dict[str, dict[str, str]]:\n    parsed: dict[str, dict[str, str]] = {}\n    section: str | None = None\n    for raw_line in source.splitlines():\n        if not raw_line.strip() or raw_line.lstrip().startswith(\"#\"):\n            continue\n        indent = len(raw_line) - len(raw_line.lstrip())\n        key, separator, raw_value = raw_line.strip().partition(\":\")\n        if not separator:\n            continue\n        value = raw_value.strip().split(\" #\", 1)[0].strip().strip(\"'\\\"\")\n        if indent == 0:\n            section = key.strip(\"'\\\"\")\n            parsed.setdefault(section, {})\n        elif section is not None:\n            parsed[section][key.strip(\"'\\\"\")] = value\n    return parsed\n\ntry:\n    config = yaml_mapping(config_path.read_text(encoding=\"utf-8\"))\nexcept OSError:\n    raise SystemExit(1)\ntry:\n    prefs = json.loads(prefs_path.read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\n\nstage_values = (\n    config.get(\"clarification\", {}).get(\"default_model\"),\n    config.get(\"execution\", {}).get(\"default_model\"),\n    config.get(\"evaluation\", {}).get(\"semantic_model\"),\n    config.get(\"resilience\", {}).get(\"reflect_model\"),\n)\nlegacy_gpt5 = all(value == \"gpt-5\" for value in stage_values)\npartial_automatic_migration = (\n    any(value == \"gpt-5\" for value in stage_values)\n    and any(value == \"default\" for value in stage_values)\n    and all(value in {\"gpt-5\", \"default\"} for value in stage_values)\n)\nhandled = prefs.get(\"codexModelMigration\") in {\"automatic-v1\", \"kept-gpt-5-v1\"}\nraise SystemExit(0 if (legacy_gpt5 or partial_automatic_migration) and not handled else 1)\nPY\nthen\n  LEGACY_CODEX_MODEL_MIGRATION_REQUIRED=\"true\"\nfi\n```\n\nIf `CODEX_READY` and `LEGACY_CODEX_MODEL_MIGRATION_REQUIRED` are both true, ask\n\"현재 설정은 모든 단계에서 gpt-5를 고정해 두고 있어요. Codex에서 선택한 모델을 자동으로 사용하도록 바꿀까요?\"\n(header `모델 설정`) with these options:\n\n- **Codex 선택으로 전환하기 (권장)**: App이나 CLI에서 바꾼 모델을 모든 단계가 자동으로 따라가요.\n  Atomically rewrite the four pins:\n\n```bash\nouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nfrom __future__ import annotations\n\nimport os\nimport sys\nimport tempfile\nfrom pathlib import Path\n\npath = Path(sys.argv[1])\noriginal = path.read_text(encoding=\"utf-8\")\nreplacements = {\n    (\"clarification\", \"default_model\"): \"default\",\n    (\"execution\", \"default_model\"): \"default\",\n    (\"evaluation\", \"semantic_model\"): \"default\",\n    (\"resilience\", \"reflect_model\"): \"default\",\n}\nseen: set[tuple[str, str]] = set()\nsection: str | None = None\noutput: list[str] = []\nfor line in original.splitlines(keepends=True):\n    stripped = line.strip()\n    indent = len(line) - len(line.lstrip())\n    key = stripped.split(\":\", 1)[0].strip(\"'\\\"\") if \":\" in stripped else \"\"\n    if indent == 0 and \":\" in stripped:\n        section = key\n    target = (section or \"\", key)\n    if indent > 0 and target in replacements:\n        newline = \"\\n\" if line.endswith(\"\\n\") else \"\"\n        prefix = line[:indent]\n        comment = \"\"\n        value_part = line.strip().split(\":\", 1)[1]\n        if \" #\" in value_part:\n            comment = \" #\" + value_part.split(\" #\", 1)[1].rstrip(\"\\n\")\n        output.append(f\"{prefix}{key}: {replacements[target]}{comment}{newline}\")\n        seen.add(target)\n    else:\n        output.append(line)\nmissing = set(replacements) - seen\nif missing:\n    raise SystemExit(f\"Cannot migrate Codex model pins; missing keys: {sorted(missing)}\")\nupdated = \"\".join(output)\nfd, tmp_name = tempfile.mkstemp(prefix=\".config.yaml.\", dir=str(path.parent))\ntry:\n    with os.fdopen(fd, \"w\", encoding=\"utf-8\") as tmp:\n        tmp.write(updated)\n        tmp.flush()\n        os.fsync(tmp.fileno())\n    os.replace(tmp_name, path)\nfinally:\n    try:\n        os.unlink(tmp_name)\n    except FileNotFoundError:\n        pass\nPY\n```\n\n  `default` sends no model pin to Codex; it is not a model named \"default\".\n  Confirm the rewrite succeeded before recording the decision. An interrupted\n  rewrite leaves a partial `gpt-5`/`default` state that the next check offers\n  again.\n- **gpt-5 고정 유지하기**: 지금처럼 모든 단계를 gpt-5로 계속 실행해요. Do not\n  change `config.yaml`.\n\nFor either choice, merge exactly one `codexModelMigration` marker into\n`~/.ouroboros/prefs.json`, keeping existing keys:\n\n```bash\nouroboros_python - \"automatic-v1\" <<'PY'\nimport json, os, sys\npath = os.path.expanduser('~/.ouroboros/prefs.json')\ntry:\n    prefs = json.load(open(path, encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprefs['codexModelMigration'] = sys.argv[1]\nos.makedirs(os.path.dirname(path), exist_ok=True)\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nPass `kept-gpt-5-v1` instead of `automatic-v1` for the keep choice. If welcome\nwas already completed, confirm briefly and exit; do not also ask the generic\nwelcome question.\n\n### Routing After the Pre-Check\n\n- **Completed, `SETUP_READY` or `CODEX_READY` true, no `--force`**: ask\n  \"Ouroboros welcome was already completed on $WELCOME_COMPLETED. What would\n  you like to do?\" with **Skip** (continue to work, recommended; exit) and\n  **Re-run welcome** (continue to Step 1).\n- **Completed but neither ready**: skip that prompt and go to the Setup Gate.\n- **`--skip`**: write the completion prefs (Step 4), print\n  `Ouroboros welcome skipped. Run /ouroboros:welcome --force to re-run onboarding.`,\n  and exit.\n\n### Setup Gate: First Use\n\nUse the readiness the Pre-Check printed; a global `config.yaml` alone is not\nenough unless it names a runtime these gates recognize. To recheck after a\nsetup run (or when the Pre-Check did not run), use these standalone gates,\nwhich print their verdict. Claude Code:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"SETUP_READY\"\nelse\n  echo \"SETUP_REQUIRED\"\nfi\n```\n\nIf that printed `SETUP_READY`, skip the Codex gate and continue to Step 1.\nOtherwise check Codex:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"CODEX_READY\"\nelse\n  echo \"CODEX_SETUP_REQUIRED\"\nfi\n```\n\nIf neither is ready (`SETUP_REQUIRED` and `CODEX_SETUP_REQUIRED`, including a\nconfig that names a runtime neither gate recognizes), ask\n\"Ouroboros를 처음 사용하시네요. 시작하기 전에 실행 환경을 설정할까요?\"\n(header `Ouroboros 시작하기`):\n\n- **설정하고 시작하기 (권장)**: 한 번만 설정하면 바로 사용할 수 있어요. Run the\n  setup for the active host yourself; never ask the user to copy a command the\n  host can run. In Codex App or Codex CLI, run `ouroboros setup --runtime codex`\n  when the executable is installed. For a Marketplace-plugin-only install run\n  `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ouroboros setup --runtime codex`\n  instead. In Claude Code, follow `../setup/SKILL.md`.\n- **나중에**: 지금은 기본 안내만 보고 나중에 설정할게요. Continue the welcome\n  flow without claiming MCP-backed features are ready.\n\nAfter a successful **Codex** setup, ask \"설정이 완료됐어요. 기본적으로 Codex에서\n선택한 모델을 사용합니다. 모델은 언제든 나중에 바꿀 수 있어요.\" (header `준비 완료`):\n\n- **바로 시작하기 (권장)**: 기본 모델로 바로 작업을 시작해요. Continue to Step 1.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. On the user's local Codex App\n  or CLI it opens the settings UI in their browser at a\n  temporary `localhost` address (not an external website). It offers **Use Codex default model** and\n  **Enter another model ID…** for a deliberate stage pin. Continue to Step 1\n  when the settings session ends.\n\nIn Claude Code, `../setup/SKILL.md` asks the equivalent model question itself;\ndo not ask it again. Do not show this gate again once a runtime is ready; the\nsettings UI stays available through `ooo config`.\n\n### Step 1: Banner\n\n```\nWelcome to Ouroboros!\n\nMost AI coding fails at the input, not the output.\nOuroboros exposes hidden assumptions BEFORE any code is written.\n\nInterview -> Seed -> Execute -> Evaluate\n    ^                            |\n    +---- Evolutionary Loop -----+\n```\n\nOrdinary Claude setup uses the default `[claude]` Agent SDK profile on MCP 1.x.\nNever inspect or mutate `~/.claude/mcp.json` as a health check. If Ouroboros\nMCP tools are not callable here, say that MCP-backed commands need a supported\nhost setup, which owns an isolated `[mcp]` launcher; `[claude-sdk]` and\n`[mcp]` are never installed together.\n\n### Step 2: Persona\n\nAsk \"What brings you to Ouroboros?\" with **New project idea** (crystallize a\nvague idea into a Seed), **Tired of rewriting prompts** (AI keeps building the\nwrong thing), and **Just exploring**. Reply in 1-2 personalized sentences.\n\n### Step 3: First Action\n\nShow the core commands: `ooo interview` (Socratic Q&A that exposes hidden\nassumptions), `ooo seed` (freeze answers into a Seed), `ooo run` (execute a\nSeed), `ooo evaluate` (verify against the acceptance criteria), `ooo unstuck`\n(lateral thinking), `ooo config` (settings), `ooo help` (full reference).\n\nAsk \"What would you like to do first?\":\n\n- **Start a project**: ask \"What do you want to build?\", then continue as `ooo interview`.\n- **Try the tutorial**: continue as `ooo tutorial`.\n- **Read the docs**: continue as `ooo help`.\n\nRun Step 4 before handing off, so completion is recorded even when the next\ncommand takes over the conversation.\n\n### Step 4: GitHub Star and Completion\n\nRun `gh auth status &>/dev/null && echo GH_OK || echo GH_MISSING`. If `GH_OK`\nand `star_asked` is not true in `~/.ouroboros/prefs.json`, ask \"If you're\nenjoying Ouroboros, would you like to star it on GitHub?\" with **Star on\nGitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`) and **Maybe later**.\n\nThen merge the completion fields into `~/.ouroboros/prefs.json`, keeping\nexisting keys. Prefix the command with `STAR_ASKED=true` when the star question\nwas asked, so it is never repeated:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\nfrom datetime import UTC, datetime\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs.update({\n    'welcomeShown': True,\n    'welcomeCompleted': datetime.now(UTC).isoformat(),\n})\nif os.environ.get('STAR_ASKED') == 'true':\n    prefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nBefore the handoff, mention that phrases like \"interview me\", \"I'm stuck\", or \"evaluate this\" also\nroute to the matching command; to watch `ooo run` or `ooo evolve` live, run\n`uvx --python '>=3.12' --from 'ouroboros-ai[tui]' ouroboros tui monitor` in a\nseparate terminal.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/status/SKILL.md":"---\nname: ouroboros-status\ndescription: \"Check session status and measure goal drift\"\naliases: [drift]\nmcp_tool: ouroboros_session_status\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:ouroboros-status\n\nCheck an execution session's status and, on request, measure drift from the Seed goal.\n\n```\n/ouroboros:ouroboros-status [session_id]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros session status\"` for `ouroboros_session_status` and `ouroboros_measure_drift`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\n### Steps\n\n1. Session: use the given `session_id`, else the most recent one in the conversation, else ask the user.\n\n2. Call `ouroboros_session_status` MCP tool:\n   ```\n   Tool: ouroboros_session_status\n   Arguments:\n     session_id: <session ID>\n   ```\n\n3. If the user asks about drift (or says \"am I drifting?\"), also call `ouroboros_measure_drift`:\n   ```\n   Tool: ouroboros_measure_drift\n   Arguments:\n     session_id: <session ID>\n     current_output: <current execution output or file contents>\n     seed_content: <original seed YAML>\n     constraint_violations: []  (any known violations)\n     current_concepts: []       (concepts in current output)\n   ```\n\n4. Show the status and progress, and the drift report as the tool renders it (weights, threshold, breakdown, suggestions). When combined drift exceeds 0.3 (status `EXCEEDED`), warn and suggest `ooo interview` to re-clarify or `ooo evolve` to course-correct; otherwise suggest continuing with `ooo run` or `ooo evaluate`.\n\n## Fallback (no MCP server)\n\nTell the user session tracking needs the Ouroboros MCP server (`ooo setup`), and that without it they can compare the implementation against the Seed by hand.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/update/SKILL.md":"---\nname: update\ndescription: \"Check for updates and upgrade Ouroboros to the latest version\"\n---\n\n# /ouroboros:update\n\nUpgrade Ouroboros without changing the installation's manager, environment, or optional-dependency profile.\n\n```\nooo update\n/ouroboros:update\n```\n\n## Instructions\n\nThe native command is the single source of truth. Run it with the active runtime's `run_shell` capability.\n\n1. Run `ouroboros update --check`.\n   - **Up to date**: report the package result together with any Codex plugin version mismatch or unknown-status warning, then stop. Do not infer that every integration is current from the package version.\n   - **Update available**: ask the user (active runtime's `ask_user` capability) to choose **Update now** or **Skip**. On **Update now**, run `ouroboros update --yes`. When the user actively uses both Claude Code and Codex, run `ouroboros update --yes --runtime all` instead; it refreshes both host integrations without changing the configured execution backend. Show the command's result.\n\n2. If the check fails but `ouroboros update --help` works, report the native error and stop. Never substitute a manual upgrade, and never infer ownership from `uv tool list`, `pipx list`, PATH order, directory names, or the active agent runtime.\n\n3. If `ouroboros update --help` does not work, this is a legacy install that predates the receipt-bound updater. Fail closed: only a read-only `ouroboros --version` is allowed. Explain that the original manager, environment, and extras cannot be proven, and ask the user to rerun their exact original install command (including its `ouroboros-ai[...]` extras and custom manager root), or to do a fresh isolated install if they do not know it. Run no package upgrade, plugin refresh, or setup command on this path.\n\n4. After a successful update, relay the command's restart guidance (Claude may use `/reload-plugins` or restart; active Codex sessions need a restart) and any Codex plugin version diagnostic. A mismatch is advisory; preserve existing marketplace refs rather than automatically removing or advancing a pin. If project instruction content needs regeneration, suggest `ooo setup`; never edit project instruction files as part of the update.\n\nThe updater replays the environment's install receipt, so the Claude SDK and MCP 2 profiles are never combined or substituted. Other options: `--dry-run`, `--prerelease`; see `ouroboros update --help`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/tutorial/SKILL.md":"---\nname: tutorial\ndescription: \"Interactive tutorial teaching Ouroboros hands-on\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:tutorial\n\nInteractive tutorial that teaches Ouroboros through hands-on experience.\n\n## Usage\n\n```\nooo tutorial\n/ouroboros:tutorial\n```\n\n## Principles\n\n1. Show something useful in the first 30 seconds.\n2. Learn by doing: the user answers questions about their own idea.\n3. Reveal features gradually.\n4. Always end a phase with one specific next action.\n5. Match the audience: technical users get the run, evaluate, and evolve\n   details; non-technical users get the interview and plain language.\n\n## Flow (about 5 minutes)\n\n1. **Hook.** Promise that in five minutes their vague idea becomes a precise\n   specification, then ask what they want to build. If they have no idea, use a\n   task-management CLI as the example.\n2. **Interview.** Ask 3-4 Socratic questions about their idea (the problem it\n   solves, the main users, the one feature that makes it useful now). Point out\n   that each answer surfaced an assumption they had not stated.\n3. **Mini-Seed.** Summarize their answers in Seed vocabulary:\n\n   ```\n   Goal: <their goal, refined>\n   Constraints: <2-3 constraints they named>\n   Acceptance criteria: <2-3 checkable outcomes>\n   ```\n\n   Do not invent an ambiguity score. Explain that `ooo interview` measures\n   ambiguity and continues until it is low enough to freeze a real Seed.\n4. **The workflow.** `Interview → Seed → Execute → Evaluate`, with evaluation\n   feeding back into the next Seed generation:\n\n   ```\n   ooo interview \"your idea\"   # expose assumptions\n   ooo seed                    # freeze the Seed\n   ooo run                     # execute it\n   ooo evaluate                # verify against the acceptance criteria\n   ooo status                  # check drift\n   ```\n\n   `ooo unstuck` helps when blocked. `run`, `evaluate`, `evolve`, and `status`\n   need the Ouroboros MCP server (`ooo setup`).\n5. **Next step.** Offer: start a real project (`ooo interview \"your actual\n   project idea\"`), the full reference (`ooo help`), or setup (`ooo setup`).\n\nIf the user asks how this differs from prompting an AI assistant directly:\nwithout a spec, the assistant guesses and you rewrite the prompt until it\nmatches; with Ouroboros, the interview exposes hidden assumptions first, so the\nbuild starts from an agreed Seed. If it seems complicated, three commands cover\nmost use: `ooo interview`, `ooo seed`, `ooo run`.\n\nThe tutorial is done when the user has experienced the interview, understands\nwhat a Seed is, and has chosen a next step.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/unstuck/SKILL.md":"---\nname: unstuck\ndescription: \"Use when the user is stuck or going in circles: the same fix failed twice or more, 'nothing works', 'I've tried everything', or a consequential choice with no clear winner that is hard to undo or splits the team (which database, which architecture). Brings hacker, researcher, simplifier, architect, and contrarian perspectives and converges on one recommendation. Not for a first error or normal progress.\"\naliases: [stuck, lateral]\n---\n\n# /ouroboros:unstuck\n\nBreak through stagnation, or advise on a hard choice, with lateral thinking personas. **Solo** runs one persona; **debate** runs several in parallel and synthesizes them.\n\n## Usage\n\n```\nooo lateral                       # debate: all 5 lateral personas\nooo lateral <persona>             # solo: one persona\nooo lateral debate <p1> <p2> ...  # debate with explicit members\nooo lateral @all                  # debate preset (the only preset)\n```\n\n## Personas (lateral pool)\n\nStateless reframing lenses only; stateful roles (evaluator, qa-judge, ontologist, socratic-interviewer) have their own skills.\n\n| Persona | Lens | Use when |\n|---------|------|----------|\n| **hacker** | Make it work first, elegance later | Overthinking blocks progress |\n| **researcher** | What information are we missing? | The problem is unclear |\n| **simplifier** | Cut scope, return to MVP | Complexity is overwhelming |\n| **architect** | Restructure the approach entirely | The current design is wrong |\n| **contrarian** | Are we solving the wrong problem? | Assumptions need challenging |\n\nBesides direct `ooo lateral`, you MAY chain into this skill from another skill (for example as `socratic-interviewer` in `ooo interview`) when the current question needs multi-perspective deliberation; afterwards summarize the options, return to the parent flow, and let the user decide.\n\n## Instructions\n\n### Step 1: Parse args into a mode\n\n| Input | Mode | Members |\n|---|---|---|\n| no args, `debate`, or `@all` | debate | all 5 personas |\n| `<persona>` | solo | that persona |\n| `debate <p1> <p2> ...` | debate | the listed personas |\n| `@<unknown-preset>` | error | reject and list known presets |\n| `<unknown-persona>` | error | reject and list the 5 personas |\n| `<p1> <p2> ...` without `debate` | error | reject and suggest `ooo lateral debate <p1> <p2>` |\n\nValidate every persona name against the pool; never coerce silently. When a parent skill wants one persona but names none, omit `persona` and pass `stagnation_pattern` (`spinning`, `oscillation`, `no_drift`, `diminishing_returns`) if known; the server picks the persona (default contrarian).\n\nPick the lateral **mode** too. Use `mode=\"decision\"` when the user faces a consequential choice between options (which database, which architecture) rather than a stall; otherwise omit `mode` (default `unstuck`). In decision mode, `problem_context` describes the options and `current_approach` the currently favored one (or `undecided`), and an omitted persona means a full debate. Pass `research=true` only when the user explicitly asks for web-grounded research; it is slower and never the default.\n\n### Step 2: Gather required context before the MCP call\n\nThe tool hard-fails when `problem_context` or `current_approach` is empty, so resolve both first (solo and debate alike):\n\n1. Reuse session state from the parent skill or recent conversation: `problem_context` (what the user is stuck on, 1-3 sentences), `current_approach` (what was tried; `\"none yet, first attempt\"` is fine), and optional `failed_attempts`.\n2. If either field is unrecoverable, ask the user one combined question with the active runtime's `ask_user` capability: \"Two things I need before lateral thinking can run: (1) what are you stuck on right now, (2) what have you already tried? A sentence each is enough.\" Wait for the answer. Never fabricate these fields; `current_approach=\"not specified\"` is acceptable, invented content is not.\n\n### Step 3: Always call `ouroboros_lateral_think`\n\nEvery invocation routes through the MCP tool, solo and debate, in every runtime; never substitute a direct subagent fan-out.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros lateral\"` for `ouroboros_lateral_think`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision` (decision mode). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent (neither exposed nor loadable), stop and report that the MCP dispatch surface is broken; do not improvise solo or debate without it.\n\nCall it with:\n- **Solo**: `persona=<one>`, `problem_context`, `current_approach`, `failed_attempts`.\n- **Debate**: `personas=[...]`, `problem_context`, `current_approach`, `failed_attempts`.\n- Plus `mode`/`research` from Step 1, and `session_id` when running inside an interview or lateral session (it binds the fan-out so results submitted from another session are refused).\n\n### Step 4: Act on the response shape (the server picks it)\n\n| Mode | Plugin response | Inline response |\n|---|---|---|\n| Solo | one `_subagent` object | one `# Lateral Thinking: <approach>` block in `content` |\n| Debate | `_subagents` array (N objects) | N blocks joined by `\\n\\n---\\n\\n`, plus a hidden dispatch block carrying the same N payloads |\n\n**Inline dispatch block (debate, inline only).** Prefer the structured copy in the response meta when present. Otherwise take the text between `<!-- ouroboros-lateral-inline-dispatch-v1 base64\\n` and `\\n-->` at the end of `content`, base64-decode it, and parse the JSON. A host that did not declare subagent capability receives the neutral shape:\n\n```json\n{\"dispatch_mode\": \"host_decides\", \"host_action\": \"dispatch_subagents_if_supported\", \"execution_preference\": \"parallel\", \"fallback_strategy\": \"sequential\", \"persona_count\": N, \"payloads\": [...]}\n```\n\nAn explicitly sequential execution authority receives `dispatch_mode=\"sequential\"` with `legacy_dispatch_mode=\"inline_fallback\"`, which is compatibility metadata only. Never split the joined display text on `---`: user content can contain the separator.\n\n#### Shape A: plugin response (OpenCode plugin mode)\n\nThe plugin spawns the children itself. Await the single `_subagent` result (solo) or all `_subagents` results (debate), then present or synthesize. If the response is inline text with neither key, you are not in plugin mode: use Shape B.\n\n#### Shape B: inline response\n\nThe dispatch block distinguishes declared `host_driven`, capability-neutral `host_decides`, and explicit `sequential` execution. **Solo**: present the approach summary, reframing prompt, and questions to consider, then route back to the workflow.\n\n##### Debate, runtime supports sub-agent dispatch\n\n1. Show the visible markdown under a short \"what the lateral toolkit suggests\" header.\n2. With `host_action=\"spawn_subagents\"`, or `host_action=\"dispatch_subagents_if_supported\"` when the runtime has a native parallel primitive, use the active runtime's `orchestrate_subagents` capability: one isolated child per payload, launched together, each given its `prompt` verbatim plus its `context`.\n3. Await all children and correlate each result by `result_correlation_key` (normally `context.persona`).\n4. Optional Round 2 cross-attack, only when Round 1 answers diverge: give each persona short summaries of the others and ask \"Identify one weakness in each. 200 words max.\"\n5. Synthesize (below).\n\n##### Debate, constrained runtime without sub-agent dispatch\n\nIf the response is stamped with `dispatch_mode=\"sequential\"`, or with `dispatch_mode=\"host_decides\"` and the host has no native parallel primitive, process each recovered payload in order, correlate every result by `result_correlation_key`, and synthesize after the last one. If no payloads are recoverable (no meta copy and no dispatch block), present the handler's markdown as-is and synthesize from that text; there is no Round 2.\n\n##### Synthesize (debate, all shapes)\n\nIn decision mode, follow the synthesis contract the response carries: exactly one recommendation stated first, its grounds (citing only sources personas actually fetched), the strongest dissent, and flip conditions. After the user accepts, offer to persist it with `ouroboros_record_conductor_decision` as the contract describes.\n\nIn unstuck mode, present options, not a verdict:\n\n```\n## Debate result: N personas\n\n### Options\n- **Option A** (from <persona>): <one-liner>\n- **Option B** (from <persona>): <one-liner>\n\n### Disagreements\n- <persona X> vs <persona Y>: <what they disagree about>\n\n### Recommended (with reasoning)\n<your single best read, labeled as your recommendation>\n```\n\nIn both modes the choice is the user's: never auto-progress to the next workflow step on their behalf.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/setup/SKILL.md":"---\nname: setup\ndescription: \"Guided onboarding wizard for Ouroboros setup\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:setup\n\nGuided Ouroboros setup inside a Claude Code session.\n\n> Other runtimes (Codex, Copilot, OpenCode, and others) configure through the\n> CLI instead, for example `ouroboros setup --runtime codex` or\n> `ouroboros setup --runtime copilot`. See\n> [Getting Started](https://github.com/Q00/ouroboros/blob/main/docs/getting-started.md).\n\n## Usage\n\n```\nooo setup\n/ouroboros:setup\n/ouroboros:setup --uninstall\n```\n\nClaude setup confirms the runtime profile (the Claude Agent SDK on MCP 1.x)\nand optionally adds an Ouroboros reference block to the project's CLAUDE.md.\nIt deliberately leaves `~/.claude/mcp.json` untouched because marketplace\nplugin wiring owns that file. `[claude]` and its explicit `[claude-sdk]` alias\nuse MCP 1.x. The plugin launches `[mcp]` in a separate MCP 2 process with the\ndependency-free `[claude-cli]` worker.\n\n## Setup Wizard Flow\n\nAsk questions with the active runtime's `ask_user` capability unless a step\nsays otherwise.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Step 0.5: Community Support\n\nIf `star_asked` is not `true` in `~/.ouroboros/prefs.json`, ask \"Ouroboros is\nfree and open-source. A GitHub star helps other developers discover it. Star\nthe repo?\" with **Star on GitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`)\nand **Skip for now**. After any answer, merge `star_asked: true` into the\nprefs file, keeping existing keys:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\n### Step 1: Environment Detection\n\n```bash\nouroboros_python --version\nwhich uvx 2>/dev/null && uvx --version 2>/dev/null\nwhich claude 2>/dev/null\nuv python list 2>/dev/null | grep \"cpython-3.1[2-9]\"\n```\n\nThe resolver already rejects Python below 3.12 and falls back to a uv-managed\ninterpreter; that does not make the `[claude-sdk]` and MCP 2 profiles\nimport-compatible. Report what was found, then:\n\n| Environment | Action |\n|:------------|:-------|\n| Python >= 3.12 + Claude CLI | Ready: configure `[claude]` SDK/MCP 1 and skills |\n| uvx + Python >= 3.12 | MCP-capable elsewhere: use a supported CLI-backed runtime setup for isolated `ouroboros-ai[mcp]` |\n| Python < 3.12 only | Run `uv python install 3.12`, then re-run `ooo setup` |\n| No package runner or Ouroboros package | Install uv (below), then re-run `ooo setup` |\n\nPrefer package managers for uv: `pipx install uv`, `pip install --user uv`, or\n`brew install uv`; the vendor one-liner\n`curl -LsSf https://astral.sh/uv/install.sh | sh` is the last resort.\n\n**IMPORTANT**: Never install `[mcp,claude]`, `[mcp,claude-sdk]`, or `[all,mcp]`\ntogether and never write a direct\n`ouroboros` or `python -m ouroboros` MCP fallback. MCP 2 launchers must use an\nisolated `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ...` or\n`pipx run --spec 'ouroboros-ai[mcp]' ...` process. Only `[mcp,claude-cli]` is\nsupported because the CLI worker is out of process. Do not write\nan Ouroboros entry to `~/.claude/mcp.json`; the plugin owns that registration.\n\n### Step 1.5: Runtime Configuration\n\nWrite the Claude runtime selection to `~/.ouroboros/config.yaml`. The welcome\ngate and the CLI read it; nothing else in this wizard writes it. This step\nnever touches `~/.claude/mcp.json`.\n\nDefine `ouroboros_cli` in the same shell as each command below (shell state\ndoes not persist between commands):\n\n```bash\nouroboros_cli() {\n  if command -v ouroboros >/dev/null 2>&1; then\n    command ouroboros \"$@\"\n  else\n    uvx --isolated --python '>=3.12' --from 'ouroboros-ai' ouroboros \"$@\"\n  fi\n}\nouroboros_cli config show orchestrator\nouroboros_cli config show llm\n```\n\nThe welcome gate is ready only when `orchestrator.runtime_backend` is `claude`\nor `claude_mcp` AND `llm.backend` is `claude`. A missing file or section\ncounts as not set.\n\n- Both conditions hold: already configured. Skip to Step 2.\n- `runtime_backend` is `claude_mcp` but `llm.backend` is not `claude`: run\n  `ouroboros_cli setup --runtime claude-cli --non-interactive` (keeps the CLI\n  transport).\n- `runtime_backend` is another runtime (for example `codex`): ask the user\n  whether to switch the default runtime to Claude. If they decline, keep the\n  existing configuration and skip to Step 2.\n- Otherwise (`runtime_backend` is `claude` with another `llm.backend`, no\n  config, no `orchestrator` section), or after the user agrees to switch, run:\n\n```bash\nouroboros_cli setup --runtime claude --non-interactive\n```\n\nBoth setup commands set `llm.backend: claude`; `--runtime claude` sets\n`orchestrator.runtime_backend: claude` and `--runtime claude-cli` sets `claude_mcp`.\nIf it fails, show the error and continue the wizard; Step 4 reports the\nruntime as not configured.\n\n### Step 2: MCP Profile Boundary\n\nTell the user: the default Claude SDK profile stays on MCP 1.x, and the\nplugin-owned MCP server runs MCP 2 separately with the `[claude-cli]` worker.\n**Do not create, update, or remove `~/.claude/mcp.json`.** Existing entries may\nbe user-managed or belong to another compatible runtime. Advanced MCP\nworkflows require a host-managed isolated `[mcp]` launcher, which the Claude\nmarketplace plugin or another supported host setup owns.\n\n### Step 3: CLAUDE.md Integration (Optional)\n\nOffer **Integrate / Skip / Preview first** for adding this ~40-line reference\nblock (pipeline, command table, agent catalog) to the project's CLAUDE.md. On\n**Preview first**, show it:\n\n````markdown\n<!-- ooo:START -->\n<!-- ooo:VERSION:0.59.8 -->\n# Ouroboros — Specification-First AI Development\n\n> Before telling AI what to build, define what should be built.\n> As Socrates asked 2,500 years ago — \"What do you truly know?\"\n> Ouroboros turns that question into an evolutionary AI workflow engine.\n\nMost AI coding fails at the input, not the output. Ouroboros fixes this by\n**exposing hidden assumptions before any code is written**.\n\n1. **Socratic Clarity** — Question until ambiguity ≤ 0.2\n2. **Ontological Precision** — Solve the root problem, not symptoms\n3. **Evolutionary Loops** — Each evaluation cycle feeds back into better specs\n\n```\nInterview → Seed → Execute → Evaluate\n    ↑                           ↓\n    └─── Evolutionary Loop ─────┘\n```\n\n## ooo Commands\n\nEach command loads its agent/MCP on-demand. Details in each skill file.\n\n| Command | Loads |\n|---------|-------|\n| `ooo` | — |\n| `ooo interview` | `ouroboros:socratic-interviewer` |\n| `ooo seed` | `ouroboros:seed-architect` |\n| `ooo run` | MCP required |\n| `ooo evolve` | MCP: `evolve_step` |\n| `ooo evaluate` | `ouroboros:evaluator` |\n| `ooo unstuck` | `ouroboros:{persona}` |\n| `ooo status` | MCP: `session_status` |\n| `ooo setup` | — |\n| `ooo help` | — |\n\n## Agents\n\nLoaded on-demand — not preloaded.\n\n**Core**: socratic-interviewer, ontologist, seed-architect, evaluator,\nadvocate, contrarian, judge\n**Support**: hacker, simplifier, researcher, architect\n<!-- ooo:END -->\n````\n\nOn **Integrate**: back up CLAUDE.md to CLAUDE.md.bak, append the block, and\nconfirm.\n\n### Step 4: Verification\n\nConfirm (with the Step 1.5 `config show` commands) that the saved Ouroboros\nconfig selects the default Claude Agent SDK runtime\non MCP 1.x while `~/.claude/mcp.json` was not mutated by this setup. The\ndependency-free Claude CLI worker remains a distinct, explicit `[claude-cli]`\nselection for the isolated MCP 2 process.\n\n### Step 5: Success Summary\n\n```\nOuroboros Setup Complete!\n\nMode:                     Claude Agent SDK (MCP 1.x)\nMCP Server:               Host-owned (config not mutated)\nCLAUDE.md:                <integrated | skipped>\n\nNext: ooo interview \"your project idea\" | ooo tutorial | ooo help\n```\n\n### Step 5.1: Model Choice (Claude Code)\n\nOffer optional model control. Ask \"설정이 완료됐어요. 기본 모델 설정으로 바로\n시작할 수 있고, 모델은 언제든 나중에 바꿀 수 있어요.\" (header `모델 설정`):\n\n- **바로 시작하기 (권장)**: 기본 모델 설정으로 바로 작업을 시작해요. Continue to Step 5.5.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. In the local Claude Code\n  harness it opens the settings UI in the user's browser at a temporary\n  `localhost` address. They can reopen it any time with `ooo config`; this\n  choice never permanently locks a model.\n\n### Step 5.5: Brownfield Repository Scan\n\nRegister existing git repositories and linked worktrees in the Ouroboros DB so\ninterviews can use them as brownfield context. Use the MCP tool only, not the\nCLI or Python scripts.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros brownfield\"` for `ouroboros_brownfield` (both the scan and the later `set_defaults` call). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent, skip this step and continue to Step 6.\n\n1. Scan and register:\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"scan\" }\n   ```\n   The walk starts at `scan_root` (default: the user's home directory) and\n   goes at most two directory levels deep, skipping dot-prefixed and noisy\n   directories such as `node_modules`. Normal repos (`.git` directory) and\n   linked worktrees (`.git` file) reached by the walk are registered self-only.\n   Git worktree families are not expanded. Repos with no remote or any remote\n   name are eligible. Existing defaults are preserved.\n\n2. The scan response `text` already holds a numbered list with default\n   markers. **Do NOT make any additional MCP calls to list or query repos.**\n   Show every repo in a plain-text two-column grid inside a code block (not a\n   markdown table), keeping the `*` default markers exactly as returned:\n\n   ```\n   Scan complete. 8 repositories registered.\n\n    1. repo-alpha                   5. repo-epsilon\n    2. repo-bravo *                 6. repo-foxtrot\n   ```\n\n   If no repos were found, skip to Step 6.\n\n3. **Do NOT use the active runtime's `ask_user` dialog for this selection.** Text emitted between\n   tool calls is not guaranteed to render, so a dialog can appear without the\n   list, and option previews truncate long lists. Instead, end the turn with the repo grid as the final message, followed by the prompt:\n\n   - Defaults exist: `Current defaults: <names> (numbers <numbers>)`, then\n     `Reply with repo numbers to change defaults (e.g. \"6, 18, 19\"), \"keep\" to keep the current defaults, or \"none\" to clear them.`\n   - No defaults: `No defaults set. Reply with repo numbers to set defaults (e.g. \"6, 18, 19\"), or \"none\" to run interviews in greenfield mode.`\n\n4. On the next turn: numbers (any separator) select those IDs; \"keep\" skips\n   the MCP call and leaves defaults unchanged; \"none\" clears all; anything else\n   gets the prompt again (never guess). Then make ONE call that replaces all\n   defaults (`\"indices\": \"\"` for none):\n\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"set_defaults\", \"indices\": \"<comma-separated IDs>\" }\n   ```\n\n   Confirm the resulting defaults, or that interviews will run in greenfield\n   mode, and mention that `ooo setup` or `ooo brownfield` changes them later.\n\n### Step 6: First Project Nudge\n\nSuggest `ooo interview \"Build a CLI tool for [something you need]\"` or\n`ooo tutorial`.\n\n## Uninstall\n\nOn `--uninstall`, ask for confirmation, explaining that it removes only the\nOuroboros block from CLAUDE.md, not plugin files, seeds, or project data. If\nconfirmed:\n1. Leave `~/.claude/mcp.json` untouched\n2. Remove `<!-- ooo:START -->` to `<!-- ooo:END -->` block from CLAUDE.md (if exists)\n3. Confirm: \"Ouroboros plugin configuration removed. To remove plugin files, run: claude plugin uninstall ouroboros\"\n\n## Setup Troubleshooting\n\n- **\"No compatible Python found\"**: plugin mode works without a global Python\n  when uv is on PATH. Otherwise install Python 3.12 (`brew install\n  python@3.12`, `sudo apt install python3.12`, or python.org/downloads).\n- **\"uvx: command not found\"**: uvx is recommended, not required. For the\n  default Claude SDK runtime, `pip install 'ouroboros-ai[claude]'`\n  (`[claude-sdk]` is an explicit alias). Use `[claude-cli]` only for the\n  isolated MCP 2 server worker. Never combine `[claude]`, `[claude-sdk]`, or\n  `[all]` with `[mcp]`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/seed/SKILL.md":"---\nname: seed\ndescription: \"Use when goal, constraints, and success criteria are already settled and the user wants them frozen into a formal spec an agent can execute and verify: 'turn this into a spec', 'write it up as a Seed', or right after an interview. Returns an immutable Seed with acceptance criteria. Not for vague requests (use interview first).\"\naliases: [crystallize]\nmcp_tool: ouroboros_generate_seed\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:seed\n\nGenerate a validated Seed specification from an interview or from requirements this conversation already settled.\n\n## Required Skill Capabilities\n\n`ask_user` (the active runtime's user-question surface), `inspect_code`, `call_mcp`, `orchestrate_subagents` (lateral persona payloads), `run_shell` (audit-trail and prefs writes), `refine_answer` (confirm free-form decisions), `maintain_ledger` (QA scores, candidate decisions, rejected proposals).\n\n## Usage\n\n```\nooo seed [session_id]\n/ouroboros:seed [session_id]\n```\n\n## Instructions\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before running any shell snippet below, and call `ouroboros_python` with every argument quoted. It accepts only Python 3.12 or newer and falls back to uv.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros seed\"` for `ouroboros_generate_seed`; `\"+ouroboros qa\"` for `ouroboros_qa`; `\"+ouroboros lateral\"` for `ouroboros_lateral_think`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\nLoad `ouroboros_generate_seed` before choosing a path: if it is callable, use **Path A**; use **Path B** only when it is genuinely absent (no Ouroboros MCP server).\n\n**Delegated responses are not artifacts.** If any tool below returns `status: \"delegated_to_subagent\"` (with `dispatch_mode: \"plugin\"` and possibly an `_subagents` array), keep the returned session ID, wait for the plugin-managed subagent results, and parse the artifact (Seed YAML, QA verdict, or persona texts) from those results, never from the envelope or its prompts.\n\n### Path A: MCP Mode (Preferred)\n\n1. Pick the entrance:\n   - `session_id` given, or a recent `ouroboros_interview` session ID in the conversation: use the interview session (step 2).\n   - No interview, but THIS conversation already settled the goal, the constraints, and verifiable success criteria (a lateral decision, a brownfield scan, or plain discussion that converged): use the interview-less path below. Do not send the user to `ooo interview` to repeat what they already said.\n   - Otherwise ask the user which interview or requirements to seed.\n\n   **Interview-less path** (`session_context`):\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_context:\n       goal: <the user's own settled wording, verbatim, never your paraphrase>\n       acceptance_criteria: [<verifiable checks: a command, a visible behaviour, a measurable state>]\n       constraints: [<optional>]\n       decisions: [<optional; each becomes a constraint>]\n       project_type: greenfield | brownfield\n   ```\n   Every value enters the Seed byte-for-byte, so shell chains in an AC (`ruff check && pytest`) are allowed. If the response has `status: \"gap_questions_required\"`, ask the user exactly the listed questions, merge the answers into `session_context`, and call again; that is the whole interview.\n\n2. Interview session:\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_id: <interview session ID>\n   ```\n   The tool extracts requirements from persisted interview state, scores ambiguity (must be <= 0.2), and returns Seed YAML.\n\n3. If no Seed YAML results, stop and ask the user to resume generation or supply the artifact. Never fabricate a Seed.\n\n4. Run the Advisory QA Check below, then go to \"After Seed Generation\".\n\n### Path B: No MCP Server\n\n1. Read the `seed-architect` prompt and adopt that role: `$OUROBOROS_AGENTS_DIR/seed-architect.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n   ```bash\n   uvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" seed-architect.md\n   ```\n\n   else `src/ouroboros/agents/seed-architect.md` in a source checkout. Resolve every agent prompt this skill names the same way, substituting its file name.\n2. Recover the requirements before drafting; never invent missing context:\n   - With a `session_id`, use current-thread Q&A and corrections only when they belong to that session; if incomplete, use `inspect_code` / `run_shell` to find persisted or exported artifacts for that ID (for example under `~/.ouroboros/data/`). Keep a persisted transcript as evidence, but let explicit same-thread corrections supersede it.\n   - Without a `session_id`, use current-thread Q&A only when it forms one coherent interview.\n   - Otherwise ask for the transcript or a requirement summary, or suggest `ooo interview`. Never seed from an absent or mismatched transcript.\n3. Generate the Seed YAML, run the Advisory QA Check, then go to \"After Seed Generation\".\n\n### Advisory QA Check (single pass, non-blocking)\n\nRun QA **exactly once** on the generated Seed. The verdict is advisory and never blocks: the Seed is presented as final regardless of score, and there is no QA-until-PASS loop.\n\nGeneration (Path A tool or Path B role) runs **exactly once** and fixes the Seed's ontology. Any later revision is a direct YAML edit by you; never call `ouroboros_generate_seed` again (it takes no revision hints and would discard the ontology).\n\n**MCP QA mode:**\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the seed YAML>\n     quality_bar: \"Seed must be internally consistent, acceptance_criteria must be measurable and testable, constraints must be concrete (no vague terms), ontology_schema must cover all entities referenced in goal/criteria, and there must be no contradictions between fields. acceptance_criteria must also be parsimonious in the ontological sense: a criterion names a state of the finished work a user can see is true, while an implementation step names a means of reaching it, and only the first belongs in the list. Read each criterion beside its siblings — one intelligible only as a move toward a sibling is that sibling's means and belongs merged into the outcome it serves, and flagging that is as important as flagging a missing piece, since it commits the seed to an unverified path. How many criteria a goal has follows from that judgment, so weigh each criterion against its siblings.\"\n     artifact_type: \"document\"\n     pass_threshold: 0.90\n     seed_content: <the seed YAML>\n     qa_session_id: <reuse across passes>\n     iteration_history: <accumulated across passes>\n   ```\nThe 0.90 bar (stricter than the default 0.80) labels the verdict; it gates nothing.\n\n**Fallback QA mode** (QA tool absent): read the `qa-judge` prompt (resolved as in Path B step 1), adopt that role, and evaluate the Seed with the same quality bar and threshold. It returns JSON with lowercase `verdict` (`pass`/`revise`/`fail`), `score`, `dimensions`, `differences`, `suggestions`, `reasoning`; uppercase the verdict only for display and add no non-schema fields. There is no `qa_session_id`; keep pass history in the audit block.\n\nPresent, always in this order:\n1. `QA advisory: <PASS|REVISE|FAIL>, score X.XX (bar 0.90).`\n2. Below the bar: the top 2-3 suggestions as short advisory bullets (findings, not tasks). Apply none automatically.\n3. The complete Seed YAML in a fenced `yaml` block.\n4. For REVISE or FAIL, one opt-in line such as `Want a refinement pass on these findings? Otherwise the seed stands as-is.` For FAIL (< 0.40) also mention `ooo interview` (revisit requirements) or `ooo unstuck` (challenge assumptions). Then continue to \"After Seed Generation\"; the Seed is final unless the user opts in.\n\nOnly on an explicit opt-in, run one refinement pass (below), re-run QA once for an updated advisory line, and present the revised YAML. Each further pass needs a fresh explicit opt-in; never chain passes. Before each later QA call, append the previous verdict and the applied/rejected decisions to `iteration_history`.\n\n#### Refinement pass: Wonder → Reflect → Refine → Restate (opt-in)\n\nDiverge across independent sources, debate, let the user decide, then apply. No candidate is accepted by default, and you never apply a revision on your own (User Adoption Gate).\n\n**Wonder: collect proposals.**\n- **QA**: the verdict's `suggestions` (structural gaps in the YAML; QA cannot see the interview).\n- **Socratic lens** (`socratic-interviewer` prompt, resolved as in Path B step 1): check the Seed against interview evidence (persisted session state first, then this conversation) for 2-4 items: dropped or softened user constraints, rejected scope that crept back, flattened nuance, unagreed assumptions. Without evidence, record `no Socratic proposal: dialectic context unavailable`; never invent preferences. A QA/Socratic conflict goes to Reflect; neither side wins automatically.\n- **Lateral personas** (only if `ouroboros_lateral_think` is callable):\n  ```\n  Tool: ouroboros_lateral_think\n  Arguments:\n    problem_context: |\n      User opted into a refinement pass (QA advisory score X.XX, bar 0.90).\n      Current seed YAML:\n      <YAML>\n      QA suggestions:\n      - <suggestion 1>\n      Original user goal from interview: <recall>\n    current_approach: \"The seed as currently drafted (above).\"\n    persona: \"all\"\n    failed_attempts:\n      - <candidates rejected in earlier passes>\n  ```\n  Extract at most 1-2 concrete, discrete revisions from each persona's prose and drop abstract advice. If the response carries the `<!-- ouroboros-lateral-inline-dispatch-v1 base64 ... -->` sentinel and the runtime can dispatch isolated subagents, decode it and send each `payload.prompt` + `payload.context` through `orchestrate_subagents`; otherwise read the visible persona sections (split on section headers, not bare `---`). If the tool is absent, record `no lateral proposals: MCP lateral tool unavailable` and do not emulate personas.\n\n**Reflect: structure the debate.** Tag each candidate with its backing sources and a type (`expand`, `sharpen`, `remove`, `resolve_conflict`): convergent (two or more sources agree, strong), divergent (sources conflict; the user resolves it), singleton (weaker). Show a balance line such as `Balance: 4 expand / 2 sharpen / 1 remove` as information, not a warning.\n\n**Refine: user gate.** Ask single-choice `ask_user` questions only, conflicts first: one per conflict group (one option per resolution plus \"Leave unchanged\"), then strong revisions (\"apply all, review one by one, or skip\"), then singletons (\"review one by one or skip all\"). Every batch offers \"keep current seed\"; confirm free-form answers with `refine_answer`. Pass rejected candidates as `failed_attempts` on later lateral calls.\n\n**Restate: apply accepted items only.** Edit the existing YAML in place, keep fields that were already correct, and do not regenerate. If everything was skipped, the Seed stands unchanged.\n\n**Audit trail.** After each pass, append to `~/.ouroboros/seed-revisions/<revision_key>.md` (create the directory if needed): pass number, QA score, every candidate with its source tag and accepted/rejected decision, and the diff against the previous YAML. `revision_key` is the `session_id`, or, without one, `<slugified-goal>-YYYYMMDDTHHMMSSZ` derived once and reused for every pass. If the write fails, include the audit block in the response.\n\n## After Seed Generation\n\nAnnounce `Your seed has been crystallized!`\n\nThen read `~/.ouroboros/prefs.json`. If `star_asked` is not `true`, ask one single-choice question with `ask_user`: \"If Ouroboros helped clarify your thinking, a GitHub star supports continued development.\" with options:\n\n- **⭐ Star**: run `gh api -X PUT /user/starred/Q00/ouroboros`, then record `star_asked`.\n- **Not now**: record `star_asked`.\n\nOffer setup only when this Seed came from Path B (no Ouroboros MCP server): say that `ooo setup` enables `ooo run` and evaluation, and point the footer at it. After Path A, MCP already works: never suggest `ooo setup`; the footer points to `ooo run`.\n\nRecord `star_asked` with this snippet, which preserves existing keys such as `welcomeShown`, `welcomeCompleted`, and `welcomeVersion`:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nIf `star_asked` is already `true`, skip the question.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/run/SKILL.md":"---\nname: ouroboros-run\ndescription: \"Use when an Ouroboros Seed (a spec file with a goal and acceptance criteria, such as *.seed.yaml) already exists and the user wants it executed: 'run the seed', 'execute this spec', 'ooo run'. Executes it and verifies every acceptance criterion. Not for raw requests without a Seed (use interview or auto).\"\naliases: [execute]\nmcp_tool: ouroboros_start_execute_seed\nmcp_args:\n  seed_path: \"$1\"\n  cwd: \"$CWD\"\n---\n\n# /ouroboros:ouroboros-run\n\nExecute a Seed specification through the Ouroboros workflow engine as a background job. A completed run enqueues formal evaluation by default, and a rejection continues through a bounded Ralph loop.\n\n## Usage\n\n```\n/ouroboros:ouroboros-run [seed_file_or_content]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros execute\"` for `ouroboros_start_execute_seed`, `ouroboros_job_wait`, `ouroboros_job_result`, and `ouroboros_ac_tree_hud`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the **Fallback (No MCP Server)** section only when the tools are genuinely absent.\n\n### Execution Steps\n\n1. **Do not create or switch branches yourself.** For a background execution\n   job, `use_worktree` defaults to true: the server runs the task in its own\n   worktree and reports `worktree_path` / `worktree_branch` in the job result.\n   Tell the user the task was isolated only when those fields are present. A\n   `dispatch_mode=\"plugin\"` response delegates to a child session and carries\n   no worktree.\n\n2. **Get the Seed.** Read a given file path with the active runtime's `inspect_code` capability, use inline YAML directly, or otherwise take the most recently generated Seed in the conversation.\n\n   Before a fresh start, do not ask about an efficiency policy unless the user\n   raised it or `execution.default_policy` in `~/.ouroboros/config.yaml` is\n   explicitly `ask`. Otherwise omit both arguments: the server applies the\n   configured default (quality-first when nothing is configured), and its start\n   receipt names the running policy and the change command. If the user did\n   choose, or the config says `ask`, map the choice in outcome language:\n\n   - **Efficient execution**: start parallel/decomposed work economically and\n     strengthen the route only when recovery requires it. Send\n     `efficiency_mode=\"adaptive\"` and `frugality_assurance=\"observe\"`.\n   - **Quality-first execution**: keep child work at the parent starting tier.\n     Send `efficiency_mode=\"quality_first\"` and `frugality_assurance=\"off\"`.\n\n   `frugality_assurance=\"strict\"` is a separate explicit opt-in because it may\n   spend extra work on proof; never infer it from the efficiency choice. Do not\n   ask again on resume: the server restores the persisted policy and rejects a\n   resume-time change.\n\n3. **Start background execution:**\n   ```\n   Tool: ouroboros_start_execute_seed\n   Arguments:\n     seed_content: <the seed YAML>\n     efficiency_mode: <only when chosen: adaptive or quality_first>\n     frugality_assurance: <only when chosen: observe, off, or explicit strict>\n     session_id: <only when resuming an existing session>\n   ```\n   Omit `model_tier` by default so the runtime selects automatically. Include\n   `model_tier: <user choice>` only when the user explicitly requested a tier.\n   The call returns at once with `job_id`, `session_id`, and `execution_id`.\n\n4. **Hand off.** Relay the server's start receipt (IDs, backends, `Efficiency Mode` with any change command, dashboard). Then add:\n   - Live view: if `execution.tui_autolaunch: true` (or legacy top-level `tui_autolaunch: true`) is set, run `ouroboros tui open`; otherwise offer it once without blocking. If it prints a manual command (headless, SSH), relay that once.\n   - Observation: a confirmed read-only observer (step 5), or durable catch-up mode.\n   - This conversation stays available: the user can refine requirements, review code, or work on an unrelated task in an isolated worktree; check for active-worker conflicts before editing this run's workspace.\n\n5. **Delegate observation to exactly one observer.** The start result carries\n   `response.meta.job_observer`, a read-only observer contract with its own wait\n   and result tools, `instructions`, `restrictions`, and fallback. If the\n   structured meta is missing, recover the contract from the final\n   `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel and fail\n   closed: if there is more than one sentinel or it is not at the end of the\n   text, the bounded payload does not decode to an object whose only key is\n   `job_observer`, that contract fails canonical v1 validation (it must equal,\n   field for field, the v1 contract the server builds from its own `job_id`,\n   `cursor`, `session_id`, `execution_id`, and `follow_result_job_keys`, so a\n   changed tool, argument, or instruction, or an extra field, fails), its\n   `job_id` differs from the visible start receipt, or the structured and inline\n   contracts differ, do not spawn an observer and report a transport-integrity\n   failure. Never rebuild the contract from visible IDs.\n\n   With a valid contract and an independent child-session primitive, spawn\n   exactly one observer through the active runtime's `orchestrate_subagents`\n   capability and pass the contract unchanged. It owns the job cursor, follows\n   the contract (including `follow_result_job_keys` for chained evaluation and\n   Ralph), and stays read-only. Claim an observer only after the spawn returns\n   a live child ID/path. The main session must not poll the same job while the\n   observer owns it. If plugin mode already delegated the whole execution (no\n   `job_id`), follow that child's lifecycle instead.\n\n   - A `wait` call or a parent job-status poll is not a spawn. The contract's\n     `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name\n     the concrete spawn and wait mechanics; pass the contract unchanged in the\n     child message. After the live child ID returns, if the runtime cannot\n     wake a parent turn that already ended when the child posts (a child\n     message only queues for the parent), keep the parent turn open with the\n     host's child-wait primitive in waits of at most 60 seconds. Relay\n     meaningful updates and wait again until the terminal summary. User input may interrupt the wait; handle it and\n     resume unless the user asks to stop live observation or replaces the\n     request. Then end only the relay loop, keep the durable job running, and\n     offer next-turn or explicit-status catch-up. If the observer child fails,\n     is cancelled, or exits early, use that same catch-up instead of waiting\n     indefinitely. The relay loop must not poll Ouroboros job tools or touch the\n     observer's cursor.\n\n   If no child can be created, do not claim an observer or promise live\n   messages. The detached worker survives the stdio MCP turn: say progress is\n   durable and will be caught up on the next turn or an explicit status\n   request. Keep the turn open only when the user explicitly asked for live\n   watching (step 6).\n\n   **Relaying observer events.** Relay each meaningful event in 1-2 lines;\n   suppress unchanged heartbeats, raw tool output, commands, and reasoning.\n   - `run_configuration`: runtime/harness, starting model or tier when known,\n     efficiency mode, frugality assurance.\n   - `execution_plan`: total ACs, dependency/parallel levels, and the first\n     scheduled AC summaries.\n   - `discovery_summary`: bounded targets and purpose.\n   - `level_started` / `level_completed`, `ac_routing` / `harness_changed`\n     (\"currently running with\"), `ac_attempt_judged`: only real changes.\n   - `ac_accepted` / `ac_rejected`: the AC's final acceptance and compact\n     disposition evidence.\n   - `attention_required`: surface immediately (see Active Conductor below).\n   - Synapse `.queued` / `.delivering`: pending, not applied yet. `.applied` /\n     `.completed`: confirm and relay any bounded AC reply. `.rejected` /\n     `.delivery_uncertain`: surface immediately; never claim the AC changed\n     course.\n\n   These are English canonical host instructions: render every relay in the\n   user's current conversation language, keeping event codes and mode values\n   only when exact diagnostics help.\n\n6. **Fallback: live relay in the main session.** Only when there is no\n   observer contract or no child primitive, and the user explicitly asked to\n   keep watching this turn. Never run it beside a delegated observer;\n   otherwise end the turn and catch up from the same cursor next turn.\n   ```\n   Tool: ouroboros_job_wait\n   Arguments:\n     job_id: <job_id>\n     cursor: <latest cursor, or 0>\n     timeout_seconds: 180\n     view: \"summary\"\n     stream: \"linked\"\n     wait_for: \"attention_or_ac_change\"\n   ```\n   Replace the cursor from `response.meta.cursor` after every call. Treat\n   `response.meta` as the source of truth and `response.text` only as a hint.\n   If `response.meta.changed` is false, repeat silently; otherwise emit one\n   compact line (phase, AC/sub-AC counts, new current-work hint), never raw\n   JSON, the full tree, or an ETA. On `completed`, `failed`, `cancelled`, or\n   `interrupted`, say so explicitly and go to step 8.\n\n7. **Drill-down only.** Use `ouroboros_ac_tree_hud` when the user asks for\n   details or progress looks stuck, never in the routine loop. `view` is\n   `\"compact\"`, `\"summary\"`, or `\"tree\"` (add `max_nodes: 30`); treat\n   `unchanged cursor=<cursor>` as a silent no-op.\n   ```\n   Tool: ouroboros_ac_tree_hud\n   Arguments:\n     session_id: <session_id>\n     cursor: <cursor>\n     view: \"summary\"\n   ```\n\n8. **Fetch the final result in the polling owner** (the observer by default,\n   the main session only on the step 6 fallback):\n   ```\n   Tool: ouroboros_job_result\n   Arguments:\n     job_id: <job_id>\n   ```\n   Present status, session ID, and summary. Its QA verdict (skippable with\n   `skip_qa: true` at start) is not the formal 3-stage evaluator.\n\n   If the result meta has `chained_evaluate_job_id`, the polling owner follows\n   that job and fetches its result: render **APPROVED** when\n   `final_approved: true`, otherwise not approved with the failed ACs or\n   reason. If the evaluate job failed or timed out, keep the run success and\n   show `Next: ooo evaluate <session_id>` as the manual retry. If the\n   evaluation has `chained_ralph_job_id`, follow it too and report approval or\n   the bounded Ralph stop reason; a rejected first evaluation does not make\n   the run blocked.\n\n   Without `chained_evaluate_job_id`, show:\n   - **PASS**: `Next: ooo evaluate <session_id> for formal 3-stage verification`\n   - **REVISE**: the differences/suggestions, then `Next: Fix the issues above, then ooo run to retry -- or ooo unstuck if blocked`\n   - **FAIL/ESCALATE**: `Next: Review failures above, then ooo run to retry -- or ooo unstuck if blocked`\n\n### Synapse intent refinement\n\nSynapse is the `ouroboros_session_signal` channel that delivers bounded user intent to one running AC. When the user adds implementation intent during an active run, the main session picks the target; never ask the user for internal AC or session IDs.\n\n1. Call `ouroboros_session_signal_targets(execution_id=...)` with the `execution_id` from the start result or observer contract.\n2. Match the user's meaning against each target's `ac_content`, display path, and current HUD activity. Select one active target directly; with several, select only a materially more relevant one, and ask a short clarification only for a genuine tie.\n3. Additive implementation refinement: call `ouroboros_session_signal` with the target's exact scope/attempt/execution guards, `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, `fallback_mode=\"after_turn\"`, `expected_contract_version` when discovery supplies it, and one stable idempotency key for this user turn. If the target went stale, rediscover once instead of asking for IDs.\n4. Read-only question or assurance request: use `mode=\"inform\"` and `contract_effect=\"additive\"`, and omit `fallback_mode` (valid only for redirect). Relay the bounded reply from the completed event.\n5. Tell the user which AC was selected and the effective mode; say it was reflected only after `.applied` or `.completed`.\n\nNever use Synapse to change approved goals, ACs, constraints, or non-goals; those need an approved shared successor or replacement contract.\n\n### Active Conductor attention handling\n\n`recommended_host_actions` is the authoritative menu; never invent a mutating tool call.\n\n1. VERIFY with at most one short-lived read-only host child using the supplied evidence IDs. Without a verifier primitive, surface the attention and stop before mutation.\n2. DECIDE among the ordered menu actions only after engine-owned retry/routing is closed.\n3. LOG `phase=\"selected\"` through `ouroboros_record_conductor_decision` before ACT. A specification change in run mode needs explicit user approval with its receipt bound.\n4. ACT only when the menu names a currently registered MCP tool. A corrective successor preserves the approved contract unless the user approved the shared specification change.\n5. LOG exactly one terminal `completed`, `failed`, or `declined` outcome. Never silently retry a failed conductor action.\n\n## Fallback (No MCP Server)\n\nTell the user:\n\n```\nOuroboros MCP server is not configured.\nTo enable full execution mode, run: /ouroboros:setup\n\nWithout MCP, you can still:\n- Use /ouroboros:interview for requirement clarification\n- Use /ouroboros:seed to generate specifications\n- Manually implement the seed specification\n```\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/publish/SKILL.md":"---\nname: publish\ndescription: \"Publish Seed specification as GitHub Issues for team-based project management\"\n---\n\n# /ouroboros:publish\n\nConvert a Seed into a GitHub Epic issue plus Task issues. Works entirely through the `gh` CLI (no MCP), creates new issues only, and never modifies existing ones.\n\n```\nooo publish [seed_path]\n/ouroboros:publish [seed_path]\n```\n\n## Instructions\n\nRun commands with the active runtime's `run_shell` capability and ask every question with the active runtime's `ask_user` capability.\n\n### Step 1: Prerequisites\n\nRun `command -v gh`. If missing, tell the user to install it from https://cli.github.com/ and stop. Run `gh auth status`; if not authenticated, tell the user to run `gh auth login` and stop.\n\n### Step 2: Locate the Seed\n\nSeeds live in `~/.ouroboros/seeds/`: interview Seeds as `{seed_id}.yaml`, PM Seeds as `pm_seed_{id}.json`. In priority order:\n\n1. An explicit `.yaml` or `.json` path argument.\n2. The most recent files from `ls -t ~/.ouroboros/seeds/*.yaml ~/.ouroboros/seeds/*.json 2>/dev/null | head -5`; if several exist, ask the user to choose.\n3. A Seed path reported by `ooo seed` or `ooo pm` earlier in this conversation.\n\nIf none is found, tell the user to run `ooo seed` or `ooo pm` first, and stop.\n\n### Step 3: Parse the Seed\n\nDetect the format by extension. Omit any section whose field is missing or empty rather than failing.\n\nYAML Seed (`ooo interview` + `ooo seed`):\n\n| Field | Use |\n|-------|-----|\n| `goal` | Epic title and Goal section |\n| `constraints` | Constraints section |\n| `acceptance_criteria` | Epic checklist, distributed to Task issues |\n| `ontology_schema` | Ontology table (field, type, description) |\n| `evaluation_principles` | Evaluation Principles table (name, weight, description) |\n| `exit_conditions` | Exit Conditions (Definition of Done) |\n| `metadata.ambiguity_score` | Confidence indicator |\n| `metadata.seed_id` | Duplicate detection |\n\nJSON PM Seed (`ooo pm`, `PMSeed` schema):\n\n| Field | Use |\n|-------|-----|\n| `pm_id` | Duplicate detection |\n| `product_name` | Epic title prefix |\n| `goal` | Goal section |\n| `constraints` | Constraints section |\n| `success_criteria` | Acceptance Criteria checklist |\n| `user_stories` | User Stories, each as \"As a **{persona}**, I want to **{action}**, so that **{benefit}**.\" |\n| `deferred_items` | Deferred Items section |\n| `decide_later_items` | Open Questions section |\n| `assumptions` | Assumptions section |\n\n### Step 4: Target repository\n\nRun `gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null`. If it returns a repo, ask whether to publish there or to another `owner/repo`; otherwise ask for `owner/repo`. Store the answer as `TARGET_REPO`. **Every later `gh` command MUST include `-R <TARGET_REPO>`.**\n\n### Step 5: Duplicate check\n\n```bash\ngh issue list -R <TARGET_REPO> --label \"ouroboros\" --state all --search \"<seed_id or pm_id>\" --limit 5 --json number,title,state\n```\n\nThis finds earlier publishes because the Epic body records the Seed ID (Step 7). If matches exist, list them and ask whether to create anyway or cancel; on cancel, stop.\n\n### Step 6: Plan the issues\n\nGroup the acceptance criteria into logical implementation units (by feature area, layer, or dependency order); each unit becomes one Task. Show the plan (Epic goal summary, then each Task title and brief scope) and ask whether to create the issues or modify the plan. On modify, ask what to change, adjust, and show it again.\n\n### Step 7: Create the issues\n\n`gh issue create` prints the issue URL; take the number from its trailing digits (`grep -o '[0-9]*$'`). Pass bodies through a quoted heredoc (`--body \"$(cat <<'BODY' ... BODY)\"`).\n\n1. Create labels, ignoring \"already exists\":\n   ```bash\n   gh label create \"ouroboros\" -R <TARGET_REPO> --description \"Created by Ouroboros publish\" --color \"6f42c1\" 2>/dev/null || true\n   gh label create \"epic\" -R <TARGET_REPO> --description \"Epic / parent issue\" --color \"0075ca\" 2>/dev/null || true\n   gh label create \"task\" -R <TARGET_REPO> --description \"Implementation task\" --color \"008672\" 2>/dev/null || true\n   ```\n2. Epic: title `[Epic] <goal summary>`, labels `ouroboros,epic`. Body: the Step 3 sections in order (Goal, Constraints, Acceptance Criteria as `- [ ]` items, Ontology, Evaluation Principles, Exit Conditions, plus the PM-only sections), then this footer:\n   ```\n   ---\n\n   **Seed ID**: `<seed_id or pm_id>` | **Ambiguity Score**: <score> | **Seed**: `<seed_file_path>`\n   *Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n3. Each Task: title `[Task] <task title>`, labels `ouroboros,task`. Body: `Parent: #<epic>`, then Scope, Acceptance Criteria (`- [ ]` items for this unit), Test Checklist, Pass Criteria (measurable done conditions), then this footer:\n   ```\n   ---\n\n   *Part of [Epic] #<epic> | Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n4. Comment on the Epic (`gh issue comment <epic> -R <TARGET_REPO>`) with an \"Implementation Tasks\" checklist of `- [ ] #<task>: <title>` lines, noting progress is tracked by checking off tasks as their issues close.\n\n### Step 8: Summary\n\nShow `Published to <TARGET_REPO>:` with the Epic and its Tasks as a tree (`#<n> [Epic|Task] <title>`) and the link `https://github.com/<TARGET_REPO>/issues/<epic>`. Suggest next steps: assign tasks, track on a GitHub Projects board, run `ooo run` for AI-assisted implementation of individual tasks.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/qa/SKILL.md":"---\nname: qa\ndescription: \"General-purpose QA verdict for any artifact type\"\n---\n\n# /ouroboros:qa\n\nFast single-pass quality verdict with actionable suggestions for any artifact: code, documents, API responses, test output, or custom content. For formal three-stage verification of an execution, use `ooo evaluate`.\n\n```\nooo qa [file_path | artifact_text]\nooo qa                                     # recent execution output\n/ouroboros:qa [file_path | artifact_text]\n```\n\nThe QA Judge scores the artifact against a quality bar on Correctness, Completeness, Quality, Intent Alignment, and Domain-Specific dimensions:\n\n| Score | Verdict | Loop action |\n|-------|---------|-------------|\n| >= 0.80 | PASS | done |\n| 0.40 - 0.79 | REVISE | continue |\n| < 0.40 | FAIL | escalate |\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros qa\"` for `ouroboros_qa`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent; this skill works without MCP setup.\n\n### QA steps\n\n1. **Artifact**: a file path (read it with the active runtime's `inspect_code` capability), inline text, or else the most recent execution output; ask with `ask_user` if unclear.\n2. **Quality bar**: the Seed's acceptance criteria when a Seed is in context, else the user's stated bar; otherwise ask \"What does 'good' mean for this artifact?\"\n3. **Artifact type**: `code`, `test_output`, `document`, `api_response`, `screenshot`, or `custom`.\n\n3.5. **Acting verification fan-out** (behavior-bearing artifacts): a text judge can be fooled by a hopeful log line. Use the active runtime's `orchestrate_subagents` capability to launch, together, one probe child per acting modality the runtime exposes: a process probe (`run_shell`: run the command or app or smoke commands with bounded timeouts, capture exit codes and real output), a browser probe (HTTP services and web UIs: load them, exercise the primary flows, capture rendering and console/network errors), a computer-use probe (GUI/TUI: drive it like a user, screenshot observed states), and an artifact probe (`inspect_code`: declared files exist with real content, not placeholders). Each probe returns structured evidence only (commands, observed effects, screenshots/paths, pass/fail per behavior) and covers the applicable adversarial classes the QA tool lists. Skip a modality only when its tools are absent or it is meaningless for the artifact, and say which were skipped and why. Await all probes and pass the merged evidence as `reference`; prefer observed behavior over source text as the `artifact` when they disagree.\n\n4. **Call the tool**:\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the content to evaluate>\n     quality_bar: <what 'pass' means>\n     artifact_type: \"code\"  (or other type)\n     reference: <observed-behaviour evidence from step 3.5, plus any reference>\n     pass_threshold: 0.80  (adjustable)\n     seed_content: <seed YAML if available>\n   ```\n\n   **Plugin delegation**: a response with `status: \"delegated_to_subagent\"` and `dispatch_mode: \"plugin\"` carries no verdict. Its content is the bridge's dispatch notice and its `_subagent` prompt is the child's input, never a result. Keep `qa_session_id`, await the plugin-spawned child, and parse its JSON verdict (`score`, `verdict`, `dimensions`, `differences`, `suggestions`, `reasoning`). No `iteration_entry` comes back, so derive the loop action as the tool does (score >= `pass_threshold`: done; >= 0.40: continue; else escalate) and build the entry yourself (`iteration`, `score`, `verdict`, `loop_action`). If the child returns no parseable verdict, say so instead of presenting the envelope.\n\n5. **Present** the score and verdict prominently, then dimension scores, specific differences, and actionable suggestions. **Empirical evidence outranks the judge**: if the judge scores PASS but a probe observed the behavior failing, present REVISE/FAIL on that evidence and say so. If nothing could act, flag that behavior was not observed. Pick the next action from the verdict:\n   - **PASS (done)**: proceed; the artifact meets the quality bar\n   - **REVISE (continue)**: address the suggestions, then run `ooo qa` again\n   - **FAIL (escalate)**: `ooo interview` to re-examine requirements, or `ooo unstuck` to challenge assumptions\n\n### Iterative QA\n\nThe first call returns `qa_session_id` and `iteration_entry` in meta. On later calls pass `qa_session_id` and the accumulated `iteration_history`. Continue until the verdict is `pass` or `fail`.\n\n### Fallback (no Ouroboros MCP server)\n\nAdopt the `qa-judge` role yourself with the same prompt the MCP tool uses: `$OUROBOROS_AGENTS_DIR/qa-judge.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n```bash\nuvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" qa-judge.md\n```\n\nelse `src/ouroboros/agents/qa-judge.md` in a source checkout.\n\nIf none is reachable, judge on the dimensions and thresholds above and label the verdict as an unaligned fallback. Run the step 3.5 probes first for behavior-bearing artifacts, render the verdict in the same shape the MCP tool returns (score, verdict, threshold, dimensions, differences, suggestions, reasoning, loop action), and keep the iterative contract with a `qa-<uuid4_short>` session id and an iteration count held in the conversation.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/ralph/SKILL.md":"---\nname: ralph\ndescription: \"MCP-owned Ralph loop around background evolve_step jobs\"\nmcp_tool: ouroboros_ralph\nmcp_args:\n  lineage_id: \"$lineage_id\"\n---\n\n# /ouroboros:ralph\n\nMCP-owned Ralph loop around background `evolve_step` jobs. \"The boulder never stops.\"\n\n## Usage\n\n```\nooo ralph --lineage-id <lineage_id>\n/ouroboros:ralph --lineage-id <lineage_id>\n```\n\nThe `ouroboros_ralph` tool owns the loop (do not reimplement it): one background job runs repeated `evolve_step` generations until QA pass, convergence, a terminal evolution action, cancellation, or `max_generations`. Router dispatch reads only the named `--lineage-id` option, never trailing text.\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros ralph job\"` for `ouroboros_ralph`, `ouroboros_job_wait`, `ouroboros_job_status`, `ouroboros_job_result`, and `ouroboros_cancel_job`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tools are genuinely absent, stop and tell the user that Ralph requires the Ouroboros MCP runtime.\n\n### 1. Prepare lineage input\n\n- **Continue a lineage**: when the user gives an existing `lineage_id` and wants to continue it, reuse it and omit `seed_content` unless they supply an updated Seed.\n- **New run from Seed YAML**: use it as `seed_content` with a fresh `lineage_id` such as `ralph-<short-slug>-<uuid>`. Never reuse a Seed, interview, or session id as the lineage id, so separate runs over one Seed do not collide.\n- **Plain natural-language request**: never pass raw text as `seed_content` or freehand Seed YAML. Run `ooo interview` and `ooo seed` first (or reuse a validated Seed in context), then start with a fresh `lineage_id`. Without inputs the tool returns input guidance instead of a job.\n\n### 2. Start Ralph\n\nCall `ouroboros_ralph` with `lineage_id`, `seed_content` (generation 1 of a new lineage), `execute` (default `true`), `parallel` (default `true`), `skip_qa` (default `false`), `project_dir` when known, and `max_generations` (default `10`, also the hard max; lower it only on request).\n\n### 3. Handle the start response\n\n- **Job started** (`response.meta.job_id` present): keep `response.meta.cursor` and report:\n\n  ```\n  [Ralph] Started background loop: <job_id>\n  Lineage: <lineage_id>\n  Live view: <dashboard_url, or `ouroboros tui open`>\n\n  A read-only observer will post meaningful progress, attention, and terminal\n  events here. This conversation remains available for other safe work.\n  ```\n\n- **Observer handoff**: if `response.meta.job_observer` is missing, recover it from the final `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel; fail closed unless it passes canonical v1 validation and its job identity matches the visible start receipt, and use it only as an identity anchor, never to reconstruct tools or arguments. When the host supports an independent child session, spawn exactly one read-only observer and pass the contract unchanged. The observer exclusively owns job wait/result calls and the cursor; the main session keeps user conversation, explicit on-demand status, and user-requested cancellation. The main session must not poll the same job while the observer is active. It may refine requirements, do read-only review, or work in an unrelated isolated worktree; check active-worker conflicts before writing to Ralph's workspace.\n  - A `wait` call or a parent job-status poll is not a spawn; claim no observer until a live child ID/path returns. The contract's `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name the concrete spawn and wait mechanics. If the runtime cannot wake a parent turn that already ended when the child posts (a child message only queues for the parent), keep the parent turn open with the host's child-wait primitive in waits of at most 60 seconds while the observer is active. Relay meaningful updates and wait again until terminal.\n  - User input may interrupt the wait; handle it and resume waiting unless the user asks to stop live observation or replaces the request. Then end only the relay loop, keep the durable job running, and offer next-turn or explicit-status catch-up. Use the same fallback, instead of waiting indefinitely, if the observer child fails, is cancelled, or exits before a terminal summary. The relay loop must not poll the Ouroboros job or take cursor ownership.\n  - If spawn fails, promise no live relays: the detached worker continues after the stdio turn, and the main session catches up from durable events on the next interaction or explicit status request.\n- **Plugin delegation** (`response.meta.status == \"delegated_to_plugin\"`, `job_id` is `None`): a child session owns the loop. Never call job tools without a job id; treat the child session result as the terminal surface and summarize its completion/error state and lineage id.\n\n### 4. Monitor (polling owner only)\n\nThe observer is the default owner. Run this loop in the main session only when no independent child session exists and the user explicitly asked for live watching; otherwise catch up on the next turn. Never run both:\n\n- `ouroboros_job_wait(job_id, cursor, timeout_seconds=120, stream=\"linked\", wait_for=\"attention_or_ac_change\")` for long polling;\n  after every wait/status response, update `cursor = response.meta.cursor`\n- `ouroboros_job_status(job_id)` for a quick status check\n- `ouroboros_job_result(job_id)` when the job is terminal\n- `ouroboros_cancel_job(job_id)` if the user says stop/cancel\n\nRelay rules: 1-2 lines per change; surface `attention_required` and rejected or uncertain delivery immediately; distinguish Synapse `queued` from runtime-proven `applied`; never forward heartbeats, raw tool output, commands, or model reasoning. Report run configuration, AC count and parallel levels, first scheduled ACs, and verified AC completion; say \"currently running with\", since later generations may switch model or harness. When `lineage.generation.started` carries `ac_focus`, report what the generation is redoing from `active_ac_descriptions` and how many ACs stay frozen (for example \"Gen 7: reworking 2/5 ACs, 3 frozen on prior PASS evidence\"); if it is absent or every AC is active, say the full AC graph is running. Never quote verify commands or expected outputs.\n\nWhen the user asks a live AC a read-only question or adds intent, call `ouroboros_session_signal_targets` for the observed execution and pick the relevant AC without asking for internal IDs. Use `mode=\"inform\"` for questions and assurance, and omit `fallback_mode` in that mode. For implementation refinement use `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, and explicit `fallback_mode=\"after_turn\"` with the exact discovered guards, sent via `ouroboros_session_signal`. Shared goal, AC, constraint, or non-goal changes require an approved shared successor.\n\n### 5. On termination\n\nThe polling owner fetches the job result, then:\n- **Success / convergence**: summarize the final generation, QA verdict, and any `worktree_path` / `worktree_branch`. A Ralph `lineage_id` is not an execution `session_id`: offer `ooo evaluate <session_id>` only when a real execution session id is available from a separate run.\n- **Max generations / failure**: summarize the stop reason and suggest `ooo unstuck`, `ooo interview`, or a narrower Ralph retry.\n- **Cancelled**: confirm and keep the job id for later inspection.\n\n### Active Conductor decision policy\n\nFor `attention_required`, use at most one short-lived read-only verifier. If the host has no verifier primitive, surface the evidence and do not mutate. Otherwise VERIFY → DECIDE from `recommended_host_actions` → LOG `selected` with `ouroboros_record_conductor_decision` → ACT only a menu-listed registered tool → LOG exactly one `completed`, `failed`, or `declined` outcome. Ralph may apply a conductor directive only to the first and sole bounded successor generation (`max_generations=1`), and only when it is deterministic and non-relaxing. Never silently retry or weaken the approved shared contract.\n\nThese are English canonical host instructions. Render them, and every relay, naturally in the user's conversation language.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/resume-session/SKILL.md":"---\nname: resume-session\ndescription: \"List in-flight Ouroboros sessions and show the commands needed to re-attach after MCP disconnect\"\n---\n\n# /ouroboros:resume-session\n\nRecover in-flight Ouroboros sessions after an unexpected MCP server disconnect. The name avoids shadowing Claude Code's built-in `/resume`.\n\n```\nooo resume-session [--all]\n/ouroboros:resume-session\n```\n\n## Instructions\n\n1. Run with the active runtime's `run_shell` capability:\n\n   ```\n   ouroboros resume --list\n   ```\n\n   It reads the configured EventStore directly and read-only (no MCP server needed, nothing created or written) and lists `running` or `paused` sessions: the 20 most recent, or all with `--all`. `--list` prints the table and exits without the interactive prompt, which aborts when no terminal is attached. Exit code 2 means the EventStore exists but could not be read.\n\n2. If sessions are listed, show the table and ask which session to work with (active runtime's `ask_user` capability). Each row carries the `session_id`, `exec_id`, and Seed id used below.\n\n3. Give the matching re-attach path:\n\n   - Inspect persisted events (read-only, no MCP server):\n     ```\n     ouroboros status execution <exec_id> --events\n     ```\n   - Inspect interactively (read-only monitor; pick the session in the TUI):\n     ```\n     ouroboros tui monitor\n     ```\n   - Resume execution (needs the original Seed file; `--resume` takes the `session_id`):\n     ```\n     ouroboros run workflow --orchestrator --resume <session_id> <seed.yaml>\n     ```\n\n   Afterwards: `ooo evaluate` once the execution completes, or `ooo cancel <session_id>` if it is stuck.\n\nIf it reports \"No in-flight sessions found\", the execution completed, failed, or was cancelled, or the EventStore was never created; `ouroboros tui monitor` browses past sessions.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","skills/pm/SKILL.md":"# pm\n\nPath: `skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/pm/SKILL.md)","skills/ooo/SKILL.md":"# ooo\n\nPath: `skills/ooo/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/ooo/SKILL.md)","skills/interview/SKILL.md":"# interview\n\nPath: `skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/interview/SKILL.md)","skills/help/SKILL.md":"# help\n\nPath: `skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/help/SKILL.md)","skills/evolve/SKILL.md":"# evolve\n\nPath: `skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evolve/SKILL.md)","skills/evaluate/SKILL.md":"# evaluate\n\nPath: `skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evaluate/SKILL.md)","skills/config/SKILL.md":"# config\n\nPath: `skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/config/SKILL.md)","skills/cancel/SKILL.md":"# cancel\n\nPath: `skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/cancel/SKILL.md)","skills/brownfield/SKILL.md":"# brownfield\n\nPath: `skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/brownfield/SKILL.md)","skills/auto/SKILL.md":"# auto\n\nPath: `skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/auto/SKILL.md)",".claude-plugin/skills/welcome/SKILL.md":"# welcome\n\nPath: `.claude-plugin/skills/welcome/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/welcome/SKILL.md)",".claude-plugin/skills/update/SKILL.md":"# update\n\nPath: `.claude-plugin/skills/update/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/update/SKILL.md)",".claude-plugin/skills/unstuck/SKILL.md":"# unstuck\n\nPath: `.claude-plugin/skills/unstuck/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/unstuck/SKILL.md)",".claude-plugin/skills/tutorial/SKILL.md":"# tutorial\n\nPath: `.claude-plugin/skills/tutorial/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/tutorial/SKILL.md)",".claude-plugin/skills/status/SKILL.md":"# status\n\nPath: `.claude-plugin/skills/status/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/status/SKILL.md)",".claude-plugin/skills/setup/SKILL.md":"# setup\n\nPath: `.claude-plugin/skills/setup/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/setup/SKILL.md)",".claude-plugin/skills/seed/SKILL.md":"# seed\n\nPath: `.claude-plugin/skills/seed/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/seed/SKILL.md)",".claude-plugin/skills/run/SKILL.md":"# run\n\nPath: `.claude-plugin/skills/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/run/SKILL.md)",".claude-plugin/skills/resume-session/SKILL.md":"# resume-session\n\nPath: `.claude-plugin/skills/resume-session/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/resume-session/SKILL.md)",".claude-plugin/skills/ralph/SKILL.md":"# ralph\n\nPath: `.claude-plugin/skills/ralph/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/ralph/SKILL.md)",".claude-plugin/skills/qa/SKILL.md":"# qa\n\nPath: `.claude-plugin/skills/qa/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/qa/SKILL.md)",".claude-plugin/skills/publish/SKILL.md":"# publish\n\nPath: `.claude-plugin/skills/publish/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/publish/SKILL.md)",".claude-plugin/skills/pm/SKILL.md":"# pm\n\nPath: `.claude-plugin/skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/pm/SKILL.md)",".claude-plugin/skills/interview/SKILL.md":"# interview\n\nPath: `.claude-plugin/skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/interview/SKILL.md)",".claude-plugin/skills/help/SKILL.md":"# help\n\nPath: `.claude-plugin/skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/help/SKILL.md)",".claude-plugin/skills/evolve/SKILL.md":"# evolve\n\nPath: `.claude-plugin/skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evolve/SKILL.md)",".claude-plugin/skills/evaluate/SKILL.md":"# evaluate\n\nPath: `.claude-plugin/skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evaluate/SKILL.md)",".claude-plugin/skills/config/SKILL.md":"# config\n\nPath: `.claude-plugin/skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/config/SKILL.md)",".claude-plugin/skills/cancel/SKILL.md":"# cancel\n\nPath: `.claude-plugin/skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/cancel/SKILL.md)",".claude-plugin/skills/brownfield/SKILL.md":"# brownfield\n\nPath: `.claude-plugin/skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/brownfield/SKILL.md)",".claude-plugin/skills/auto/SKILL.md":"# auto\n\nPath: `.claude-plugin/skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/auto/SKILL.md)","tests/fixtures/router/skills/frontmatter-body/run/SKILL.md":"# run\n\nPath: `tests/fixtures/router/skills/frontmatter-body/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/router/skills/frontmatter-body/run/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/AGENTS.md)","CLAUDE.md":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/CLAUDE.md)","llms.txt":"# LLM Index & Context Digest\n\nPath: `llms.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms.txt)","llms-full.txt":"# LLM Full Documentation Context\n\nPath: `llms-full.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms-full.txt)",".codex-plugin/plugin.json":"# codex-plugin Plugin Manifest\n\nPath: `.codex-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex-plugin/plugin.json)",".codex/config.toml":"# Codex Directive: config.toml\n\nPath: `.codex/config.toml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/config.toml)",".codex/hooks.json":"# Codex Directive: hooks.json\n\nPath: `.codex/hooks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/hooks.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/plugin.json)","docs/architecture.md":"# docs - System Architecture & Module Boundaries\n\nPath: `docs/architecture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/docs/architecture.md)",".agents/plugins/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.agents/plugins/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.agents/plugins/marketplace.json)","src/ouroboros/agents/advocate.md":"# Subagent: advocate\n\nPath: `src/ouroboros/agents/advocate.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/advocate.md)","src/ouroboros/agents/analysis-agent.md":"# Subagent: analysis-agent\n\nPath: `src/ouroboros/agents/analysis-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/analysis-agent.md)","src/ouroboros/agents/architect.md":"# Subagent: architect\n\nPath: `src/ouroboros/agents/architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/architect.md)","src/ouroboros/agents/breadth-keeper.md":"# Subagent: breadth-keeper\n\nPath: `src/ouroboros/agents/breadth-keeper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/breadth-keeper.md)","src/ouroboros/agents/code-executor.md":"# Subagent: code-executor\n\nPath: `src/ouroboros/agents/code-executor.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/code-executor.md)","src/ouroboros/agents/codebase-explorer.md":"# Subagent: codebase-explorer\n\nPath: `src/ouroboros/agents/codebase-explorer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/codebase-explorer.md)","src/ouroboros/agents/consensus-reviewer.md":"# Subagent: consensus-reviewer\n\nPath: `src/ouroboros/agents/consensus-reviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/consensus-reviewer.md)","src/ouroboros/agents/contrarian.md":"# Subagent: contrarian\n\nPath: `src/ouroboros/agents/contrarian.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/contrarian.md)","src/ouroboros/agents/evaluator.md":"# Subagent: evaluator\n\nPath: `src/ouroboros/agents/evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/evaluator.md)","src/ouroboros/agents/hacker.md":"# Subagent: hacker\n\nPath: `src/ouroboros/agents/hacker.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/hacker.md)","src/ouroboros/agents/judge.md":"# Subagent: judge\n\nPath: `src/ouroboros/agents/judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/judge.md)","src/ouroboros/agents/ontologist.md":"# Subagent: ontologist\n\nPath: `src/ouroboros/agents/ontologist.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontologist.md)","src/ouroboros/agents/ontology-analyst.md":"# Subagent: ontology-analyst\n\nPath: `src/ouroboros/agents/ontology-analyst.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontology-analyst.md)","src/ouroboros/agents/qa-judge.md":"# Subagent: qa-judge\n\nPath: `src/ouroboros/agents/qa-judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/qa-judge.md)","src/ouroboros/agents/research-agent.md":"# Subagent: research-agent\n\nPath: `src/ouroboros/agents/research-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/research-agent.md)","src/ouroboros/agents/researcher.md":"# Subagent: researcher\n\nPath: `src/ouroboros/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/researcher.md)","src/ouroboros/agents/seed-architect.md":"# Subagent: seed-architect\n\nPath: `src/ouroboros/agents/seed-architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-architect.md)","src/ouroboros/agents/seed-closer.md":"# Subagent: seed-closer\n\nPath: `src/ouroboros/agents/seed-closer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-closer.md)","src/ouroboros/agents/semantic-evaluator.md":"# Subagent: semantic-evaluator\n\nPath: `src/ouroboros/agents/semantic-evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/semantic-evaluator.md)","src/ouroboros/agents/simplifier.md":"# Subagent: simplifier\n\nPath: `src/ouroboros/agents/simplifier.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/simplifier.md)","src/ouroboros/agents/socratic-interviewer.md":"# Subagent: socratic-interviewer\n\nPath: `src/ouroboros/agents/socratic-interviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/socratic-interviewer.md)","tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json":"# github-pr-ops Plugin Manifest\n\nPath: `tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/AGENTS.md)","tokens":300,"sizeBytes":147},{"name":"llms-full.txt","path":"llms-full.txt","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms-full.txt","title":"LLM Full Documentation Context","category":"root-instruction","format":"text","content":"# LLM Full Documentation Context\n\nPath: `llms-full.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms-full.txt)","tokens":300,"sizeBytes":153},{"name":"llms.txt","path":"llms.txt","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms.txt","title":"LLM Index & Context Digest","category":"root-instruction","format":"text","content":"# LLM Index & Context Digest\n\nPath: `llms.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms.txt)","tokens":300,"sizeBytes":139},{"name":"architecture.md","path":"docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/docs/architecture.md","title":"docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"# docs - System Architecture & Module Boundaries\n\nPath: `docs/architecture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/docs/architecture.md)","tokens":300,"sizeBytes":183},{"name":"SKILL.md","path":".claude-plugin/skills/auto/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/auto/SKILL.md","title":"auto","category":"anthropic-skill","format":"markdown","content":"# auto\n\nPath: `.claude-plugin/skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/auto/SKILL.md)","tokens":300,"sizeBytes":171},{"name":"SKILL.md","path":".claude-plugin/skills/brownfield/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/brownfield/SKILL.md","title":"brownfield","category":"anthropic-skill","format":"markdown","content":"# brownfield\n\nPath: `.claude-plugin/skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/brownfield/SKILL.md)","tokens":300,"sizeBytes":189},{"name":"SKILL.md","path":".claude-plugin/skills/cancel/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/cancel/SKILL.md","title":"cancel","category":"anthropic-skill","format":"markdown","content":"# cancel\n\nPath: `.claude-plugin/skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/cancel/SKILL.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude-plugin/skills/config/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/config/SKILL.md","title":"config","category":"anthropic-skill","format":"markdown","content":"# config\n\nPath: `.claude-plugin/skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/config/SKILL.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude-plugin/skills/evaluate/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evaluate/SKILL.md","title":"evaluate","category":"anthropic-skill","format":"markdown","content":"# evaluate\n\nPath: `.claude-plugin/skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evaluate/SKILL.md)","tokens":300,"sizeBytes":183},{"name":"SKILL.md","path":".claude-plugin/skills/evolve/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evolve/SKILL.md","title":"evolve","category":"anthropic-skill","format":"markdown","content":"# evolve\n\nPath: `.claude-plugin/skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evolve/SKILL.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude-plugin/skills/help/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/help/SKILL.md","title":"help","category":"anthropic-skill","format":"markdown","content":"# help\n\nPath: `.claude-plugin/skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/help/SKILL.md)","tokens":300,"sizeBytes":171},{"name":"SKILL.md","path":".claude-plugin/skills/interview/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/interview/SKILL.md","title":"interview","category":"anthropic-skill","format":"markdown","content":"# interview\n\nPath: `.claude-plugin/skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/interview/SKILL.md)","tokens":300,"sizeBytes":186},{"name":"SKILL.md","path":".claude-plugin/skills/pm/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/pm/SKILL.md","title":"pm","category":"anthropic-skill","format":"markdown","content":"# pm\n\nPath: `.claude-plugin/skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/pm/SKILL.md)","tokens":300,"sizeBytes":165},{"name":"SKILL.md","path":".claude-plugin/skills/publish/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/publish/SKILL.md","title":"publish","category":"anthropic-skill","format":"markdown","content":"# publish\n\nPath: `.claude-plugin/skills/publish/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/publish/SKILL.md)","tokens":300,"sizeBytes":180},{"name":"SKILL.md","path":".claude-plugin/skills/qa/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/qa/SKILL.md","title":"qa","category":"anthropic-skill","format":"markdown","content":"# qa\n\nPath: `.claude-plugin/skills/qa/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/qa/SKILL.md)","tokens":300,"sizeBytes":165},{"name":"SKILL.md","path":".claude-plugin/skills/ralph/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/ralph/SKILL.md","title":"ralph","category":"anthropic-skill","format":"markdown","content":"# ralph\n\nPath: `.claude-plugin/skills/ralph/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/ralph/SKILL.md)","tokens":300,"sizeBytes":174},{"name":"SKILL.md","path":".claude-plugin/skills/resume-session/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/resume-session/SKILL.md","title":"resume-session","category":"anthropic-skill","format":"markdown","content":"# resume-session\n\nPath: `.claude-plugin/skills/resume-session/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/resume-session/SKILL.md)","tokens":300,"sizeBytes":201},{"name":"SKILL.md","path":".claude-plugin/skills/run/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/run/SKILL.md","title":"run","category":"anthropic-skill","format":"markdown","content":"# run\n\nPath: `.claude-plugin/skills/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/run/SKILL.md)","tokens":300,"sizeBytes":168},{"name":"SKILL.md","path":".claude-plugin/skills/seed/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/seed/SKILL.md","title":"seed","category":"anthropic-skill","format":"markdown","content":"# seed\n\nPath: `.claude-plugin/skills/seed/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/seed/SKILL.md)","tokens":300,"sizeBytes":171},{"name":"SKILL.md","path":".claude-plugin/skills/setup/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/setup/SKILL.md","title":"setup","category":"anthropic-skill","format":"markdown","content":"# setup\n\nPath: `.claude-plugin/skills/setup/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/setup/SKILL.md)","tokens":300,"sizeBytes":174},{"name":"SKILL.md","path":".claude-plugin/skills/status/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/status/SKILL.md","title":"status","category":"anthropic-skill","format":"markdown","content":"# status\n\nPath: `.claude-plugin/skills/status/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/status/SKILL.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude-plugin/skills/tutorial/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/tutorial/SKILL.md","title":"tutorial","category":"anthropic-skill","format":"markdown","content":"# tutorial\n\nPath: `.claude-plugin/skills/tutorial/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/tutorial/SKILL.md)","tokens":300,"sizeBytes":183},{"name":"SKILL.md","path":".claude-plugin/skills/unstuck/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/unstuck/SKILL.md","title":"unstuck","category":"anthropic-skill","format":"markdown","content":"# unstuck\n\nPath: `.claude-plugin/skills/unstuck/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/unstuck/SKILL.md)","tokens":300,"sizeBytes":180},{"name":"SKILL.md","path":".claude-plugin/skills/update/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/update/SKILL.md","title":"update","category":"anthropic-skill","format":"markdown","content":"# update\n\nPath: `.claude-plugin/skills/update/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/update/SKILL.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude-plugin/skills/welcome/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/welcome/SKILL.md","title":"welcome","category":"anthropic-skill","format":"markdown","content":"# welcome\n\nPath: `.claude-plugin/skills/welcome/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/welcome/SKILL.md)","tokens":300,"sizeBytes":180},{"name":"SKILL.md","path":"skills/auto/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/auto/SKILL.md","title":"auto","category":"anthropic-skill","format":"markdown","content":"# auto\n\nPath: `skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/auto/SKILL.md)","tokens":300,"sizeBytes":141},{"name":"SKILL.md","path":"skills/brownfield/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/brownfield/SKILL.md","title":"brownfield","category":"anthropic-skill","format":"markdown","content":"# brownfield\n\nPath: `skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/brownfield/SKILL.md)","tokens":300,"sizeBytes":159},{"name":"SKILL.md","path":"skills/cancel/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/cancel/SKILL.md","title":"cancel","category":"anthropic-skill","format":"markdown","content":"# cancel\n\nPath: `skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/cancel/SKILL.md)","tokens":300,"sizeBytes":147},{"name":"SKILL.md","path":"skills/config/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/config/SKILL.md","title":"config","category":"anthropic-skill","format":"markdown","content":"# config\n\nPath: `skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/config/SKILL.md)","tokens":300,"sizeBytes":147},{"name":"SKILL.md","path":"skills/evaluate/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evaluate/SKILL.md","title":"evaluate","category":"anthropic-skill","format":"markdown","content":"# evaluate\n\nPath: `skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evaluate/SKILL.md)","tokens":300,"sizeBytes":153},{"name":"SKILL.md","path":"skills/evolve/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evolve/SKILL.md","title":"evolve","category":"anthropic-skill","format":"markdown","content":"# evolve\n\nPath: `skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evolve/SKILL.md)","tokens":300,"sizeBytes":147},{"name":"SKILL.md","path":"skills/help/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/help/SKILL.md","title":"help","category":"anthropic-skill","format":"markdown","content":"# help\n\nPath: `skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/help/SKILL.md)","tokens":300,"sizeBytes":141},{"name":"SKILL.md","path":"skills/interview/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/interview/SKILL.md","title":"interview","category":"anthropic-skill","format":"markdown","content":"# interview\n\nPath: `skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/interview/SKILL.md)","tokens":300,"sizeBytes":156},{"name":"SKILL.md","path":"skills/ooo/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/ooo/SKILL.md","title":"ooo","category":"anthropic-skill","format":"markdown","content":"# ooo\n\nPath: `skills/ooo/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/ooo/SKILL.md)","tokens":300,"sizeBytes":138},{"name":"SKILL.md","path":"skills/pm/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/pm/SKILL.md","title":"pm","category":"anthropic-skill","format":"markdown","content":"# pm\n\nPath: `skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/pm/SKILL.md)","tokens":300,"sizeBytes":135},{"name":"SKILL.md","path":"skills/publish/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/publish/SKILL.md","title":"publish","category":"anthropic-skill","format":"markdown","content":"---\nname: publish\ndescription: \"Publish Seed specification as GitHub Issues for team-based project management\"\n---\n\n# /ouroboros:publish\n\nConvert a Seed into a GitHub Epic issue plus Task issues. Works entirely through the `gh` CLI (no MCP), creates new issues only, and never modifies existing ones.\n\n```\nooo publish [seed_path]\n/ouroboros:publish [seed_path]\n```\n\n## Instructions\n\nRun commands with the active runtime's `run_shell` capability and ask every question with the active runtime's `ask_user` capability.\n\n### Step 1: Prerequisites\n\nRun `command -v gh`. If missing, tell the user to install it from https://cli.github.com/ and stop. Run `gh auth status`; if not authenticated, tell the user to run `gh auth login` and stop.\n\n### Step 2: Locate the Seed\n\nSeeds live in `~/.ouroboros/seeds/`: interview Seeds as `{seed_id}.yaml`, PM Seeds as `pm_seed_{id}.json`. In priority order:\n\n1. An explicit `.yaml` or `.json` path argument.\n2. The most recent files from `ls -t ~/.ouroboros/seeds/*.yaml ~/.ouroboros/seeds/*.json 2>/dev/null | head -5`; if several exist, ask the user to choose.\n3. A Seed path reported by `ooo seed` or `ooo pm` earlier in this conversation.\n\nIf none is found, tell the user to run `ooo seed` or `ooo pm` first, and stop.\n\n### Step 3: Parse the Seed\n\nDetect the format by extension. Omit any section whose field is missing or empty rather than failing.\n\nYAML Seed (`ooo interview` + `ooo seed`):\n\n| Field | Use |\n|-------|-----|\n| `goal` | Epic title and Goal section |\n| `constraints` | Constraints section |\n| `acceptance_criteria` | Epic checklist, distributed to Task issues |\n| `ontology_schema` | Ontology table (field, type, description) |\n| `evaluation_principles` | Evaluation Principles table (name, weight, description) |\n| `exit_conditions` | Exit Conditions (Definition of Done) |\n| `metadata.ambiguity_score` | Confidence indicator |\n| `metadata.seed_id` | Duplicate detection |\n\nJSON PM Seed (`ooo pm`, `PMSeed` schema):\n\n| Field | Use |\n|-------|-----|\n| `pm_id` | Duplicate detection |\n| `product_name` | Epic title prefix |\n| `goal` | Goal section |\n| `constraints` | Constraints section |\n| `success_criteria` | Acceptance Criteria checklist |\n| `user_stories` | User Stories, each as \"As a **{persona}**, I want to **{action}**, so that **{benefit}**.\" |\n| `deferred_items` | Deferred Items section |\n| `decide_later_items` | Open Questions section |\n| `assumptions` | Assumptions section |\n\n### Step 4: Target repository\n\nRun `gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null`. If it returns a repo, ask whether to publish there or to another `owner/repo`; otherwise ask for `owner/repo`. Store the answer as `TARGET_REPO`. **Every later `gh` command MUST include `-R <TARGET_REPO>`.**\n\n### Step 5: Duplicate check\n\n```bash\ngh issue list -R <TARGET_REPO> --label \"ouroboros\" --state all --search \"<seed_id or pm_id>\" --limit 5 --json number,title,state\n```\n\nThis finds earlier publishes because the Epic body records the Seed ID (Step 7). If matches exist, list them and ask whether to create anyway or cancel; on cancel, stop.\n\n### Step 6: Plan the issues\n\nGroup the acceptance criteria into logical implementation units (by feature area, layer, or dependency order); each unit becomes one Task. Show the plan (Epic goal summary, then each Task title and brief scope) and ask whether to create the issues or modify the plan. On modify, ask what to change, adjust, and show it again.\n\n### Step 7: Create the issues\n\n`gh issue create` prints the issue URL; take the number from its trailing digits (`grep -o '[0-9]*$'`). Pass bodies through a quoted heredoc (`--body \"$(cat <<'BODY' ... BODY)\"`).\n\n1. Create labels, ignoring \"already exists\":\n   ```bash\n   gh label create \"ouroboros\" -R <TARGET_REPO> --description \"Created by Ouroboros publish\" --color \"6f42c1\" 2>/dev/null || true\n   gh label create \"epic\" -R <TARGET_REPO> --description \"Epic / parent issue\" --color \"0075ca\" 2>/dev/null || true\n   gh label create \"task\" -R <TARGET_REPO> --description \"Implementation task\" --color \"008672\" 2>/dev/null || true\n   ```\n2. Epic: title `[Epic] <goal summary>`, labels `ouroboros,epic`. Body: the Step 3 sections in order (Goal, Constraints, Acceptance Criteria as `- [ ]` items, Ontology, Evaluation Principles, Exit Conditions, plus the PM-only sections), then this footer:\n   ```\n   ---\n\n   **Seed ID**: `<seed_id or pm_id>` | **Ambiguity Score**: <score> | **Seed**: `<seed_file_path>`\n   *Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n3. Each Task: title `[Task] <task title>`, labels `ouroboros,task`. Body: `Parent: #<epic>`, then Scope, Acceptance Criteria (`- [ ]` items for this unit), Test Checklist, Pass Criteria (measurable done conditions), then this footer:\n   ```\n   ---\n\n   *Part of [Epic] #<epic> | Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`*\n   ```\n4. Comment on the Epic (`gh issue comment <epic> -R <TARGET_REPO>`) with an \"Implementation Tasks\" checklist of `- [ ] #<task>: <title>` lines, noting progress is tracked by checking off tasks as their issues close.\n\n### Step 8: Summary\n\nShow `Published to <TARGET_REPO>:` with the Epic and its Tasks as a tree (`#<n> [Epic|Task] <title>`) and the link `https://github.com/<TARGET_REPO>/issues/<epic>`. Suggest next steps: assign tasks, track on a GitHub Projects board, run `ooo run` for AI-assisted implementation of individual tasks.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"publish","description":"Publish Seed specification as GitHub Issues for team-based project management"},"isInternal":false,"tokens":1534,"sizeBytes":5818},{"name":"SKILL.md","path":"skills/qa/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/qa/SKILL.md","title":"qa","category":"anthropic-skill","format":"markdown","content":"---\nname: qa\ndescription: \"General-purpose QA verdict for any artifact type\"\n---\n\n# /ouroboros:qa\n\nFast single-pass quality verdict with actionable suggestions for any artifact: code, documents, API responses, test output, or custom content. For formal three-stage verification of an execution, use `ooo evaluate`.\n\n```\nooo qa [file_path | artifact_text]\nooo qa                                     # recent execution output\n/ouroboros:qa [file_path | artifact_text]\n```\n\nThe QA Judge scores the artifact against a quality bar on Correctness, Completeness, Quality, Intent Alignment, and Domain-Specific dimensions:\n\n| Score | Verdict | Loop action |\n|-------|---------|-------------|\n| >= 0.80 | PASS | done |\n| 0.40 - 0.79 | REVISE | continue |\n| < 0.40 | FAIL | escalate |\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros qa\"` for `ouroboros_qa`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent; this skill works without MCP setup.\n\n### QA steps\n\n1. **Artifact**: a file path (read it with the active runtime's `inspect_code` capability), inline text, or else the most recent execution output; ask with `ask_user` if unclear.\n2. **Quality bar**: the Seed's acceptance criteria when a Seed is in context, else the user's stated bar; otherwise ask \"What does 'good' mean for this artifact?\"\n3. **Artifact type**: `code`, `test_output`, `document`, `api_response`, `screenshot`, or `custom`.\n\n3.5. **Acting verification fan-out** (behavior-bearing artifacts): a text judge can be fooled by a hopeful log line. Use the active runtime's `orchestrate_subagents` capability to launch, together, one probe child per acting modality the runtime exposes: a process probe (`run_shell`: run the command or app or smoke commands with bounded timeouts, capture exit codes and real output), a browser probe (HTTP services and web UIs: load them, exercise the primary flows, capture rendering and console/network errors), a computer-use probe (GUI/TUI: drive it like a user, screenshot observed states), and an artifact probe (`inspect_code`: declared files exist with real content, not placeholders). Each probe returns structured evidence only (commands, observed effects, screenshots/paths, pass/fail per behavior) and covers the applicable adversarial classes the QA tool lists. Skip a modality only when its tools are absent or it is meaningless for the artifact, and say which were skipped and why. Await all probes and pass the merged evidence as `reference`; prefer observed behavior over source text as the `artifact` when they disagree.\n\n4. **Call the tool**:\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the content to evaluate>\n     quality_bar: <what 'pass' means>\n     artifact_type: \"code\"  (or other type)\n     reference: <observed-behaviour evidence from step 3.5, plus any reference>\n     pass_threshold: 0.80  (adjustable)\n     seed_content: <seed YAML if available>\n   ```\n\n   **Plugin delegation**: a response with `status: \"delegated_to_subagent\"` and `dispatch_mode: \"plugin\"` carries no verdict. Its content is the bridge's dispatch notice and its `_subagent` prompt is the child's input, never a result. Keep `qa_session_id`, await the plugin-spawned child, and parse its JSON verdict (`score`, `verdict`, `dimensions`, `differences`, `suggestions`, `reasoning`). No `iteration_entry` comes back, so derive the loop action as the tool does (score >= `pass_threshold`: done; >= 0.40: continue; else escalate) and build the entry yourself (`iteration`, `score`, `verdict`, `loop_action`). If the child returns no parseable verdict, say so instead of presenting the envelope.\n\n5. **Present** the score and verdict prominently, then dimension scores, specific differences, and actionable suggestions. **Empirical evidence outranks the judge**: if the judge scores PASS but a probe observed the behavior failing, present REVISE/FAIL on that evidence and say so. If nothing could act, flag that behavior was not observed. Pick the next action from the verdict:\n   - **PASS (done)**: proceed; the artifact meets the quality bar\n   - **REVISE (continue)**: address the suggestions, then run `ooo qa` again\n   - **FAIL (escalate)**: `ooo interview` to re-examine requirements, or `ooo unstuck` to challenge assumptions\n\n### Iterative QA\n\nThe first call returns `qa_session_id` and `iteration_entry` in meta. On later calls pass `qa_session_id` and the accumulated `iteration_history`. Continue until the verdict is `pass` or `fail`.\n\n### Fallback (no Ouroboros MCP server)\n\nAdopt the `qa-judge` role yourself with the same prompt the MCP tool uses: `$OUROBOROS_AGENTS_DIR/qa-judge.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n```bash\nuvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" qa-judge.md\n```\n\nelse `src/ouroboros/agents/qa-judge.md` in a source checkout.\n\nIf none is reachable, judge on the dimensions and thresholds above and label the verdict as an unaligned fallback. Run the step 3.5 probes first for behavior-bearing artifacts, render the verdict in the same shape the MCP tool returns (score, verdict, threshold, dimensions, differences, suggestions, reasoning, loop action), and keep the iterative contract with a `qa-<uuid4_short>` session id and an iteration count held in the conversation.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"qa","description":"General-purpose QA verdict for any artifact type"},"isInternal":false,"tokens":1451,"sizeBytes":6166},{"name":"SKILL.md","path":"skills/ralph/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/ralph/SKILL.md","title":"ralph","category":"anthropic-skill","format":"markdown","content":"---\nname: ralph\ndescription: \"MCP-owned Ralph loop around background evolve_step jobs\"\nmcp_tool: ouroboros_ralph\nmcp_args:\n  lineage_id: \"$lineage_id\"\n---\n\n# /ouroboros:ralph\n\nMCP-owned Ralph loop around background `evolve_step` jobs. \"The boulder never stops.\"\n\n## Usage\n\n```\nooo ralph --lineage-id <lineage_id>\n/ouroboros:ralph --lineage-id <lineage_id>\n```\n\nThe `ouroboros_ralph` tool owns the loop (do not reimplement it): one background job runs repeated `evolve_step` generations until QA pass, convergence, a terminal evolution action, cancellation, or `max_generations`. Router dispatch reads only the named `--lineage-id` option, never trailing text.\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros ralph job\"` for `ouroboros_ralph`, `ouroboros_job_wait`, `ouroboros_job_status`, `ouroboros_job_result`, and `ouroboros_cancel_job`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tools are genuinely absent, stop and tell the user that Ralph requires the Ouroboros MCP runtime.\n\n### 1. Prepare lineage input\n\n- **Continue a lineage**: when the user gives an existing `lineage_id` and wants to continue it, reuse it and omit `seed_content` unless they supply an updated Seed.\n- **New run from Seed YAML**: use it as `seed_content` with a fresh `lineage_id` such as `ralph-<short-slug>-<uuid>`. Never reuse a Seed, interview, or session id as the lineage id, so separate runs over one Seed do not collide.\n- **Plain natural-language request**: never pass raw text as `seed_content` or freehand Seed YAML. Run `ooo interview` and `ooo seed` first (or reuse a validated Seed in context), then start with a fresh `lineage_id`. Without inputs the tool returns input guidance instead of a job.\n\n### 2. Start Ralph\n\nCall `ouroboros_ralph` with `lineage_id`, `seed_content` (generation 1 of a new lineage), `execute` (default `true`), `parallel` (default `true`), `skip_qa` (default `false`), `project_dir` when known, and `max_generations` (default `10`, also the hard max; lower it only on request).\n\n### 3. Handle the start response\n\n- **Job started** (`response.meta.job_id` present): keep `response.meta.cursor` and report:\n\n  ```\n  [Ralph] Started background loop: <job_id>\n  Lineage: <lineage_id>\n  Live view: <dashboard_url, or `ouroboros tui open`>\n\n  A read-only observer will post meaningful progress, attention, and terminal\n  events here. This conversation remains available for other safe work.\n  ```\n\n- **Observer handoff**: if `response.meta.job_observer` is missing, recover it from the final `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel; fail closed unless it passes canonical v1 validation and its job identity matches the visible start receipt, and use it only as an identity anchor, never to reconstruct tools or arguments. When the host supports an independent child session, spawn exactly one read-only observer and pass the contract unchanged. The observer exclusively owns job wait/result calls and the cursor; the main session keeps user conversation, explicit on-demand status, and user-requested cancellation. The main session must not poll the same job while the observer is active. It may refine requirements, do read-only review, or work in an unrelated isolated worktree; check active-worker conflicts before writing to Ralph's workspace.\n  - A `wait` call or a parent job-status poll is not a spawn; claim no observer until a live child ID/path returns. The contract's `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name the concrete spawn and wait mechanics. If the runtime cannot wake a parent turn that already ended when the child posts (a child message only queues for the parent), keep the parent turn open with the host's child-wait primitive in waits of at most 60 seconds while the observer is active. Relay meaningful updates and wait again until terminal.\n  - User input may interrupt the wait; handle it and resume waiting unless the user asks to stop live observation or replaces the request. Then end only the relay loop, keep the durable job running, and offer next-turn or explicit-status catch-up. Use the same fallback, instead of waiting indefinitely, if the observer child fails, is cancelled, or exits before a terminal summary. The relay loop must not poll the Ouroboros job or take cursor ownership.\n  - If spawn fails, promise no live relays: the detached worker continues after the stdio turn, and the main session catches up from durable events on the next interaction or explicit status request.\n- **Plugin delegation** (`response.meta.status == \"delegated_to_plugin\"`, `job_id` is `None`): a child session owns the loop. Never call job tools without a job id; treat the child session result as the terminal surface and summarize its completion/error state and lineage id.\n\n### 4. Monitor (polling owner only)\n\nThe observer is the default owner. Run this loop in the main session only when no independent child session exists and the user explicitly asked for live watching; otherwise catch up on the next turn. Never run both:\n\n- `ouroboros_job_wait(job_id, cursor, timeout_seconds=120, stream=\"linked\", wait_for=\"attention_or_ac_change\")` for long polling;\n  after every wait/status response, update `cursor = response.meta.cursor`\n- `ouroboros_job_status(job_id)` for a quick status check\n- `ouroboros_job_result(job_id)` when the job is terminal\n- `ouroboros_cancel_job(job_id)` if the user says stop/cancel\n\nRelay rules: 1-2 lines per change; surface `attention_required` and rejected or uncertain delivery immediately; distinguish Synapse `queued` from runtime-proven `applied`; never forward heartbeats, raw tool output, commands, or model reasoning. Report run configuration, AC count and parallel levels, first scheduled ACs, and verified AC completion; say \"currently running with\", since later generations may switch model or harness. When `lineage.generation.started` carries `ac_focus`, report what the generation is redoing from `active_ac_descriptions` and how many ACs stay frozen (for example \"Gen 7: reworking 2/5 ACs, 3 frozen on prior PASS evidence\"); if it is absent or every AC is active, say the full AC graph is running. Never quote verify commands or expected outputs.\n\nWhen the user asks a live AC a read-only question or adds intent, call `ouroboros_session_signal_targets` for the observed execution and pick the relevant AC without asking for internal IDs. Use `mode=\"inform\"` for questions and assurance, and omit `fallback_mode` in that mode. For implementation refinement use `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, and explicit `fallback_mode=\"after_turn\"` with the exact discovered guards, sent via `ouroboros_session_signal`. Shared goal, AC, constraint, or non-goal changes require an approved shared successor.\n\n### 5. On termination\n\nThe polling owner fetches the job result, then:\n- **Success / convergence**: summarize the final generation, QA verdict, and any `worktree_path` / `worktree_branch`. A Ralph `lineage_id` is not an execution `session_id`: offer `ooo evaluate <session_id>` only when a real execution session id is available from a separate run.\n- **Max generations / failure**: summarize the stop reason and suggest `ooo unstuck`, `ooo interview`, or a narrower Ralph retry.\n- **Cancelled**: confirm and keep the job id for later inspection.\n\n### Active Conductor decision policy\n\nFor `attention_required`, use at most one short-lived read-only verifier. If the host has no verifier primitive, surface the evidence and do not mutate. Otherwise VERIFY → DECIDE from `recommended_host_actions` → LOG `selected` with `ouroboros_record_conductor_decision` → ACT only a menu-listed registered tool → LOG exactly one `completed`, `failed`, or `declined` outcome. Ralph may apply a conductor directive only to the first and sole bounded successor generation (`max_generations=1`), and only when it is deterministic and non-relaxing. Never silently retry or weaken the approved shared contract.\n\nThese are English canonical host instructions. Render them, and every relay, naturally in the user's conversation language.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"ralph","description":"MCP-owned Ralph loop around background evolve_step jobs","mcp_tool":"ouroboros_ralph","mcp_args":{"lineage_id":"$lineage_id"}},"isInternal":false,"tokens":2053,"sizeBytes":8987},{"name":"SKILL.md","path":"skills/resume-session/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/resume-session/SKILL.md","title":"resume-session","category":"anthropic-skill","format":"markdown","content":"---\nname: resume-session\ndescription: \"List in-flight Ouroboros sessions and show the commands needed to re-attach after MCP disconnect\"\n---\n\n# /ouroboros:resume-session\n\nRecover in-flight Ouroboros sessions after an unexpected MCP server disconnect. The name avoids shadowing Claude Code's built-in `/resume`.\n\n```\nooo resume-session [--all]\n/ouroboros:resume-session\n```\n\n## Instructions\n\n1. Run with the active runtime's `run_shell` capability:\n\n   ```\n   ouroboros resume --list\n   ```\n\n   It reads the configured EventStore directly and read-only (no MCP server needed, nothing created or written) and lists `running` or `paused` sessions: the 20 most recent, or all with `--all`. `--list` prints the table and exits without the interactive prompt, which aborts when no terminal is attached. Exit code 2 means the EventStore exists but could not be read.\n\n2. If sessions are listed, show the table and ask which session to work with (active runtime's `ask_user` capability). Each row carries the `session_id`, `exec_id`, and Seed id used below.\n\n3. Give the matching re-attach path:\n\n   - Inspect persisted events (read-only, no MCP server):\n     ```\n     ouroboros status execution <exec_id> --events\n     ```\n   - Inspect interactively (read-only monitor; pick the session in the TUI):\n     ```\n     ouroboros tui monitor\n     ```\n   - Resume execution (needs the original Seed file; `--resume` takes the `session_id`):\n     ```\n     ouroboros run workflow --orchestrator --resume <session_id> <seed.yaml>\n     ```\n\n   Afterwards: `ooo evaluate` once the execution completes, or `ooo cancel <session_id>` if it is stuck.\n\nIf it reports \"No in-flight sessions found\", the execution completed, failed, or was cancelled, or the EventStore was never created; `ouroboros tui monitor` browses past sessions.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"resume-session","description":"List in-flight Ouroboros sessions and show the commands needed to re-attach after MCP disconnect"},"isInternal":false,"tokens":523,"sizeBytes":2175},{"name":"SKILL.md","path":"skills/run/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/run/SKILL.md","title":"ouroboros-run","category":"anthropic-skill","format":"markdown","content":"---\nname: ouroboros-run\ndescription: \"Use when an Ouroboros Seed (a spec file with a goal and acceptance criteria, such as *.seed.yaml) already exists and the user wants it executed: 'run the seed', 'execute this spec', 'ooo run'. Executes it and verifies every acceptance criterion. Not for raw requests without a Seed (use interview or auto).\"\naliases: [execute]\nmcp_tool: ouroboros_start_execute_seed\nmcp_args:\n  seed_path: \"$1\"\n  cwd: \"$CWD\"\n---\n\n# /ouroboros:ouroboros-run\n\nExecute a Seed specification through the Ouroboros workflow engine as a background job. A completed run enqueues formal evaluation by default, and a rejection continues through a bounded Ralph loop.\n\n## Usage\n\n```\n/ouroboros:ouroboros-run [seed_file_or_content]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros execute\"` for `ouroboros_start_execute_seed`, `ouroboros_job_wait`, `ouroboros_job_result`, and `ouroboros_ac_tree_hud`; `\"+ouroboros session signal\"` for `ouroboros_session_signal_targets` and `ouroboros_session_signal`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the **Fallback (No MCP Server)** section only when the tools are genuinely absent.\n\n### Execution Steps\n\n1. **Do not create or switch branches yourself.** For a background execution\n   job, `use_worktree` defaults to true: the server runs the task in its own\n   worktree and reports `worktree_path` / `worktree_branch` in the job result.\n   Tell the user the task was isolated only when those fields are present. A\n   `dispatch_mode=\"plugin\"` response delegates to a child session and carries\n   no worktree.\n\n2. **Get the Seed.** Read a given file path with the active runtime's `inspect_code` capability, use inline YAML directly, or otherwise take the most recently generated Seed in the conversation.\n\n   Before a fresh start, do not ask about an efficiency policy unless the user\n   raised it or `execution.default_policy` in `~/.ouroboros/config.yaml` is\n   explicitly `ask`. Otherwise omit both arguments: the server applies the\n   configured default (quality-first when nothing is configured), and its start\n   receipt names the running policy and the change command. If the user did\n   choose, or the config says `ask`, map the choice in outcome language:\n\n   - **Efficient execution**: start parallel/decomposed work economically and\n     strengthen the route only when recovery requires it. Send\n     `efficiency_mode=\"adaptive\"` and `frugality_assurance=\"observe\"`.\n   - **Quality-first execution**: keep child work at the parent starting tier.\n     Send `efficiency_mode=\"quality_first\"` and `frugality_assurance=\"off\"`.\n\n   `frugality_assurance=\"strict\"` is a separate explicit opt-in because it may\n   spend extra work on proof; never infer it from the efficiency choice. Do not\n   ask again on resume: the server restores the persisted policy and rejects a\n   resume-time change.\n\n3. **Start background execution:**\n   ```\n   Tool: ouroboros_start_execute_seed\n   Arguments:\n     seed_content: <the seed YAML>\n     efficiency_mode: <only when chosen: adaptive or quality_first>\n     frugality_assurance: <only when chosen: observe, off, or explicit strict>\n     session_id: <only when resuming an existing session>\n   ```\n   Omit `model_tier` by default so the runtime selects automatically. Include\n   `model_tier: <user choice>` only when the user explicitly requested a tier.\n   The call returns at once with `job_id`, `session_id`, and `execution_id`.\n\n4. **Hand off.** Relay the server's start receipt (IDs, backends, `Efficiency Mode` with any change command, dashboard). Then add:\n   - Live view: if `execution.tui_autolaunch: true` (or legacy top-level `tui_autolaunch: true`) is set, run `ouroboros tui open`; otherwise offer it once without blocking. If it prints a manual command (headless, SSH), relay that once.\n   - Observation: a confirmed read-only observer (step 5), or durable catch-up mode.\n   - This conversation stays available: the user can refine requirements, review code, or work on an unrelated task in an isolated worktree; check for active-worker conflicts before editing this run's workspace.\n\n5. **Delegate observation to exactly one observer.** The start result carries\n   `response.meta.job_observer`, a read-only observer contract with its own wait\n   and result tools, `instructions`, `restrictions`, and fallback. If the\n   structured meta is missing, recover the contract from the final\n   `<!-- ouroboros-job-observer-v1 base64 ... -->` content sentinel and fail\n   closed: if there is more than one sentinel or it is not at the end of the\n   text, the bounded payload does not decode to an object whose only key is\n   `job_observer`, that contract fails canonical v1 validation (it must equal,\n   field for field, the v1 contract the server builds from its own `job_id`,\n   `cursor`, `session_id`, `execution_id`, and `follow_result_job_keys`, so a\n   changed tool, argument, or instruction, or an extra field, fails), its\n   `job_id` differs from the visible start receipt, or the structured and inline\n   contracts differ, do not spawn an observer and report a transport-integrity\n   failure. Never rebuild the contract from visible IDs.\n\n   With a valid contract and an independent child-session primitive, spawn\n   exactly one observer through the active runtime's `orchestrate_subagents`\n   capability and pass the contract unchanged. It owns the job cursor, follows\n   the contract (including `follow_result_job_keys` for chained evaluation and\n   Ralph), and stays read-only. Claim an observer only after the spawn returns\n   a live child ID/path. The main session must not poll the same job while the\n   observer owns it. If plugin mode already delegated the whole execution (no\n   `job_id`), follow that child's lifecycle instead.\n\n   - A `wait` call or a parent job-status poll is not a spawn. The contract's\n     `host_lifecycle` and the runtime's `orchestrate_subagents` guidance name\n     the concrete spawn and wait mechanics; pass the contract unchanged in the\n     child message. After the live child ID returns, if the runtime cannot\n     wake a parent turn that already ended when the child posts (a child\n     message only queues for the parent), keep the parent turn open with the\n     host's child-wait primitive in waits of at most 60 seconds. Relay\n     meaningful updates and wait again until the terminal summary. User input may interrupt the wait; handle it and\n     resume unless the user asks to stop live observation or replaces the\n     request. Then end only the relay loop, keep the durable job running, and\n     offer next-turn or explicit-status catch-up. If the observer child fails,\n     is cancelled, or exits early, use that same catch-up instead of waiting\n     indefinitely. The relay loop must not poll Ouroboros job tools or touch the\n     observer's cursor.\n\n   If no child can be created, do not claim an observer or promise live\n   messages. The detached worker survives the stdio MCP turn: say progress is\n   durable and will be caught up on the next turn or an explicit status\n   request. Keep the turn open only when the user explicitly asked for live\n   watching (step 6).\n\n   **Relaying observer events.** Relay each meaningful event in 1-2 lines;\n   suppress unchanged heartbeats, raw tool output, commands, and reasoning.\n   - `run_configuration`: runtime/harness, starting model or tier when known,\n     efficiency mode, frugality assurance.\n   - `execution_plan`: total ACs, dependency/parallel levels, and the first\n     scheduled AC summaries.\n   - `discovery_summary`: bounded targets and purpose.\n   - `level_started` / `level_completed`, `ac_routing` / `harness_changed`\n     (\"currently running with\"), `ac_attempt_judged`: only real changes.\n   - `ac_accepted` / `ac_rejected`: the AC's final acceptance and compact\n     disposition evidence.\n   - `attention_required`: surface immediately (see Active Conductor below).\n   - Synapse `.queued` / `.delivering`: pending, not applied yet. `.applied` /\n     `.completed`: confirm and relay any bounded AC reply. `.rejected` /\n     `.delivery_uncertain`: surface immediately; never claim the AC changed\n     course.\n\n   These are English canonical host instructions: render every relay in the\n   user's current conversation language, keeping event codes and mode values\n   only when exact diagnostics help.\n\n6. **Fallback: live relay in the main session.** Only when there is no\n   observer contract or no child primitive, and the user explicitly asked to\n   keep watching this turn. Never run it beside a delegated observer;\n   otherwise end the turn and catch up from the same cursor next turn.\n   ```\n   Tool: ouroboros_job_wait\n   Arguments:\n     job_id: <job_id>\n     cursor: <latest cursor, or 0>\n     timeout_seconds: 180\n     view: \"summary\"\n     stream: \"linked\"\n     wait_for: \"attention_or_ac_change\"\n   ```\n   Replace the cursor from `response.meta.cursor` after every call. Treat\n   `response.meta` as the source of truth and `response.text` only as a hint.\n   If `response.meta.changed` is false, repeat silently; otherwise emit one\n   compact line (phase, AC/sub-AC counts, new current-work hint), never raw\n   JSON, the full tree, or an ETA. On `completed`, `failed`, `cancelled`, or\n   `interrupted`, say so explicitly and go to step 8.\n\n7. **Drill-down only.** Use `ouroboros_ac_tree_hud` when the user asks for\n   details or progress looks stuck, never in the routine loop. `view` is\n   `\"compact\"`, `\"summary\"`, or `\"tree\"` (add `max_nodes: 30`); treat\n   `unchanged cursor=<cursor>` as a silent no-op.\n   ```\n   Tool: ouroboros_ac_tree_hud\n   Arguments:\n     session_id: <session_id>\n     cursor: <cursor>\n     view: \"summary\"\n   ```\n\n8. **Fetch the final result in the polling owner** (the observer by default,\n   the main session only on the step 6 fallback):\n   ```\n   Tool: ouroboros_job_result\n   Arguments:\n     job_id: <job_id>\n   ```\n   Present status, session ID, and summary. Its QA verdict (skippable with\n   `skip_qa: true` at start) is not the formal 3-stage evaluator.\n\n   If the result meta has `chained_evaluate_job_id`, the polling owner follows\n   that job and fetches its result: render **APPROVED** when\n   `final_approved: true`, otherwise not approved with the failed ACs or\n   reason. If the evaluate job failed or timed out, keep the run success and\n   show `Next: ooo evaluate <session_id>` as the manual retry. If the\n   evaluation has `chained_ralph_job_id`, follow it too and report approval or\n   the bounded Ralph stop reason; a rejected first evaluation does not make\n   the run blocked.\n\n   Without `chained_evaluate_job_id`, show:\n   - **PASS**: `Next: ooo evaluate <session_id> for formal 3-stage verification`\n   - **REVISE**: the differences/suggestions, then `Next: Fix the issues above, then ooo run to retry -- or ooo unstuck if blocked`\n   - **FAIL/ESCALATE**: `Next: Review failures above, then ooo run to retry -- or ooo unstuck if blocked`\n\n### Synapse intent refinement\n\nSynapse is the `ouroboros_session_signal` channel that delivers bounded user intent to one running AC. When the user adds implementation intent during an active run, the main session picks the target; never ask the user for internal AC or session IDs.\n\n1. Call `ouroboros_session_signal_targets(execution_id=...)` with the `execution_id` from the start result or observer contract.\n2. Match the user's meaning against each target's `ac_content`, display path, and current HUD activity. Select one active target directly; with several, select only a materially more relevant one, and ask a short clarification only for a genuine tie.\n3. Additive implementation refinement: call `ouroboros_session_signal` with the target's exact scope/attempt/execution guards, `contract_effect=\"additive\"`, `source=\"user\"`, `mode=\"redirect\"`, `fallback_mode=\"after_turn\"`, `expected_contract_version` when discovery supplies it, and one stable idempotency key for this user turn. If the target went stale, rediscover once instead of asking for IDs.\n4. Read-only question or assurance request: use `mode=\"inform\"` and `contract_effect=\"additive\"`, and omit `fallback_mode` (valid only for redirect). Relay the bounded reply from the completed event.\n5. Tell the user which AC was selected and the effective mode; say it was reflected only after `.applied` or `.completed`.\n\nNever use Synapse to change approved goals, ACs, constraints, or non-goals; those need an approved shared successor or replacement contract.\n\n### Active Conductor attention handling\n\n`recommended_host_actions` is the authoritative menu; never invent a mutating tool call.\n\n1. VERIFY with at most one short-lived read-only host child using the supplied evidence IDs. Without a verifier primitive, surface the attention and stop before mutation.\n2. DECIDE among the ordered menu actions only after engine-owned retry/routing is closed.\n3. LOG `phase=\"selected\"` through `ouroboros_record_conductor_decision` before ACT. A specification change in run mode needs explicit user approval with its receipt bound.\n4. ACT only when the menu names a currently registered MCP tool. A corrective successor preserves the approved contract unless the user approved the shared specification change.\n5. LOG exactly one terminal `completed`, `failed`, or `declined` outcome. Never silently retry a failed conductor action.\n\n## Fallback (No MCP Server)\n\nTell the user:\n\n```\nOuroboros MCP server is not configured.\nTo enable full execution mode, run: /ouroboros:setup\n\nWithout MCP, you can still:\n- Use /ouroboros:interview for requirement clarification\n- Use /ouroboros:seed to generate specifications\n- Manually implement the seed specification\n```\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"ouroboros-run","description":"Use when an Ouroboros Seed (a spec file with a goal and acceptance criteria, such as *.seed.yaml) already exists and the user wants it executed: 'run the seed', 'execute this spec', 'ooo run'. Executes it and verifies every acceptance criterion. Not for raw requests without a Seed (use interview or auto).","aliases":["execute"],"mcp_tool":"ouroboros_start_execute_seed","mcp_args":{"seed_path":"$1","cwd":"$CWD"}},"isInternal":false,"tokens":3343,"sizeBytes":14352},{"name":"SKILL.md","path":"skills/seed/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/seed/SKILL.md","title":"seed","category":"anthropic-skill","format":"markdown","content":"---\nname: seed\ndescription: \"Use when goal, constraints, and success criteria are already settled and the user wants them frozen into a formal spec an agent can execute and verify: 'turn this into a spec', 'write it up as a Seed', or right after an interview. Returns an immutable Seed with acceptance criteria. Not for vague requests (use interview first).\"\naliases: [crystallize]\nmcp_tool: ouroboros_generate_seed\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:seed\n\nGenerate a validated Seed specification from an interview or from requirements this conversation already settled.\n\n## Required Skill Capabilities\n\n`ask_user` (the active runtime's user-question surface), `inspect_code`, `call_mcp`, `orchestrate_subagents` (lateral persona payloads), `run_shell` (audit-trail and prefs writes), `refine_answer` (confirm free-form decisions), `maintain_ledger` (QA scores, candidate decisions, rejected proposals).\n\n## Usage\n\n```\nooo seed [session_id]\n/ouroboros:seed [session_id]\n```\n\n## Instructions\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before running any shell snippet below, and call `ouroboros_python` with every argument quoted. It accepts only Python 3.12 or newer and falls back to uv.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros seed\"` for `ouroboros_generate_seed`; `\"+ouroboros qa\"` for `ouroboros_qa`; `\"+ouroboros lateral\"` for `ouroboros_lateral_think`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\nLoad `ouroboros_generate_seed` before choosing a path: if it is callable, use **Path A**; use **Path B** only when it is genuinely absent (no Ouroboros MCP server).\n\n**Delegated responses are not artifacts.** If any tool below returns `status: \"delegated_to_subagent\"` (with `dispatch_mode: \"plugin\"` and possibly an `_subagents` array), keep the returned session ID, wait for the plugin-managed subagent results, and parse the artifact (Seed YAML, QA verdict, or persona texts) from those results, never from the envelope or its prompts.\n\n### Path A: MCP Mode (Preferred)\n\n1. Pick the entrance:\n   - `session_id` given, or a recent `ouroboros_interview` session ID in the conversation: use the interview session (step 2).\n   - No interview, but THIS conversation already settled the goal, the constraints, and verifiable success criteria (a lateral decision, a brownfield scan, or plain discussion that converged): use the interview-less path below. Do not send the user to `ooo interview` to repeat what they already said.\n   - Otherwise ask the user which interview or requirements to seed.\n\n   **Interview-less path** (`session_context`):\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_context:\n       goal: <the user's own settled wording, verbatim, never your paraphrase>\n       acceptance_criteria: [<verifiable checks: a command, a visible behaviour, a measurable state>]\n       constraints: [<optional>]\n       decisions: [<optional; each becomes a constraint>]\n       project_type: greenfield | brownfield\n   ```\n   Every value enters the Seed byte-for-byte, so shell chains in an AC (`ruff check && pytest`) are allowed. If the response has `status: \"gap_questions_required\"`, ask the user exactly the listed questions, merge the answers into `session_context`, and call again; that is the whole interview.\n\n2. Interview session:\n   ```\n   Tool: ouroboros_generate_seed\n   Arguments:\n     session_id: <interview session ID>\n   ```\n   The tool extracts requirements from persisted interview state, scores ambiguity (must be <= 0.2), and returns Seed YAML.\n\n3. If no Seed YAML results, stop and ask the user to resume generation or supply the artifact. Never fabricate a Seed.\n\n4. Run the Advisory QA Check below, then go to \"After Seed Generation\".\n\n### Path B: No MCP Server\n\n1. Read the `seed-architect` prompt and adopt that role: `$OUROBOROS_AGENTS_DIR/seed-architect.md` when that override is set; else the installed package's copy, printed with `run_shell`:\n\n   ```bash\n   uvx --isolated --python '>=3.12' --from ouroboros-ai python -c \"import importlib.resources as r, sys; print(r.files('ouroboros.agents').joinpath(sys.argv[1]).read_text(encoding='utf-8'))\" seed-architect.md\n   ```\n\n   else `src/ouroboros/agents/seed-architect.md` in a source checkout. Resolve every agent prompt this skill names the same way, substituting its file name.\n2. Recover the requirements before drafting; never invent missing context:\n   - With a `session_id`, use current-thread Q&A and corrections only when they belong to that session; if incomplete, use `inspect_code` / `run_shell` to find persisted or exported artifacts for that ID (for example under `~/.ouroboros/data/`). Keep a persisted transcript as evidence, but let explicit same-thread corrections supersede it.\n   - Without a `session_id`, use current-thread Q&A only when it forms one coherent interview.\n   - Otherwise ask for the transcript or a requirement summary, or suggest `ooo interview`. Never seed from an absent or mismatched transcript.\n3. Generate the Seed YAML, run the Advisory QA Check, then go to \"After Seed Generation\".\n\n### Advisory QA Check (single pass, non-blocking)\n\nRun QA **exactly once** on the generated Seed. The verdict is advisory and never blocks: the Seed is presented as final regardless of score, and there is no QA-until-PASS loop.\n\nGeneration (Path A tool or Path B role) runs **exactly once** and fixes the Seed's ontology. Any later revision is a direct YAML edit by you; never call `ouroboros_generate_seed` again (it takes no revision hints and would discard the ontology).\n\n**MCP QA mode:**\n   ```\n   Tool: ouroboros_qa\n   Arguments:\n     artifact: <the seed YAML>\n     quality_bar: \"Seed must be internally consistent, acceptance_criteria must be measurable and testable, constraints must be concrete (no vague terms), ontology_schema must cover all entities referenced in goal/criteria, and there must be no contradictions between fields. acceptance_criteria must also be parsimonious in the ontological sense: a criterion names a state of the finished work a user can see is true, while an implementation step names a means of reaching it, and only the first belongs in the list. Read each criterion beside its siblings — one intelligible only as a move toward a sibling is that sibling's means and belongs merged into the outcome it serves, and flagging that is as important as flagging a missing piece, since it commits the seed to an unverified path. How many criteria a goal has follows from that judgment, so weigh each criterion against its siblings.\"\n     artifact_type: \"document\"\n     pass_threshold: 0.90\n     seed_content: <the seed YAML>\n     qa_session_id: <reuse across passes>\n     iteration_history: <accumulated across passes>\n   ```\nThe 0.90 bar (stricter than the default 0.80) labels the verdict; it gates nothing.\n\n**Fallback QA mode** (QA tool absent): read the `qa-judge` prompt (resolved as in Path B step 1), adopt that role, and evaluate the Seed with the same quality bar and threshold. It returns JSON with lowercase `verdict` (`pass`/`revise`/`fail`), `score`, `dimensions`, `differences`, `suggestions`, `reasoning`; uppercase the verdict only for display and add no non-schema fields. There is no `qa_session_id`; keep pass history in the audit block.\n\nPresent, always in this order:\n1. `QA advisory: <PASS|REVISE|FAIL>, score X.XX (bar 0.90).`\n2. Below the bar: the top 2-3 suggestions as short advisory bullets (findings, not tasks). Apply none automatically.\n3. The complete Seed YAML in a fenced `yaml` block.\n4. For REVISE or FAIL, one opt-in line such as `Want a refinement pass on these findings? Otherwise the seed stands as-is.` For FAIL (< 0.40) also mention `ooo interview` (revisit requirements) or `ooo unstuck` (challenge assumptions). Then continue to \"After Seed Generation\"; the Seed is final unless the user opts in.\n\nOnly on an explicit opt-in, run one refinement pass (below), re-run QA once for an updated advisory line, and present the revised YAML. Each further pass needs a fresh explicit opt-in; never chain passes. Before each later QA call, append the previous verdict and the applied/rejected decisions to `iteration_history`.\n\n#### Refinement pass: Wonder → Reflect → Refine → Restate (opt-in)\n\nDiverge across independent sources, debate, let the user decide, then apply. No candidate is accepted by default, and you never apply a revision on your own (User Adoption Gate).\n\n**Wonder: collect proposals.**\n- **QA**: the verdict's `suggestions` (structural gaps in the YAML; QA cannot see the interview).\n- **Socratic lens** (`socratic-interviewer` prompt, resolved as in Path B step 1): check the Seed against interview evidence (persisted session state first, then this conversation) for 2-4 items: dropped or softened user constraints, rejected scope that crept back, flattened nuance, unagreed assumptions. Without evidence, record `no Socratic proposal: dialectic context unavailable`; never invent preferences. A QA/Socratic conflict goes to Reflect; neither side wins automatically.\n- **Lateral personas** (only if `ouroboros_lateral_think` is callable):\n  ```\n  Tool: ouroboros_lateral_think\n  Arguments:\n    problem_context: |\n      User opted into a refinement pass (QA advisory score X.XX, bar 0.90).\n      Current seed YAML:\n      <YAML>\n      QA suggestions:\n      - <suggestion 1>\n      Original user goal from interview: <recall>\n    current_approach: \"The seed as currently drafted (above).\"\n    persona: \"all\"\n    failed_attempts:\n      - <candidates rejected in earlier passes>\n  ```\n  Extract at most 1-2 concrete, discrete revisions from each persona's prose and drop abstract advice. If the response carries the `<!-- ouroboros-lateral-inline-dispatch-v1 base64 ... -->` sentinel and the runtime can dispatch isolated subagents, decode it and send each `payload.prompt` + `payload.context` through `orchestrate_subagents`; otherwise read the visible persona sections (split on section headers, not bare `---`). If the tool is absent, record `no lateral proposals: MCP lateral tool unavailable` and do not emulate personas.\n\n**Reflect: structure the debate.** Tag each candidate with its backing sources and a type (`expand`, `sharpen`, `remove`, `resolve_conflict`): convergent (two or more sources agree, strong), divergent (sources conflict; the user resolves it), singleton (weaker). Show a balance line such as `Balance: 4 expand / 2 sharpen / 1 remove` as information, not a warning.\n\n**Refine: user gate.** Ask single-choice `ask_user` questions only, conflicts first: one per conflict group (one option per resolution plus \"Leave unchanged\"), then strong revisions (\"apply all, review one by one, or skip\"), then singletons (\"review one by one or skip all\"). Every batch offers \"keep current seed\"; confirm free-form answers with `refine_answer`. Pass rejected candidates as `failed_attempts` on later lateral calls.\n\n**Restate: apply accepted items only.** Edit the existing YAML in place, keep fields that were already correct, and do not regenerate. If everything was skipped, the Seed stands unchanged.\n\n**Audit trail.** After each pass, append to `~/.ouroboros/seed-revisions/<revision_key>.md` (create the directory if needed): pass number, QA score, every candidate with its source tag and accepted/rejected decision, and the diff against the previous YAML. `revision_key` is the `session_id`, or, without one, `<slugified-goal>-YYYYMMDDTHHMMSSZ` derived once and reused for every pass. If the write fails, include the audit block in the response.\n\n## After Seed Generation\n\nAnnounce `Your seed has been crystallized!`\n\nThen read `~/.ouroboros/prefs.json`. If `star_asked` is not `true`, ask one single-choice question with `ask_user`: \"If Ouroboros helped clarify your thinking, a GitHub star supports continued development.\" with options:\n\n- **⭐ Star**: run `gh api -X PUT /user/starred/Q00/ouroboros`, then record `star_asked`.\n- **Not now**: record `star_asked`.\n\nOffer setup only when this Seed came from Path B (no Ouroboros MCP server): say that `ooo setup` enables `ooo run` and evaluation, and point the footer at it. After Path A, MCP already works: never suggest `ooo setup`; the footer points to `ooo run`.\n\nRecord `star_asked` with this snippet, which preserves existing keys such as `welcomeShown`, `welcomeCompleted`, and `welcomeVersion`:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nIf `star_asked` is already `true`, skip the question.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"seed","description":"Use when goal, constraints, and success criteria are already settled and the user wants them frozen into a formal spec an agent can execute and verify: 'turn this into a spec', 'write it up as a Seed', or right after an interview. Returns an immutable Seed with acceptance criteria. Not for vague requests (use interview first).","aliases":["crystallize"],"mcp_tool":"ouroboros_generate_seed","mcp_args":{"session_id":"$1"}},"isInternal":false,"tokens":3554,"sizeBytes":14727},{"name":"SKILL.md","path":"skills/setup/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/setup/SKILL.md","title":"setup","category":"anthropic-skill","format":"markdown","content":"---\nname: setup\ndescription: \"Guided onboarding wizard for Ouroboros setup\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:setup\n\nGuided Ouroboros setup inside a Claude Code session.\n\n> Other runtimes (Codex, Copilot, OpenCode, and others) configure through the\n> CLI instead, for example `ouroboros setup --runtime codex` or\n> `ouroboros setup --runtime copilot`. See\n> [Getting Started](https://github.com/Q00/ouroboros/blob/main/docs/getting-started.md).\n\n## Usage\n\n```\nooo setup\n/ouroboros:setup\n/ouroboros:setup --uninstall\n```\n\nClaude setup confirms the runtime profile (the Claude Agent SDK on MCP 1.x)\nand optionally adds an Ouroboros reference block to the project's CLAUDE.md.\nIt deliberately leaves `~/.claude/mcp.json` untouched because marketplace\nplugin wiring owns that file. `[claude]` and its explicit `[claude-sdk]` alias\nuse MCP 1.x. The plugin launches `[mcp]` in a separate MCP 2 process with the\ndependency-free `[claude-cli]` worker.\n\n## Setup Wizard Flow\n\nAsk questions with the active runtime's `ask_user` capability unless a step\nsays otherwise.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Step 0.5: Community Support\n\nIf `star_asked` is not `true` in `~/.ouroboros/prefs.json`, ask \"Ouroboros is\nfree and open-source. A GitHub star helps other developers discover it. Star\nthe repo?\" with **Star on GitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`)\nand **Skip for now**. After any answer, merge `star_asked: true` into the\nprefs file, keeping existing keys:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\n### Step 1: Environment Detection\n\n```bash\nouroboros_python --version\nwhich uvx 2>/dev/null && uvx --version 2>/dev/null\nwhich claude 2>/dev/null\nuv python list 2>/dev/null | grep \"cpython-3.1[2-9]\"\n```\n\nThe resolver already rejects Python below 3.12 and falls back to a uv-managed\ninterpreter; that does not make the `[claude-sdk]` and MCP 2 profiles\nimport-compatible. Report what was found, then:\n\n| Environment | Action |\n|:------------|:-------|\n| Python >= 3.12 + Claude CLI | Ready: configure `[claude]` SDK/MCP 1 and skills |\n| uvx + Python >= 3.12 | MCP-capable elsewhere: use a supported CLI-backed runtime setup for isolated `ouroboros-ai[mcp]` |\n| Python < 3.12 only | Run `uv python install 3.12`, then re-run `ooo setup` |\n| No package runner or Ouroboros package | Install uv (below), then re-run `ooo setup` |\n\nPrefer package managers for uv: `pipx install uv`, `pip install --user uv`, or\n`brew install uv`; the vendor one-liner\n`curl -LsSf https://astral.sh/uv/install.sh | sh` is the last resort.\n\n**IMPORTANT**: Never install `[mcp,claude]`, `[mcp,claude-sdk]`, or `[all,mcp]`\ntogether and never write a direct\n`ouroboros` or `python -m ouroboros` MCP fallback. MCP 2 launchers must use an\nisolated `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ...` or\n`pipx run --spec 'ouroboros-ai[mcp]' ...` process. Only `[mcp,claude-cli]` is\nsupported because the CLI worker is out of process. Do not write\nan Ouroboros entry to `~/.claude/mcp.json`; the plugin owns that registration.\n\n### Step 1.5: Runtime Configuration\n\nWrite the Claude runtime selection to `~/.ouroboros/config.yaml`. The welcome\ngate and the CLI read it; nothing else in this wizard writes it. This step\nnever touches `~/.claude/mcp.json`.\n\nDefine `ouroboros_cli` in the same shell as each command below (shell state\ndoes not persist between commands):\n\n```bash\nouroboros_cli() {\n  if command -v ouroboros >/dev/null 2>&1; then\n    command ouroboros \"$@\"\n  else\n    uvx --isolated --python '>=3.12' --from 'ouroboros-ai' ouroboros \"$@\"\n  fi\n}\nouroboros_cli config show orchestrator\nouroboros_cli config show llm\n```\n\nThe welcome gate is ready only when `orchestrator.runtime_backend` is `claude`\nor `claude_mcp` AND `llm.backend` is `claude`. A missing file or section\ncounts as not set.\n\n- Both conditions hold: already configured. Skip to Step 2.\n- `runtime_backend` is `claude_mcp` but `llm.backend` is not `claude`: run\n  `ouroboros_cli setup --runtime claude-cli --non-interactive` (keeps the CLI\n  transport).\n- `runtime_backend` is another runtime (for example `codex`): ask the user\n  whether to switch the default runtime to Claude. If they decline, keep the\n  existing configuration and skip to Step 2.\n- Otherwise (`runtime_backend` is `claude` with another `llm.backend`, no\n  config, no `orchestrator` section), or after the user agrees to switch, run:\n\n```bash\nouroboros_cli setup --runtime claude --non-interactive\n```\n\nBoth setup commands set `llm.backend: claude`; `--runtime claude` sets\n`orchestrator.runtime_backend: claude` and `--runtime claude-cli` sets `claude_mcp`.\nIf it fails, show the error and continue the wizard; Step 4 reports the\nruntime as not configured.\n\n### Step 2: MCP Profile Boundary\n\nTell the user: the default Claude SDK profile stays on MCP 1.x, and the\nplugin-owned MCP server runs MCP 2 separately with the `[claude-cli]` worker.\n**Do not create, update, or remove `~/.claude/mcp.json`.** Existing entries may\nbe user-managed or belong to another compatible runtime. Advanced MCP\nworkflows require a host-managed isolated `[mcp]` launcher, which the Claude\nmarketplace plugin or another supported host setup owns.\n\n### Step 3: CLAUDE.md Integration (Optional)\n\nOffer **Integrate / Skip / Preview first** for adding this ~40-line reference\nblock (pipeline, command table, agent catalog) to the project's CLAUDE.md. On\n**Preview first**, show it:\n\n````markdown\n<!-- ooo:START -->\n<!-- ooo:VERSION:0.59.8 -->\n# Ouroboros — Specification-First AI Development\n\n> Before telling AI what to build, define what should be built.\n> As Socrates asked 2,500 years ago — \"What do you truly know?\"\n> Ouroboros turns that question into an evolutionary AI workflow engine.\n\nMost AI coding fails at the input, not the output. Ouroboros fixes this by\n**exposing hidden assumptions before any code is written**.\n\n1. **Socratic Clarity** — Question until ambiguity ≤ 0.2\n2. **Ontological Precision** — Solve the root problem, not symptoms\n3. **Evolutionary Loops** — Each evaluation cycle feeds back into better specs\n\n```\nInterview → Seed → Execute → Evaluate\n    ↑                           ↓\n    └─── Evolutionary Loop ─────┘\n```\n\n## ooo Commands\n\nEach command loads its agent/MCP on-demand. Details in each skill file.\n\n| Command | Loads |\n|---------|-------|\n| `ooo` | — |\n| `ooo interview` | `ouroboros:socratic-interviewer` |\n| `ooo seed` | `ouroboros:seed-architect` |\n| `ooo run` | MCP required |\n| `ooo evolve` | MCP: `evolve_step` |\n| `ooo evaluate` | `ouroboros:evaluator` |\n| `ooo unstuck` | `ouroboros:{persona}` |\n| `ooo status` | MCP: `session_status` |\n| `ooo setup` | — |\n| `ooo help` | — |\n\n## Agents\n\nLoaded on-demand — not preloaded.\n\n**Core**: socratic-interviewer, ontologist, seed-architect, evaluator,\nadvocate, contrarian, judge\n**Support**: hacker, simplifier, researcher, architect\n<!-- ooo:END -->\n````\n\nOn **Integrate**: back up CLAUDE.md to CLAUDE.md.bak, append the block, and\nconfirm.\n\n### Step 4: Verification\n\nConfirm (with the Step 1.5 `config show` commands) that the saved Ouroboros\nconfig selects the default Claude Agent SDK runtime\non MCP 1.x while `~/.claude/mcp.json` was not mutated by this setup. The\ndependency-free Claude CLI worker remains a distinct, explicit `[claude-cli]`\nselection for the isolated MCP 2 process.\n\n### Step 5: Success Summary\n\n```\nOuroboros Setup Complete!\n\nMode:                     Claude Agent SDK (MCP 1.x)\nMCP Server:               Host-owned (config not mutated)\nCLAUDE.md:                <integrated | skipped>\n\nNext: ooo interview \"your project idea\" | ooo tutorial | ooo help\n```\n\n### Step 5.1: Model Choice (Claude Code)\n\nOffer optional model control. Ask \"설정이 완료됐어요. 기본 모델 설정으로 바로\n시작할 수 있고, 모델은 언제든 나중에 바꿀 수 있어요.\" (header `모델 설정`):\n\n- **바로 시작하기 (권장)**: 기본 모델 설정으로 바로 작업을 시작해요. Continue to Step 5.5.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. In the local Claude Code\n  harness it opens the settings UI in the user's browser at a temporary\n  `localhost` address. They can reopen it any time with `ooo config`; this\n  choice never permanently locks a model.\n\n### Step 5.5: Brownfield Repository Scan\n\nRegister existing git repositories and linked worktrees in the Ouroboros DB so\ninterviews can use them as brownfield context. Use the MCP tool only, not the\nCLI or Python scripts.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros brownfield\"` for `ouroboros_brownfield` (both the scan and the later `set_defaults` call). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent, skip this step and continue to Step 6.\n\n1. Scan and register:\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"scan\" }\n   ```\n   The walk starts at `scan_root` (default: the user's home directory) and\n   goes at most two directory levels deep, skipping dot-prefixed and noisy\n   directories such as `node_modules`. Normal repos (`.git` directory) and\n   linked worktrees (`.git` file) reached by the walk are registered self-only.\n   Git worktree families are not expanded. Repos with no remote or any remote\n   name are eligible. Existing defaults are preserved.\n\n2. The scan response `text` already holds a numbered list with default\n   markers. **Do NOT make any additional MCP calls to list or query repos.**\n   Show every repo in a plain-text two-column grid inside a code block (not a\n   markdown table), keeping the `*` default markers exactly as returned:\n\n   ```\n   Scan complete. 8 repositories registered.\n\n    1. repo-alpha                   5. repo-epsilon\n    2. repo-bravo *                 6. repo-foxtrot\n   ```\n\n   If no repos were found, skip to Step 6.\n\n3. **Do NOT use the active runtime's `ask_user` dialog for this selection.** Text emitted between\n   tool calls is not guaranteed to render, so a dialog can appear without the\n   list, and option previews truncate long lists. Instead, end the turn with the repo grid as the final message, followed by the prompt:\n\n   - Defaults exist: `Current defaults: <names> (numbers <numbers>)`, then\n     `Reply with repo numbers to change defaults (e.g. \"6, 18, 19\"), \"keep\" to keep the current defaults, or \"none\" to clear them.`\n   - No defaults: `No defaults set. Reply with repo numbers to set defaults (e.g. \"6, 18, 19\"), or \"none\" to run interviews in greenfield mode.`\n\n4. On the next turn: numbers (any separator) select those IDs; \"keep\" skips\n   the MCP call and leaves defaults unchanged; \"none\" clears all; anything else\n   gets the prompt again (never guess). Then make ONE call that replaces all\n   defaults (`\"indices\": \"\"` for none):\n\n   ```\n   Tool: ouroboros_brownfield\n   Arguments: { \"action\": \"set_defaults\", \"indices\": \"<comma-separated IDs>\" }\n   ```\n\n   Confirm the resulting defaults, or that interviews will run in greenfield\n   mode, and mention that `ooo setup` or `ooo brownfield` changes them later.\n\n### Step 6: First Project Nudge\n\nSuggest `ooo interview \"Build a CLI tool for [something you need]\"` or\n`ooo tutorial`.\n\n## Uninstall\n\nOn `--uninstall`, ask for confirmation, explaining that it removes only the\nOuroboros block from CLAUDE.md, not plugin files, seeds, or project data. If\nconfirmed:\n1. Leave `~/.claude/mcp.json` untouched\n2. Remove `<!-- ooo:START -->` to `<!-- ooo:END -->` block from CLAUDE.md (if exists)\n3. Confirm: \"Ouroboros plugin configuration removed. To remove plugin files, run: claude plugin uninstall ouroboros\"\n\n## Setup Troubleshooting\n\n- **\"No compatible Python found\"**: plugin mode works without a global Python\n  when uv is on PATH. Otherwise install Python 3.12 (`brew install\n  python@3.12`, `sudo apt install python3.12`, or python.org/downloads).\n- **\"uvx: command not found\"**: uvx is recommended, not required. For the\n  default Claude SDK runtime, `pip install 'ouroboros-ai[claude]'`\n  (`[claude-sdk]` is an explicit alias). Use `[claude-cli]` only for the\n  isolated MCP 2 server worker. Never combine `[claude]`, `[claude-sdk]`, or\n  `[all]` with `[mcp]`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"setup","description":"Guided onboarding wizard for Ouroboros setup","disable-model-invocation":true,"disableModelInvocation":true},"isInternal":false,"tokens":4027,"sizeBytes":14703},{"name":"SKILL.md","path":"skills/status/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/status/SKILL.md","title":"ouroboros-status","category":"anthropic-skill","format":"markdown","content":"---\nname: ouroboros-status\ndescription: \"Check session status and measure goal drift\"\naliases: [drift]\nmcp_tool: ouroboros_session_status\nmcp_args:\n  session_id: \"$1\"\n---\n\n# /ouroboros:ouroboros-status\n\nCheck an execution session's status and, on request, measure drift from the Seed goal.\n\n```\n/ouroboros:ouroboros-status [session_id]\n```\n\n## Instructions\n\n### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros session status\"` for `ouroboros_session_status` and `ouroboros_measure_drift`. A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. Use the fallback only when the tool is genuinely absent.\n\n### Steps\n\n1. Session: use the given `session_id`, else the most recent one in the conversation, else ask the user.\n\n2. Call `ouroboros_session_status` MCP tool:\n   ```\n   Tool: ouroboros_session_status\n   Arguments:\n     session_id: <session ID>\n   ```\n\n3. If the user asks about drift (or says \"am I drifting?\"), also call `ouroboros_measure_drift`:\n   ```\n   Tool: ouroboros_measure_drift\n   Arguments:\n     session_id: <session ID>\n     current_output: <current execution output or file contents>\n     seed_content: <original seed YAML>\n     constraint_violations: []  (any known violations)\n     current_concepts: []       (concepts in current output)\n   ```\n\n4. Show the status and progress, and the drift report as the tool renders it (weights, threshold, breakdown, suggestions). When combined drift exceeds 0.3 (status `EXCEEDED`), warn and suggest `ooo interview` to re-clarify or `ooo evolve` to course-correct; otherwise suggest continuing with `ooo run` or `ooo evaluate`.\n\n## Fallback (no MCP server)\n\nTell the user session tracking needs the Ouroboros MCP server (`ooo setup`), and that without it they can compare the implementation against the Seed by hand.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"ouroboros-status","description":"Check session status and measure goal drift","aliases":["drift"],"mcp_tool":"ouroboros_session_status","mcp_args":{"session_id":"$1"}},"isInternal":false,"tokens":597,"sizeBytes":2449},{"name":"SKILL.md","path":"skills/tutorial/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/tutorial/SKILL.md","title":"tutorial","category":"anthropic-skill","format":"markdown","content":"---\nname: tutorial\ndescription: \"Interactive tutorial teaching Ouroboros hands-on\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:tutorial\n\nInteractive tutorial that teaches Ouroboros through hands-on experience.\n\n## Usage\n\n```\nooo tutorial\n/ouroboros:tutorial\n```\n\n## Principles\n\n1. Show something useful in the first 30 seconds.\n2. Learn by doing: the user answers questions about their own idea.\n3. Reveal features gradually.\n4. Always end a phase with one specific next action.\n5. Match the audience: technical users get the run, evaluate, and evolve\n   details; non-technical users get the interview and plain language.\n\n## Flow (about 5 minutes)\n\n1. **Hook.** Promise that in five minutes their vague idea becomes a precise\n   specification, then ask what they want to build. If they have no idea, use a\n   task-management CLI as the example.\n2. **Interview.** Ask 3-4 Socratic questions about their idea (the problem it\n   solves, the main users, the one feature that makes it useful now). Point out\n   that each answer surfaced an assumption they had not stated.\n3. **Mini-Seed.** Summarize their answers in Seed vocabulary:\n\n   ```\n   Goal: <their goal, refined>\n   Constraints: <2-3 constraints they named>\n   Acceptance criteria: <2-3 checkable outcomes>\n   ```\n\n   Do not invent an ambiguity score. Explain that `ooo interview` measures\n   ambiguity and continues until it is low enough to freeze a real Seed.\n4. **The workflow.** `Interview → Seed → Execute → Evaluate`, with evaluation\n   feeding back into the next Seed generation:\n\n   ```\n   ooo interview \"your idea\"   # expose assumptions\n   ooo seed                    # freeze the Seed\n   ooo run                     # execute it\n   ooo evaluate                # verify against the acceptance criteria\n   ooo status                  # check drift\n   ```\n\n   `ooo unstuck` helps when blocked. `run`, `evaluate`, `evolve`, and `status`\n   need the Ouroboros MCP server (`ooo setup`).\n5. **Next step.** Offer: start a real project (`ooo interview \"your actual\n   project idea\"`), the full reference (`ooo help`), or setup (`ooo setup`).\n\nIf the user asks how this differs from prompting an AI assistant directly:\nwithout a spec, the assistant guesses and you rewrite the prompt until it\nmatches; with Ouroboros, the interview exposes hidden assumptions first, so the\nbuild starts from an agreed Seed. If it seems complicated, three commands cover\nmost use: `ooo interview`, `ooo seed`, `ooo run`.\n\nThe tutorial is done when the user has experienced the interview, understands\nwhat a Seed is, and has chosen a next step.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"tutorial","description":"Interactive tutorial teaching Ouroboros hands-on","disable-model-invocation":true,"disableModelInvocation":true},"isInternal":false,"tokens":693,"sizeBytes":2961},{"name":"SKILL.md","path":"skills/unstuck/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/unstuck/SKILL.md","title":"unstuck","category":"anthropic-skill","format":"markdown","content":"---\nname: unstuck\ndescription: \"Use when the user is stuck or going in circles: the same fix failed twice or more, 'nothing works', 'I've tried everything', or a consequential choice with no clear winner that is hard to undo or splits the team (which database, which architecture). Brings hacker, researcher, simplifier, architect, and contrarian perspectives and converges on one recommendation. Not for a first error or normal progress.\"\naliases: [stuck, lateral]\n---\n\n# /ouroboros:unstuck\n\nBreak through stagnation, or advise on a hard choice, with lateral thinking personas. **Solo** runs one persona; **debate** runs several in parallel and synthesizes them.\n\n## Usage\n\n```\nooo lateral                       # debate: all 5 lateral personas\nooo lateral <persona>             # solo: one persona\nooo lateral debate <p1> <p2> ...  # debate with explicit members\nooo lateral @all                  # debate preset (the only preset)\n```\n\n## Personas (lateral pool)\n\nStateless reframing lenses only; stateful roles (evaluator, qa-judge, ontologist, socratic-interviewer) have their own skills.\n\n| Persona | Lens | Use when |\n|---------|------|----------|\n| **hacker** | Make it work first, elegance later | Overthinking blocks progress |\n| **researcher** | What information are we missing? | The problem is unclear |\n| **simplifier** | Cut scope, return to MVP | Complexity is overwhelming |\n| **architect** | Restructure the approach entirely | The current design is wrong |\n| **contrarian** | Are we solving the wrong problem? | Assumptions need challenging |\n\nBesides direct `ooo lateral`, you MAY chain into this skill from another skill (for example as `socratic-interviewer` in `ooo interview`) when the current question needs multi-perspective deliberation; afterwards summarize the options, return to the parent flow, and let the user decide.\n\n## Instructions\n\n### Step 1: Parse args into a mode\n\n| Input | Mode | Members |\n|---|---|---|\n| no args, `debate`, or `@all` | debate | all 5 personas |\n| `<persona>` | solo | that persona |\n| `debate <p1> <p2> ...` | debate | the listed personas |\n| `@<unknown-preset>` | error | reject and list known presets |\n| `<unknown-persona>` | error | reject and list the 5 personas |\n| `<p1> <p2> ...` without `debate` | error | reject and suggest `ooo lateral debate <p1> <p2>` |\n\nValidate every persona name against the pool; never coerce silently. When a parent skill wants one persona but names none, omit `persona` and pass `stagnation_pattern` (`spinning`, `oscillation`, `no_drift`, `diminishing_returns`) if known; the server picks the persona (default contrarian).\n\nPick the lateral **mode** too. Use `mode=\"decision\"` when the user faces a consequential choice between options (which database, which architecture) rather than a stall; otherwise omit `mode` (default `unstuck`). In decision mode, `problem_context` describes the options and `current_approach` the currently favored one (or `undecided`), and an omitted persona means a full debate. Pass `research=true` only when the user explicitly asks for web-grounded research; it is slower and never the default.\n\n### Step 2: Gather required context before the MCP call\n\nThe tool hard-fails when `problem_context` or `current_approach` is empty, so resolve both first (solo and debate alike):\n\n1. Reuse session state from the parent skill or recent conversation: `problem_context` (what the user is stuck on, 1-3 sentences), `current_approach` (what was tried; `\"none yet, first attempt\"` is fine), and optional `failed_attempts`.\n2. If either field is unrecoverable, ask the user one combined question with the active runtime's `ask_user` capability: \"Two things I need before lateral thinking can run: (1) what are you stuck on right now, (2) what have you already tried? A sentence each is enough.\" Wait for the answer. Never fabricate these fields; `current_approach=\"not specified\"` is acceptable, invented content is not.\n\n### Step 3: Always call `ouroboros_lateral_think`\n\nEvery invocation routes through the MCP tool, solo and debate, in every runtime; never substitute a direct subagent fan-out.\n\n#### Loading MCP tools (deferred-schema guard)\n\nOuroboros tools may be deferred, and a schema loaded on one turn can unload by the next. Immediately before each `ouroboros_*` call, load it with the active runtime's tool-discovery capability: `\"+ouroboros lateral\"` for `ouroboros_lateral_think`; `\"+ouroboros conductor decision\"` for `ouroboros_record_conductor_decision` (decision mode). A call whose schema is not loaded fails with \"Invalid tool parameters\". If the tool is already callable, discovery is a no-op and an empty result is expected. If the tool is genuinely absent (neither exposed nor loadable), stop and report that the MCP dispatch surface is broken; do not improvise solo or debate without it.\n\nCall it with:\n- **Solo**: `persona=<one>`, `problem_context`, `current_approach`, `failed_attempts`.\n- **Debate**: `personas=[...]`, `problem_context`, `current_approach`, `failed_attempts`.\n- Plus `mode`/`research` from Step 1, and `session_id` when running inside an interview or lateral session (it binds the fan-out so results submitted from another session are refused).\n\n### Step 4: Act on the response shape (the server picks it)\n\n| Mode | Plugin response | Inline response |\n|---|---|---|\n| Solo | one `_subagent` object | one `# Lateral Thinking: <approach>` block in `content` |\n| Debate | `_subagents` array (N objects) | N blocks joined by `\\n\\n---\\n\\n`, plus a hidden dispatch block carrying the same N payloads |\n\n**Inline dispatch block (debate, inline only).** Prefer the structured copy in the response meta when present. Otherwise take the text between `<!-- ouroboros-lateral-inline-dispatch-v1 base64\\n` and `\\n-->` at the end of `content`, base64-decode it, and parse the JSON. A host that did not declare subagent capability receives the neutral shape:\n\n```json\n{\"dispatch_mode\": \"host_decides\", \"host_action\": \"dispatch_subagents_if_supported\", \"execution_preference\": \"parallel\", \"fallback_strategy\": \"sequential\", \"persona_count\": N, \"payloads\": [...]}\n```\n\nAn explicitly sequential execution authority receives `dispatch_mode=\"sequential\"` with `legacy_dispatch_mode=\"inline_fallback\"`, which is compatibility metadata only. Never split the joined display text on `---`: user content can contain the separator.\n\n#### Shape A: plugin response (OpenCode plugin mode)\n\nThe plugin spawns the children itself. Await the single `_subagent` result (solo) or all `_subagents` results (debate), then present or synthesize. If the response is inline text with neither key, you are not in plugin mode: use Shape B.\n\n#### Shape B: inline response\n\nThe dispatch block distinguishes declared `host_driven`, capability-neutral `host_decides`, and explicit `sequential` execution. **Solo**: present the approach summary, reframing prompt, and questions to consider, then route back to the workflow.\n\n##### Debate, runtime supports sub-agent dispatch\n\n1. Show the visible markdown under a short \"what the lateral toolkit suggests\" header.\n2. With `host_action=\"spawn_subagents\"`, or `host_action=\"dispatch_subagents_if_supported\"` when the runtime has a native parallel primitive, use the active runtime's `orchestrate_subagents` capability: one isolated child per payload, launched together, each given its `prompt` verbatim plus its `context`.\n3. Await all children and correlate each result by `result_correlation_key` (normally `context.persona`).\n4. Optional Round 2 cross-attack, only when Round 1 answers diverge: give each persona short summaries of the others and ask \"Identify one weakness in each. 200 words max.\"\n5. Synthesize (below).\n\n##### Debate, constrained runtime without sub-agent dispatch\n\nIf the response is stamped with `dispatch_mode=\"sequential\"`, or with `dispatch_mode=\"host_decides\"` and the host has no native parallel primitive, process each recovered payload in order, correlate every result by `result_correlation_key`, and synthesize after the last one. If no payloads are recoverable (no meta copy and no dispatch block), present the handler's markdown as-is and synthesize from that text; there is no Round 2.\n\n##### Synthesize (debate, all shapes)\n\nIn decision mode, follow the synthesis contract the response carries: exactly one recommendation stated first, its grounds (citing only sources personas actually fetched), the strongest dissent, and flip conditions. After the user accepts, offer to persist it with `ouroboros_record_conductor_decision` as the contract describes.\n\nIn unstuck mode, present options, not a verdict:\n\n```\n## Debate result: N personas\n\n### Options\n- **Option A** (from <persona>): <one-liner>\n- **Option B** (from <persona>): <one-liner>\n\n### Disagreements\n- <persona X> vs <persona Y>: <what they disagree about>\n\n### Recommended (with reasoning)\n<your single best read, labeled as your recommendation>\n```\n\nIn both modes the choice is the user's: never auto-progress to the next workflow step on their behalf.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"unstuck","description":"Use when the user is stuck or going in circles: the same fix failed twice or more, 'nothing works', 'I've tried everything', or a consequential choice with no clear winner that is hard to undo or splits the team (which database, which architecture). Brings hacker, researcher, simplifier, architect, and contrarian perspectives and converges on one recommendation. Not for a first error or normal progress.","aliases":["stuck","lateral"]},"isInternal":false,"tokens":2178,"sizeBytes":9379},{"name":"SKILL.md","path":"skills/update/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/update/SKILL.md","title":"update","category":"anthropic-skill","format":"markdown","content":"---\nname: update\ndescription: \"Check for updates and upgrade Ouroboros to the latest version\"\n---\n\n# /ouroboros:update\n\nUpgrade Ouroboros without changing the installation's manager, environment, or optional-dependency profile.\n\n```\nooo update\n/ouroboros:update\n```\n\n## Instructions\n\nThe native command is the single source of truth. Run it with the active runtime's `run_shell` capability.\n\n1. Run `ouroboros update --check`.\n   - **Up to date**: report the package result together with any Codex plugin version mismatch or unknown-status warning, then stop. Do not infer that every integration is current from the package version.\n   - **Update available**: ask the user (active runtime's `ask_user` capability) to choose **Update now** or **Skip**. On **Update now**, run `ouroboros update --yes`. When the user actively uses both Claude Code and Codex, run `ouroboros update --yes --runtime all` instead; it refreshes both host integrations without changing the configured execution backend. Show the command's result.\n\n2. If the check fails but `ouroboros update --help` works, report the native error and stop. Never substitute a manual upgrade, and never infer ownership from `uv tool list`, `pipx list`, PATH order, directory names, or the active agent runtime.\n\n3. If `ouroboros update --help` does not work, this is a legacy install that predates the receipt-bound updater. Fail closed: only a read-only `ouroboros --version` is allowed. Explain that the original manager, environment, and extras cannot be proven, and ask the user to rerun their exact original install command (including its `ouroboros-ai[...]` extras and custom manager root), or to do a fresh isolated install if they do not know it. Run no package upgrade, plugin refresh, or setup command on this path.\n\n4. After a successful update, relay the command's restart guidance (Claude may use `/reload-plugins` or restart; active Codex sessions need a restart) and any Codex plugin version diagnostic. A mismatch is advisory; preserve existing marketplace refs rather than automatically removing or advancing a pin. If project instruction content needs regeneration, suggest `ooo setup`; never edit project instruction files as part of the update.\n\nThe updater replays the environment's install receipt, so the Claude SDK and MCP 2 profiles are never combined or substituted. Other options: `--dry-run`, `--prerelease`; see `ouroboros update --help`.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"update","description":"Check for updates and upgrade Ouroboros to the latest version"},"isInternal":false,"tokens":623,"sizeBytes":2793},{"name":"SKILL.md","path":"skills/welcome/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/welcome/SKILL.md","title":"welcome","category":"anthropic-skill","format":"markdown","content":"---\nname: welcome\ndescription: \"First-touch experience for new Ouroboros users\"\ndisable-model-invocation: true\n---\n\n# /ouroboros:welcome\n\nInteractive onboarding for new Ouroboros users.\n\n## Usage\n\n```\n/ouroboros:welcome              # First-time or update onboarding\n/ouroboros:welcome --skip       # Skip welcome, mark as shown\n/ouroboros:welcome --force      # Force re-run welcome even if shown\n```\n\n## Instructions\n\nAsk every question with the active runtime's `ask_user` capability, in the\nuser's language. The Korean labels below are the canonical wording.\n\n### Python Runtime (Required)\n\nDefine this resolver in the same shell before any snippet below. It accepts\nonly Python 3.12 or newer (`python3`, then `python`, then uv) and preserves\narguments and stdin. Quote every argument passed to `ouroboros_python`.\n\n<!-- ouroboros-python-resolver:start -->\n```bash\nouroboros_python() {\n  if command -v python3 >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 \"$@\")\n    return\n  fi\n  if command -v python >/dev/null 2>&1 &&\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1\n  then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python \"$@\")\n    return\n  fi\n  if command -v uv >/dev/null 2>&1; then\n    (unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python \"$@\")\n    return\n  fi\n  printf '%s\\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2\n  return 127\n}\n```\n<!-- ouroboros-python-resolver:end -->\n\n### Pre-Check: Already Completed?\n\nRun the resolver, this section's blocks, and the migration check below in one\nshell call, then print the result with\n`printf 'completed=%s setup=%s codex=%s migration=%s\\n' \"$WELCOME_COMPLETED\" \"${SETUP_READY:-}\" \"${CODEX_READY:-}\" \"${LEGACY_CODEX_MODEL_MIGRATION_REQUIRED:-}\"`.\n\nRead the completion marker (legacy `welcomeShown: true` also counts):\n\n```bash\nWELCOME_COMPLETED=$(ouroboros_python - <<'PY'\nimport json, os\ntry:\n    prefs = json.load(open(os.path.expanduser('~/.ouroboros/prefs.json'), encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprint(prefs.get('welcomeCompleted') or ('legacy-welcomeShown' if prefs.get('welcomeShown') else ''))\nPY\n)\n```\n\nBefore honoring that completion marker, determine whether setup is ready for\nthe active runtime.\nA previously completed welcome must never hide the setup gate from a user who\nchose **나중에** or whose setup was later removed.\n\nClaude Code is ready when `~/.ouroboros/config.yaml` has\n`orchestrator.runtime_backend` in `{claude, claude_mcp}` and `llm.backend:\nclaude`. The marketplace plugin owns its MCP registration, so host-owned\n`~/.claude/mcp.json` is never part of readiness:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  SETUP_READY=\"true\"\nfi\n```\n\nIf `SETUP_READY` is not true, check Codex. It is ready when both backends are\n`codex`, the Codex CLI (`OUROBOROS_CODEX_CLI_PATH`, else\n`orchestrator.codex_cli_path`, else `codex` on PATH) is runnable, and\n`mcp_servers\\.ouroboros` in `$CODEX_HOME/config.toml` (any TOML key spelling)\nhas a runnable `command` or a non-blank `url`:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  CODEX_READY=\"true\"\nfi\n```\n\n### Legacy Codex Model Migration\n\nOlder configurations saved `gpt-5` into all four stage-model fields. That is\nnow an explicit pin that stops Codex App/CLI model changes from taking effect.\nNever rewrite a possible user pin silently. When Codex is ready, detect that\nexact legacy shape (or an interrupted migration) once:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$HOME/.ouroboros/prefs.json\" <<'PY'\nfrom __future__ import annotations\n\nimport json\nimport sys\nfrom pathlib import Path\n\nconfig_path, prefs_path = map(Path, sys.argv[1:])\n\ndef yaml_mapping(source: str) -> dict[str, dict[str, str]]:\n    parsed: dict[str, dict[str, str]] = {}\n    section: str | None = None\n    for raw_line in source.splitlines():\n        if not raw_line.strip() or raw_line.lstrip().startswith(\"#\"):\n            continue\n        indent = len(raw_line) - len(raw_line.lstrip())\n        key, separator, raw_value = raw_line.strip().partition(\":\")\n        if not separator:\n            continue\n        value = raw_value.strip().split(\" #\", 1)[0].strip().strip(\"'\\\"\")\n        if indent == 0:\n            section = key.strip(\"'\\\"\")\n            parsed.setdefault(section, {})\n        elif section is not None:\n            parsed[section][key.strip(\"'\\\"\")] = value\n    return parsed\n\ntry:\n    config = yaml_mapping(config_path.read_text(encoding=\"utf-8\"))\nexcept OSError:\n    raise SystemExit(1)\ntry:\n    prefs = json.loads(prefs_path.read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\n\nstage_values = (\n    config.get(\"clarification\", {}).get(\"default_model\"),\n    config.get(\"execution\", {}).get(\"default_model\"),\n    config.get(\"evaluation\", {}).get(\"semantic_model\"),\n    config.get(\"resilience\", {}).get(\"reflect_model\"),\n)\nlegacy_gpt5 = all(value == \"gpt-5\" for value in stage_values)\npartial_automatic_migration = (\n    any(value == \"gpt-5\" for value in stage_values)\n    and any(value == \"default\" for value in stage_values)\n    and all(value in {\"gpt-5\", \"default\"} for value in stage_values)\n)\nhandled = prefs.get(\"codexModelMigration\") in {\"automatic-v1\", \"kept-gpt-5-v1\"}\nraise SystemExit(0 if (legacy_gpt5 or partial_automatic_migration) and not handled else 1)\nPY\nthen\n  LEGACY_CODEX_MODEL_MIGRATION_REQUIRED=\"true\"\nfi\n```\n\nIf `CODEX_READY` and `LEGACY_CODEX_MODEL_MIGRATION_REQUIRED` are both true, ask\n\"현재 설정은 모든 단계에서 gpt-5를 고정해 두고 있어요. Codex에서 선택한 모델을 자동으로 사용하도록 바꿀까요?\"\n(header `모델 설정`) with these options:\n\n- **Codex 선택으로 전환하기 (권장)**: App이나 CLI에서 바꾼 모델을 모든 단계가 자동으로 따라가요.\n  Atomically rewrite the four pins:\n\n```bash\nouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nfrom __future__ import annotations\n\nimport os\nimport sys\nimport tempfile\nfrom pathlib import Path\n\npath = Path(sys.argv[1])\noriginal = path.read_text(encoding=\"utf-8\")\nreplacements = {\n    (\"clarification\", \"default_model\"): \"default\",\n    (\"execution\", \"default_model\"): \"default\",\n    (\"evaluation\", \"semantic_model\"): \"default\",\n    (\"resilience\", \"reflect_model\"): \"default\",\n}\nseen: set[tuple[str, str]] = set()\nsection: str | None = None\noutput: list[str] = []\nfor line in original.splitlines(keepends=True):\n    stripped = line.strip()\n    indent = len(line) - len(line.lstrip())\n    key = stripped.split(\":\", 1)[0].strip(\"'\\\"\") if \":\" in stripped else \"\"\n    if indent == 0 and \":\" in stripped:\n        section = key\n    target = (section or \"\", key)\n    if indent > 0 and target in replacements:\n        newline = \"\\n\" if line.endswith(\"\\n\") else \"\"\n        prefix = line[:indent]\n        comment = \"\"\n        value_part = line.strip().split(\":\", 1)[1]\n        if \" #\" in value_part:\n            comment = \" #\" + value_part.split(\" #\", 1)[1].rstrip(\"\\n\")\n        output.append(f\"{prefix}{key}: {replacements[target]}{comment}{newline}\")\n        seen.add(target)\n    else:\n        output.append(line)\nmissing = set(replacements) - seen\nif missing:\n    raise SystemExit(f\"Cannot migrate Codex model pins; missing keys: {sorted(missing)}\")\nupdated = \"\".join(output)\nfd, tmp_name = tempfile.mkstemp(prefix=\".config.yaml.\", dir=str(path.parent))\ntry:\n    with os.fdopen(fd, \"w\", encoding=\"utf-8\") as tmp:\n        tmp.write(updated)\n        tmp.flush()\n        os.fsync(tmp.fileno())\n    os.replace(tmp_name, path)\nfinally:\n    try:\n        os.unlink(tmp_name)\n    except FileNotFoundError:\n        pass\nPY\n```\n\n  `default` sends no model pin to Codex; it is not a model named \"default\".\n  Confirm the rewrite succeeded before recording the decision. An interrupted\n  rewrite leaves a partial `gpt-5`/`default` state that the next check offers\n  again.\n- **gpt-5 고정 유지하기**: 지금처럼 모든 단계를 gpt-5로 계속 실행해요. Do not\n  change `config.yaml`.\n\nFor either choice, merge exactly one `codexModelMigration` marker into\n`~/.ouroboros/prefs.json`, keeping existing keys:\n\n```bash\nouroboros_python - \"automatic-v1\" <<'PY'\nimport json, os, sys\npath = os.path.expanduser('~/.ouroboros/prefs.json')\ntry:\n    prefs = json.load(open(path, encoding='utf-8'))\nexcept Exception:\n    prefs = {}\nif not isinstance(prefs, dict):\n    prefs = {}\nprefs['codexModelMigration'] = sys.argv[1]\nos.makedirs(os.path.dirname(path), exist_ok=True)\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nPass `kept-gpt-5-v1` instead of `automatic-v1` for the keep choice. If welcome\nwas already completed, confirm briefly and exit; do not also ask the generic\nwelcome question.\n\n### Routing After the Pre-Check\n\n- **Completed, `SETUP_READY` or `CODEX_READY` true, no `--force`**: ask\n  \"Ouroboros welcome was already completed on $WELCOME_COMPLETED. What would\n  you like to do?\" with **Skip** (continue to work, recommended; exit) and\n  **Re-run welcome** (continue to Step 1).\n- **Completed but neither ready**: skip that prompt and go to the Setup Gate.\n- **`--skip`**: write the completion prefs (Step 4), print\n  `Ouroboros welcome skipped. Run /ouroboros:welcome --force to re-run onboarding.`,\n  and exit.\n\n### Setup Gate: First Use\n\nUse the readiness the Pre-Check printed; a global `config.yaml` alone is not\nenough unless it names a runtime these gates recognize. To recheck after a\nsetup run (or when the Pre-Check did not run), use these standalone gates,\nwhich print their verdict. Claude Code:\n\n```bash\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" <<'PY'\nimport sys\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ntry:\n    config = load_yaml(sys.argv[1])\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") in {\"claude\", \"claude_mcp\"}\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"claude\"\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"SETUP_READY\"\nelse\n  echo \"SETUP_REQUIRED\"\nfi\n```\n\nIf that printed `SETUP_READY`, skip the Codex gate and continue to Step 1.\nOtherwise check Codex:\n\n```bash\nCODEX_HOME_DIR=\"${CODEX_HOME:-$HOME/.codex}\"\ncase \"$CODEX_HOME_DIR\" in\n  \"~\") CODEX_HOME_DIR=\"$HOME\" ;;\n  \"~/\"*) CODEX_HOME_DIR=\"$HOME/${CODEX_HOME_DIR#\"~/\"}\" ;;\nesac\nif ouroboros_python - \"$HOME/.ouroboros/config.yaml\" \"$CODEX_HOME_DIR/config.toml\" <<'PY'\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom pathlib import Path\n\ntry:\n    import yaml\nexcept ModuleNotFoundError:\n    yaml = None\n\n\ndef scalar(raw: str) -> str:\n    return raw.strip().split(\" #\", 1)[0].strip().rstrip(\",}\").strip().strip(\"'\\\"\")\n\n\ndef load_yaml(path: str) -> dict:\n    source = Path(path).read_text(encoding=\"utf-8\")\n    if yaml is not None:\n        loaded = yaml.safe_load(source) or {}\n        return loaded if isinstance(loaded, dict) else {}\n    parsed: dict[str, dict[str, str]] = {}\n    section = None\n    for line in source.splitlines():\n        if not line.strip() or line.lstrip().startswith(\"#\"):\n            continue\n        key, separator, value = line.strip().partition(\":\")\n        if not separator:\n            continue\n        key = key.strip(\"'\\\"\")\n        if not line[0].isspace():\n            section = key\n            parsed[section] = {}\n            flow = value.strip().split(\" #\", 1)[0].strip()\n            if flow.startswith(\"{\") and flow.endswith(\"}\"):\n                for part in flow[1:-1].split(\",\"):\n                    field, separator, field_value = part.partition(\":\")\n                    if separator:\n                        parsed[section][field.strip().strip(\"'\\\"\")] = scalar(field_value)\n        elif section is not None:\n            parsed[section][key] = scalar(value)\n    return parsed\n\n\ndef runnable(candidate: str) -> bool:\n    value = candidate.strip()\n    if not value:\n        return False\n    if \"/\" not in value:\n        return shutil.which(value) is not None\n    path = Path(value).expanduser()\n    return path.is_file() and os.access(path, os.X_OK)\n\n\ndef mcp_ready(entry: object) -> bool:\n    if not isinstance(entry, dict):\n        return False\n    command, url = entry.get(\"command\"), entry.get(\"url\")\n    if isinstance(command, str) and command.strip():\n        return runnable(command)\n    return isinstance(url, str) and bool(url.strip())\n\n\ntry:\n    config = load_yaml(sys.argv[1])\n    codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding=\"utf-8\"))\nexcept (OSError, ValueError):\n    raise SystemExit(1)\norchestrator, llm = config.get(\"orchestrator\"), config.get(\"llm\")\nservers = codex_config.get(\"mcp_servers\")\ncli_path = os.environ.get(\"OUROBOROS_CODEX_CLI_PATH\")\nif not cli_path and isinstance(orchestrator, dict):\n    cli_path = orchestrator.get(\"codex_cli_path\")\nif not isinstance(cli_path, str) or not cli_path.strip():\n    cli_path = \"codex\"\nready = (\n    isinstance(orchestrator, dict)\n    and orchestrator.get(\"runtime_backend\") == \"codex\"\n    and isinstance(llm, dict)\n    and llm.get(\"backend\") == \"codex\"\n    and runnable(cli_path)\n    and mcp_ready(servers.get(\"ouroboros\") if isinstance(servers, dict) else None)\n)\nraise SystemExit(0 if ready else 1)\nPY\nthen\n  echo \"CODEX_READY\"\nelse\n  echo \"CODEX_SETUP_REQUIRED\"\nfi\n```\n\nIf neither is ready (`SETUP_REQUIRED` and `CODEX_SETUP_REQUIRED`, including a\nconfig that names a runtime neither gate recognizes), ask\n\"Ouroboros를 처음 사용하시네요. 시작하기 전에 실행 환경을 설정할까요?\"\n(header `Ouroboros 시작하기`):\n\n- **설정하고 시작하기 (권장)**: 한 번만 설정하면 바로 사용할 수 있어요. Run the\n  setup for the active host yourself; never ask the user to copy a command the\n  host can run. In Codex App or Codex CLI, run `ouroboros setup --runtime codex`\n  when the executable is installed. For a Marketplace-plugin-only install run\n  `uvx --isolated --python '>=3.12' --from 'ouroboros-ai[mcp]' ouroboros setup --runtime codex`\n  instead. In Claude Code, follow `../setup/SKILL.md`.\n- **나중에**: 지금은 기본 안내만 보고 나중에 설정할게요. Continue the welcome\n  flow without claiming MCP-backed features are ready.\n\nAfter a successful **Codex** setup, ask \"설정이 완료됐어요. 기본적으로 Codex에서\n선택한 모델을 사용합니다. 모델은 언제든 나중에 바꿀 수 있어요.\" (header `준비 완료`):\n\n- **바로 시작하기 (권장)**: 기본 모델로 바로 작업을 시작해요. Continue to Step 1.\n- **직접 모델 설정하기**: 단계별로 모델을 바꾸거나 목록에 없는 모델 ID를 입력해\n  고정해요. Read and follow `../config/SKILL.md`. On the user's local Codex App\n  or CLI it opens the settings UI in their browser at a\n  temporary `localhost` address (not an external website). It offers **Use Codex default model** and\n  **Enter another model ID…** for a deliberate stage pin. Continue to Step 1\n  when the settings session ends.\n\nIn Claude Code, `../setup/SKILL.md` asks the equivalent model question itself;\ndo not ask it again. Do not show this gate again once a runtime is ready; the\nsettings UI stays available through `ooo config`.\n\n### Step 1: Banner\n\n```\nWelcome to Ouroboros!\n\nMost AI coding fails at the input, not the output.\nOuroboros exposes hidden assumptions BEFORE any code is written.\n\nInterview -> Seed -> Execute -> Evaluate\n    ^                            |\n    +---- Evolutionary Loop -----+\n```\n\nOrdinary Claude setup uses the default `[claude]` Agent SDK profile on MCP 1.x.\nNever inspect or mutate `~/.claude/mcp.json` as a health check. If Ouroboros\nMCP tools are not callable here, say that MCP-backed commands need a supported\nhost setup, which owns an isolated `[mcp]` launcher; `[claude-sdk]` and\n`[mcp]` are never installed together.\n\n### Step 2: Persona\n\nAsk \"What brings you to Ouroboros?\" with **New project idea** (crystallize a\nvague idea into a Seed), **Tired of rewriting prompts** (AI keeps building the\nwrong thing), and **Just exploring**. Reply in 1-2 personalized sentences.\n\n### Step 3: First Action\n\nShow the core commands: `ooo interview` (Socratic Q&A that exposes hidden\nassumptions), `ooo seed` (freeze answers into a Seed), `ooo run` (execute a\nSeed), `ooo evaluate` (verify against the acceptance criteria), `ooo unstuck`\n(lateral thinking), `ooo config` (settings), `ooo help` (full reference).\n\nAsk \"What would you like to do first?\":\n\n- **Start a project**: ask \"What do you want to build?\", then continue as `ooo interview`.\n- **Try the tutorial**: continue as `ooo tutorial`.\n- **Read the docs**: continue as `ooo help`.\n\nRun Step 4 before handing off, so completion is recorded even when the next\ncommand takes over the conversation.\n\n### Step 4: GitHub Star and Completion\n\nRun `gh auth status &>/dev/null && echo GH_OK || echo GH_MISSING`. If `GH_OK`\nand `star_asked` is not true in `~/.ouroboros/prefs.json`, ask \"If you're\nenjoying Ouroboros, would you like to star it on GitHub?\" with **Star on\nGitHub** (run `gh api -X PUT /user/starred/Q00/ouroboros`) and **Maybe later**.\n\nThen merge the completion fields into `~/.ouroboros/prefs.json`, keeping\nexisting keys. Prefix the command with `STAR_ASKED=true` when the star question\nwas asked, so it is never repeated:\n\n```bash\nouroboros_python - <<'PY'\nimport json, os\nfrom datetime import UTC, datetime\npath = os.path.expanduser('~/.ouroboros/prefs.json')\nos.makedirs(os.path.dirname(path), exist_ok=True)\ntry:\n    with open(path, encoding='utf-8') as f:\n        prefs = json.load(f)\n    if not isinstance(prefs, dict):\n        prefs = {}\nexcept Exception:\n    prefs = {}\nprefs.update({\n    'welcomeShown': True,\n    'welcomeCompleted': datetime.now(UTC).isoformat(),\n})\nif os.environ.get('STAR_ASKED') == 'true':\n    prefs['star_asked'] = True\nwith open(path, 'w', encoding='utf-8') as f:\n    json.dump(prefs, f, indent=2)\n    f.write('\\n')\nPY\n```\n\nBefore the handoff, mention that phrases like \"interview me\", \"I'm stuck\", or \"evaluate this\" also\nroute to the matching command; to watch `ooo run` or `ooo evolve` live, run\n`uvx --python '>=3.12' --from 'ouroboros-ai[tui]' ouroboros tui monitor` in a\nseparate terminal.\n\n## RFC #1392 State Breadcrumb Footer\n\nEnd the final response with exactly one line `◆ <current state> → next: <recommended action>`. Derive the state from live session state via `ouroboros_session_status` when available, otherwise from this skill's actual outcome. Never use a linear `Step N of M` footer; when the next step is a real choice, list 2-3 options.\n","frontmatter":{"name":"welcome","description":"First-touch experience for new Ouroboros users","disable-model-invocation":true,"disableModelInvocation":true},"isInternal":false,"tokens":6599,"sizeBytes":25150},{"name":"SKILL.md","path":"tests/fixtures/router/skills/frontmatter-body/run/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/router/skills/frontmatter-body/run/SKILL.md","title":"run","category":"anthropic-skill","format":"markdown","content":"# run\n\nPath: `tests/fixtures/router/skills/frontmatter-body/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/router/skills/frontmatter-body/run/SKILL.md)","tokens":300,"sizeBytes":216},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/CLAUDE.md)","tokens":300,"sizeBytes":154},{"name":"marketplace.json","path":".agents/plugins/marketplace.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.agents/plugins/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.agents/plugins/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.agents/plugins/marketplace.json)","tokens":300,"sizeBytes":194},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":192},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":178},{"name":"plugin.json","path":".codex-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex-plugin/plugin.json","title":"codex-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# codex-plugin Plugin Manifest\n\nPath: `.codex-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex-plugin/plugin.json)","tokens":300,"sizeBytes":175},{"name":"ouroboros.plugin.json","path":"tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json","title":"github-pr-ops Plugin Manifest","category":"plugin-manifest","format":"json","content":"# github-pr-ops Plugin Manifest\n\nPath: `tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/tests/fixtures/plugins-fixture/plugins/github-pr-ops/ouroboros.plugin.json)","tokens":300,"sizeBytes":274},{"name":"config.toml","path":".codex/config.toml","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/config.toml","title":"Codex Directive: config.toml","category":"codex-rule","format":"markdown","content":"# Codex Directive: config.toml\n\nPath: `.codex/config.toml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/config.toml)","tokens":300,"sizeBytes":161},{"name":"hooks.json","path":".codex/hooks.json","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/hooks.json","title":"Codex Directive: hooks.json","category":"codex-rule","format":"markdown","content":"# Codex Directive: hooks.json\n\nPath: `.codex/hooks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.codex/hooks.json)","tokens":300,"sizeBytes":158},{"name":"advocate.md","path":"src/ouroboros/agents/advocate.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/advocate.md","title":"Subagent: advocate","category":"subagent-persona","format":"markdown","content":"# Subagent: advocate\n\nPath: `src/ouroboros/agents/advocate.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/advocate.md)","tokens":300,"sizeBytes":179},{"name":"analysis-agent.md","path":"src/ouroboros/agents/analysis-agent.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/analysis-agent.md","title":"Subagent: analysis-agent","category":"subagent-persona","format":"markdown","content":"# Subagent: analysis-agent\n\nPath: `src/ouroboros/agents/analysis-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/analysis-agent.md)","tokens":300,"sizeBytes":197},{"name":"architect.md","path":"src/ouroboros/agents/architect.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/architect.md","title":"Subagent: architect","category":"subagent-persona","format":"markdown","content":"# Subagent: architect\n\nPath: `src/ouroboros/agents/architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/architect.md)","tokens":300,"sizeBytes":182},{"name":"breadth-keeper.md","path":"src/ouroboros/agents/breadth-keeper.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/breadth-keeper.md","title":"Subagent: breadth-keeper","category":"subagent-persona","format":"markdown","content":"# Subagent: breadth-keeper\n\nPath: `src/ouroboros/agents/breadth-keeper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/breadth-keeper.md)","tokens":300,"sizeBytes":197},{"name":"code-executor.md","path":"src/ouroboros/agents/code-executor.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/code-executor.md","title":"Subagent: code-executor","category":"subagent-persona","format":"markdown","content":"# Subagent: code-executor\n\nPath: `src/ouroboros/agents/code-executor.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/code-executor.md)","tokens":300,"sizeBytes":194},{"name":"codebase-explorer.md","path":"src/ouroboros/agents/codebase-explorer.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/codebase-explorer.md","title":"Subagent: codebase-explorer","category":"subagent-persona","format":"markdown","content":"# Subagent: codebase-explorer\n\nPath: `src/ouroboros/agents/codebase-explorer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/codebase-explorer.md)","tokens":300,"sizeBytes":206},{"name":"consensus-reviewer.md","path":"src/ouroboros/agents/consensus-reviewer.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/consensus-reviewer.md","title":"Subagent: consensus-reviewer","category":"subagent-persona","format":"markdown","content":"# Subagent: consensus-reviewer\n\nPath: `src/ouroboros/agents/consensus-reviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/consensus-reviewer.md)","tokens":300,"sizeBytes":209},{"name":"contrarian.md","path":"src/ouroboros/agents/contrarian.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/contrarian.md","title":"Subagent: contrarian","category":"subagent-persona","format":"markdown","content":"# Subagent: contrarian\n\nPath: `src/ouroboros/agents/contrarian.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/contrarian.md)","tokens":300,"sizeBytes":185},{"name":"evaluator.md","path":"src/ouroboros/agents/evaluator.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/evaluator.md","title":"Subagent: evaluator","category":"subagent-persona","format":"markdown","content":"# Subagent: evaluator\n\nPath: `src/ouroboros/agents/evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/evaluator.md)","tokens":300,"sizeBytes":182},{"name":"hacker.md","path":"src/ouroboros/agents/hacker.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/hacker.md","title":"Subagent: hacker","category":"subagent-persona","format":"markdown","content":"# Subagent: hacker\n\nPath: `src/ouroboros/agents/hacker.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/hacker.md)","tokens":300,"sizeBytes":173},{"name":"judge.md","path":"src/ouroboros/agents/judge.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/judge.md","title":"Subagent: judge","category":"subagent-persona","format":"markdown","content":"# Subagent: judge\n\nPath: `src/ouroboros/agents/judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/judge.md)","tokens":300,"sizeBytes":170},{"name":"ontologist.md","path":"src/ouroboros/agents/ontologist.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontologist.md","title":"Subagent: ontologist","category":"subagent-persona","format":"markdown","content":"# Subagent: ontologist\n\nPath: `src/ouroboros/agents/ontologist.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontologist.md)","tokens":300,"sizeBytes":185},{"name":"ontology-analyst.md","path":"src/ouroboros/agents/ontology-analyst.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontology-analyst.md","title":"Subagent: ontology-analyst","category":"subagent-persona","format":"markdown","content":"# Subagent: ontology-analyst\n\nPath: `src/ouroboros/agents/ontology-analyst.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/ontology-analyst.md)","tokens":300,"sizeBytes":203},{"name":"qa-judge.md","path":"src/ouroboros/agents/qa-judge.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/qa-judge.md","title":"Subagent: qa-judge","category":"subagent-persona","format":"markdown","content":"# Subagent: qa-judge\n\nPath: `src/ouroboros/agents/qa-judge.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/qa-judge.md)","tokens":300,"sizeBytes":179},{"name":"research-agent.md","path":"src/ouroboros/agents/research-agent.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/research-agent.md","title":"Subagent: research-agent","category":"subagent-persona","format":"markdown","content":"# Subagent: research-agent\n\nPath: `src/ouroboros/agents/research-agent.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/research-agent.md)","tokens":300,"sizeBytes":197},{"name":"researcher.md","path":"src/ouroboros/agents/researcher.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/researcher.md","title":"Subagent: researcher","category":"subagent-persona","format":"markdown","content":"# Subagent: researcher\n\nPath: `src/ouroboros/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/researcher.md)","tokens":300,"sizeBytes":185},{"name":"seed-architect.md","path":"src/ouroboros/agents/seed-architect.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-architect.md","title":"Subagent: seed-architect","category":"subagent-persona","format":"markdown","content":"# Subagent: seed-architect\n\nPath: `src/ouroboros/agents/seed-architect.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-architect.md)","tokens":300,"sizeBytes":197},{"name":"seed-closer.md","path":"src/ouroboros/agents/seed-closer.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-closer.md","title":"Subagent: seed-closer","category":"subagent-persona","format":"markdown","content":"# Subagent: seed-closer\n\nPath: `src/ouroboros/agents/seed-closer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/seed-closer.md)","tokens":300,"sizeBytes":188},{"name":"semantic-evaluator.md","path":"src/ouroboros/agents/semantic-evaluator.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/semantic-evaluator.md","title":"Subagent: semantic-evaluator","category":"subagent-persona","format":"markdown","content":"# Subagent: semantic-evaluator\n\nPath: `src/ouroboros/agents/semantic-evaluator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/semantic-evaluator.md)","tokens":300,"sizeBytes":209},{"name":"simplifier.md","path":"src/ouroboros/agents/simplifier.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/simplifier.md","title":"Subagent: simplifier","category":"subagent-persona","format":"markdown","content":"# Subagent: simplifier\n\nPath: `src/ouroboros/agents/simplifier.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/simplifier.md)","tokens":300,"sizeBytes":185},{"name":"socratic-interviewer.md","path":"src/ouroboros/agents/socratic-interviewer.md","rawUrl":"https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/socratic-interviewer.md","title":"Subagent: socratic-interviewer","category":"subagent-persona","format":"markdown","content":"# Subagent: socratic-interviewer\n\nPath: `src/ouroboros/agents/socratic-interviewer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/src/ouroboros/agents/socratic-interviewer.md)","tokens":300,"sizeBytes":215}],"systemPromptSnippet":"<yakaai_skills repo=\"Q00/ouroboros\">\n<!-- File: AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/AGENTS.md)\n\n<!-- File: llms-full.txt (Tokens: ~300 | Category: root-instruction) -->\n# LLM Full Documentation Context\n\nPath: `llms-full.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms-full.txt)\n\n<!-- File: llms.txt (Tokens: ~300 | Category: root-instruction) -->\n# LLM Index & Context Digest\n\nPath: `llms.txt`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/llms.txt)\n\n<!-- File: docs/architecture.md (Tokens: ~300 | Category: project-spec) -->\n# docs - System Architecture & Module Boundaries\n\nPath: `docs/architecture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/docs/architecture.md)\n\n<!-- File: .claude-plugin/skills/auto/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# auto\n\nPath: `.claude-plugin/skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/auto/SKILL.md)\n\n<!-- File: .claude-plugin/skills/brownfield/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# brownfield\n\nPath: `.claude-plugin/skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/brownfield/SKILL.md)\n\n<!-- File: .claude-plugin/skills/cancel/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# cancel\n\nPath: `.claude-plugin/skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/cancel/SKILL.md)\n\n<!-- File: .claude-plugin/skills/config/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# config\n\nPath: `.claude-plugin/skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/config/SKILL.md)\n\n<!-- File: .claude-plugin/skills/evaluate/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# evaluate\n\nPath: `.claude-plugin/skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evaluate/SKILL.md)\n\n<!-- File: .claude-plugin/skills/evolve/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# evolve\n\nPath: `.claude-plugin/skills/evolve/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/evolve/SKILL.md)\n\n<!-- File: .claude-plugin/skills/help/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# help\n\nPath: `.claude-plugin/skills/help/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/help/SKILL.md)\n\n<!-- File: .claude-plugin/skills/interview/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# interview\n\nPath: `.claude-plugin/skills/interview/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/interview/SKILL.md)\n\n<!-- File: .claude-plugin/skills/pm/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# pm\n\nPath: `.claude-plugin/skills/pm/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/pm/SKILL.md)\n\n<!-- File: .claude-plugin/skills/publish/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# publish\n\nPath: `.claude-plugin/skills/publish/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/publish/SKILL.md)\n\n<!-- File: .claude-plugin/skills/qa/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# qa\n\nPath: `.claude-plugin/skills/qa/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/qa/SKILL.md)\n\n<!-- File: .claude-plugin/skills/ralph/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# ralph\n\nPath: `.claude-plugin/skills/ralph/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/ralph/SKILL.md)\n\n<!-- File: .claude-plugin/skills/resume-session/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# resume-session\n\nPath: `.claude-plugin/skills/resume-session/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/resume-session/SKILL.md)\n\n<!-- File: .claude-plugin/skills/run/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# run\n\nPath: `.claude-plugin/skills/run/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/run/SKILL.md)\n\n<!-- File: .claude-plugin/skills/seed/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# seed\n\nPath: `.claude-plugin/skills/seed/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/seed/SKILL.md)\n\n<!-- File: .claude-plugin/skills/setup/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# setup\n\nPath: `.claude-plugin/skills/setup/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/setup/SKILL.md)\n\n<!-- File: .claude-plugin/skills/status/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# status\n\nPath: `.claude-plugin/skills/status/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/status/SKILL.md)\n\n<!-- File: .claude-plugin/skills/tutorial/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# tutorial\n\nPath: `.claude-plugin/skills/tutorial/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/tutorial/SKILL.md)\n\n<!-- File: .claude-plugin/skills/unstuck/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# unstuck\n\nPath: `.claude-plugin/skills/unstuck/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/unstuck/SKILL.md)\n\n<!-- File: .claude-plugin/skills/update/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# update\n\nPath: `.claude-plugin/skills/update/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/update/SKILL.md)\n\n<!-- File: .claude-plugin/skills/welcome/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# welcome\n\nPath: `.claude-plugin/skills/welcome/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/.claude-plugin/skills/welcome/SKILL.md)\n\n<!-- File: skills/auto/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# auto\n\nPath: `skills/auto/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/auto/SKILL.md)\n\n<!-- File: skills/brownfield/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# brownfield\n\nPath: `skills/brownfield/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/brownfield/SKILL.md)\n\n<!-- File: skills/cancel/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# cancel\n\nPath: `skills/cancel/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/cancel/SKILL.md)\n\n<!-- File: skills/config/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# config\n\nPath: `skills/config/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/config/SKILL.md)\n\n<!-- File: skills/evaluate/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# evaluate\n\nPath: `skills/evaluate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Q00/ouroboros/HEAD/skills/evaluate/SKILL.md)\n\n<!-- ... +47 more modular skills available via /api/skills/Q00/ouroboros?path={path} -->\n</yakaai_skills>"}