Claude Skill

tiling-tree

Exhaustive problem space exploration using the MIT Synthetic Neurobiology "tiling tree" method. Partitions a problem into MECE (Mutually Exclusive, Collectively Exhaustive) subsets recursively via parallel subagents, then evaluates leaf ideas against specified criteria. Use when

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download oaustegard-claude-skills-plugins_ai-and-reasoning_skills_tiling-tree-e39c726.zip · 6 KB
Part of oaustegard/claude-skills — 39 skills

Install

skills CLI npx skills add https://github.com/oaustegard/claude-skills/tree/main/plugins/ai-and-reasoning/skills/tiling-tree
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install oaustegard-claude-skills@llmmart
Git git clone https://github.com/oaustegard/claude-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole oaustegard/claude-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Tiling Tree

Implements the MIT Synthetic Neurobiology tiling tree method: recursively partition a problem space into non-overlapping, collectively exhaustive subsets until reaching actionable leaf ideas, then evaluate those leaves.

Core Concept

The method's power comes from MECE splits forcing exploration of unfamiliar territory. A split is only valid when you can state precisely what each branch excludes — if you can't, the criterion is too vague and branches will overlap.

Key insight from the source method: always look for the "third option" that falls outside an obvious binary split. The bloodstream-secretion approach to neural recording only emerged because "wired vs. wireless" was defined precisely enough to reveal it covered neither case.

When to Use

  • "What are all the ways we could solve X?"
  • "Apply the tiling tree method to Y"
  • "Exhaustively map the solution space for Z"
  • Any request for MECE decomposition of a problem domain

Setup

Requires orchestrating-agents skill to be installed. Load it first:

import sys
sys.path.insert(0, '/mnt/skills/user/orchestrating-agents/scripts')

from claude_client import invoke_claude, invoke_parallel, parse_json_response

Running the Tiling Tree

# Basic usage
python3 /mnt/skills/user/tiling-tree/scripts/tiling_tree.py "Your problem here"

# With options
python3 /mnt/skills/user/tiling-tree/scripts/tiling_tree.py \
  "How can we record neural activity?" \
  --depth 3 \
  --criteria "impact,novelty,feasibility" \
  --output /mnt/user-data/outputs/neural_recording_tree.md

Parameters

Parameter Default Notes
problem required Natural language problem statement
--depth 2 Max recursion depth. Depth 2 ≈ 16 leaves, depth 3 ≈ 64 leaves
--criteria impact,novelty,feasibility Comma-separated evaluation dimensions
--output tiling_tree.md Output markdown path

Depth guidance: Start with depth 2 to validate the problem framing. Increase to 3 only when the domain genuinely warrants it — depth 3 generates ~64 leaves and ~40 API calls.

Architecture

  • Orchestrator (this script): builds tree skeleton, dispatches parallel split jobs per level, merges results, detects gaps
  • Branch agents (invoke_parallel): each receives one node to split, returns MECE branches with explicit exclusion statements
  • Evaluator (invoke_claude): single agent scores all leaves for cross-leaf consistency

Parallel splitting happens level-by-level (not node-by-node), so a depth-2 tree makes only 2 API round-trips for the splitting phase regardless of branching factor.

Output

A markdown file containing:

  1. Full tree diagram with split criteria and evaluation scores at leaves
  2. Ranked leaf table sorted by overall score

Interpreting Results

Good trees have:

  • Split criteria that are definitions, not questions ("energy source type" not "is it renewable?")
  • Leaf exclusions that confirm non-overlap
  • A "surprising" branch — something you wouldn't have thought of without the tree

If all leaves feel obvious, the split criteria were too coarse. Redo the tree with more precise definitions at the branch level where it went flat.

Files (claude-skills)
  • scripts
    • tiling_tree.py 11 KB
      #!/usr/bin/env python3
      """
      Tiling Tree — exhaustive MECE problem space exploration via parallel subagents.
      
      Implements the MIT Synthetic Neurobiology "tiling tree" method.
      Depends on: orchestrating-agents skill
      
      Usage:
          python3 tiling_tree.py "How can we generate energy?"
          python3 tiling_tree.py "How can we record neural activity?" --depth 3 --criteria "impact,feasibility,novelty"
      """
      
      import argparse
      import json
      import sys
      from dataclasses import dataclass, field
      
      # ── Dependency setup ──────────────────────────────────────────────────────────
      
      sys.path.insert(0, '/mnt/skills/user/orchestrating-agents/scripts')
      
      try:
          from claude_client import invoke_claude, invoke_parallel, parse_json_response
      except ImportError as e:
          print(f"ERROR: orchestrating-agents skill not found at /mnt/skills/user/orchestrating-agents/\n{e}")
          sys.exit(1)
      
      
      # ── Data model ────────────────────────────────────────────────────────────────
      
      @dataclass
      class Node:
          id: str
          label: str
          definition: str
          parent_id: str | None
          depth: int
          split_criterion: str = ""
          children: list = field(default_factory=list)
          is_leaf: bool = False
          exclusions: str = ""
          evaluation: dict = field(default_factory=dict)
      
      
      # ── Prompts ───────────────────────────────────────────────────────────────────
      
      SPLITTER_SYSTEM = """You are a rigorous analyst applying the "tiling tree" method from MIT's Synthetic Neurobiology group. Your job: partition a problem space into MECE subsets (Mutually Exclusive, Collectively Exhaustive).
      
      Rules:
      1. Define your split criterion PRECISELY before naming branches. Vague criteria produce overlapping branches.
      2. Branches must not overlap. State explicitly what each branch EXCLUDES to verify this.
      3. Branches together must cover the entire parent set.
      4. Prefer physics/math/logical splits — they tend to be genuinely exhaustive.
      5. Look for the "third option" — what falls outside an obvious binary split?
      6. A branch is a LEAF when it represents a single concrete, actionable approach (not a category).
      7. Aim for 2-4 branches per split.
      
      Respond ONLY with valid JSON."""
      
      EVALUATOR_SYSTEM = """You evaluate candidate approaches against specified criteria. Be calibrated: reserve high scores for genuinely strong candidates. Respond ONLY with valid JSON."""
      
      
      def _splitter_prompt(label: str, definition: str, depth: int, max_depth: int) -> str:
          leaf_instruction = (
              "Mark branches as leaves (is_leaf: true) if they represent a single concrete approach."
              if depth < max_depth
              else "Final level — mark ALL branches as leaves (is_leaf: true)."
          )
          return f"""Problem space to partition: "{label}"
      Definition: {definition}
      Current depth: {depth}/{max_depth}
      
      {leaf_instruction}
      
      Respond with JSON:
      {{
        "split_criterion": "Precise property used to split this space (a definition, not a question)",
        "branches": [
          {{
            "label": "Short name",
            "definition": "Precise definition of what belongs here",
            "exclusions": "What this branch explicitly does NOT include",
            "is_leaf": false,
            "leaf_idea": ""
          }}
        ],
        "coverage_check": "One sentence confirming branches together cover the full parent space"
      }}"""
      
      
      def _evaluator_prompt(leaves: list, criteria: list[str]) -> str:
          descriptions = "\n".join(
              f'- [{l.id}] {l.label}: {l.definition}' for l in leaves
          )
          score_template = ", ".join(f'"{c}": 1-5' for c in criteria)
          return f"""Evaluate these candidate approaches:
      
      {descriptions}
      
      Criteria: {', '.join(criteria)}
      
      Respond with JSON:
      {{
        "evaluations": [
          {{
            "id": "node_id",
            "scores": {{{score_template}}},
            "rationale": "One sentence on the most important trade-off",
            "overall": 1-5
          }}
        ]
      }}"""
      
      
      # ── Tree construction ─────────────────────────────────────────────────────────
      
      # @lat: [[orchestration#Tiling Tree]]
      def build_tree(problem: str, max_depth: int = 2) -> Node:
          root = Node(
              id="root",
              label=problem,
              definition=f"The complete set of all possible approaches to: {problem}",
              parent_id=None,
              depth=0,
          )
      
          frontier = [root]
      
          for level in range(max_depth):
              to_split = [n for n in frontier if not n.is_leaf]
              if not to_split:
                  break
      
              print(f"  Level {level + 1}: splitting {len(to_split)} node(s) in parallel...")
      
              prompts = [
                  {
                      "prompt": _splitter_prompt(n.label, n.definition, n.depth + 1, max_depth),
                      "system": SPLITTER_SYSTEM,
                      "temperature": 1.0,
                  }
                  for n in to_split
              ]
      
              raw_results = invoke_parallel(
                  prompts,
                  model="claude-sonnet-4-6",
                  max_tokens=2048
              )
      
              next_frontier = []
              for node, raw in zip(to_split, raw_results):
                  try:
                      data = parse_json_response(raw)
                  except (json.JSONDecodeError, Exception) as e:
                      print(f"  ✗ Parse failed for '{node.label}': {e}", file=sys.stderr)
                      node.is_leaf = True
                      continue
      
                  node.split_criterion = data.get("split_criterion", "")
                  print(f"  ✓ '{node.label[:40]}' → {node.split_criterion[:60]}...")
      
                  for i, b in enumerate(data.get("branches", [])):
                      child = Node(
                          id=f"{node.id}_{i}",
                          label=b["label"],
                          definition=b.get("leaf_idea") or b["definition"],
                          parent_id=node.id,
                          depth=node.depth + 1,
                          is_leaf=b.get("is_leaf", node.depth + 1 >= max_depth),
                          exclusions=b.get("exclusions", ""),
                      )
                      node.children.append(child)
                      if not child.is_leaf:
                          next_frontier.append(child)
      
              frontier = next_frontier
      
          return root
      
      
      def collect_leaves(node: Node) -> list:
          if node.is_leaf:
              return [node]
          return [leaf for child in node.children for leaf in collect_leaves(child)]
      
      
      def evaluate_leaves(leaves: list, criteria: list[str]) -> None:
          print(f"  Evaluating {len(leaves)} leaves against: {', '.join(criteria)}...")
          try:
              raw = invoke_claude(
                  prompt=_evaluator_prompt(leaves, criteria),
                  system=EVALUATOR_SYSTEM,
                  model="claude-sonnet-4-6",
                  max_tokens=4096,
                  temperature=0.8,
              )
              data = parse_json_response(raw)
              leaf_map = {l.id: l for l in leaves}
              for ev in data.get("evaluations", []):
                  node = leaf_map.get(ev["id"])
                  if node:
                      node.evaluation = ev
          except Exception as e:
              print(f"  ✗ Evaluation failed: {e}", file=sys.stderr)
      
      
      # ── Rendering ─────────────────────────────────────────────────────────────────
      
      def _count_nodes(node: Node) -> int:
          return 1 + sum(_count_nodes(c) for c in node.children)
      
      
      def render_tree(node: Node, prefix: str = "", is_last: bool = True) -> str:
          lines = []
      
          if node.depth == 0:
              lines.append(f"◆ {node.label}")
          else:
              connector = "└── " if is_last else "├── "
              tag = " [LEAF]" if node.is_leaf else ""
              lines.append(f"{prefix}{connector}{node.label}{tag}")
              if node.is_leaf and node.evaluation:
                  sub = "    " if is_last else "│   "
                  ev = node.evaluation
                  score_str = "  ".join(f"{k}:{v}" for k, v in ev.get("scores", {}).items())
                  lines.append(f"{prefix}{sub}  ↳ {score_str}  overall:{ev.get('overall', '?')}")
                  lines.append(f"{prefix}{sub}  ↳ {ev.get('rationale', '')}")
      
          if node.split_criterion and node.children:
              sub = "    " if (is_last or node.depth == 0) else "│   "
              lines.append(f"{prefix}{sub}[split: {node.split_criterion[:72]}]")
      
          child_prefix = prefix + ("    " if is_last else "│   ")
          for i, child in enumerate(node.children):
              lines.append(render_tree(child, child_prefix, i == len(node.children) - 1))
      
          return "\n".join(lines)
      
      
      def render_markdown(root: Node, problem: str, criteria: list[str]) -> str:
          leaves = collect_leaves(root)
          ranked = sorted(leaves, key=lambda l: l.evaluation.get("overall", 0), reverse=True)
          node_count = _count_nodes(root)
      
          md = [f"# Tiling Tree: {problem}\n"]
          md.append("## Tree\n```")
          md.append(render_tree(root))
          md.append("```\n")
      
          if criteria and any(l.evaluation for l in leaves):
              md.append(f"## Ranked Leaves ({', '.join(criteria)})\n")
              for rank, leaf in enumerate(ranked, 1):
                  ev = leaf.evaluation
                  scores = ev.get("scores", {})
                  score_str = " | ".join(f"**{k}**: {v}/5" for k, v in scores.items())
                  md.append(f"### {rank}. {leaf.label}  *(overall {ev.get('overall', '?')}/5)*")
                  md.append(f"{score_str}\n")
                  md.append(f"> {leaf.definition}\n")
                  md.append(f"{ev.get('rationale', '')}\n")
      
          md.append(f"---\n*{len(leaves)} leaf ideas across {node_count} total nodes.*")
          return "\n".join(md)
      
      
      # ── Entry point ───────────────────────────────────────────────────────────────
      
      def main():
          parser = argparse.ArgumentParser(
              description="Tiling Tree — exhaustive MECE problem space exploration"
          )
          parser.add_argument("problem", help="The problem to tile")
          parser.add_argument("--depth", type=int, default=2,
                              help="Max tree depth (default: 2, yields ~16 leaves)")
          parser.add_argument("--criteria", default="impact,novelty,feasibility",
                              help="Comma-separated evaluation criteria")
          parser.add_argument("--output", default="/mnt/user-data/outputs/tiling_tree.md",
                              help="Output markdown path")
          args = parser.parse_args()
      
          criteria = [c.strip() for c in args.criteria.split(",")]
      
          print(f"\n◆ Tiling Tree: {args.problem}")
          print(f"  Depth: {args.depth} | Criteria: {', '.join(criteria)}\n")
      
          root = build_tree(args.problem, max_depth=args.depth)
          leaves = collect_leaves(root)
          print(f"\n  Tree complete: {len(leaves)} leaves\n")
      
          if criteria:
              evaluate_leaves(leaves, criteria)
      
          print("\n" + render_tree(root))
      
          md = render_markdown(root, args.problem, criteria)
          with open(args.output, "w") as f:
              f.write(md)
          print(f"\n  Saved: {args.output}")
      
      
      if __name__ == "__main__":
          main()
      
  • CHANGELOG.md 427 B
    # tiling-tree - Changelog
    
    All notable changes to the `tiling-tree` skill are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
    
    ## [1.0.1] - 2026-03-06
    
    ### Fixed
    
    - remove shim and local _parse_json workarounds from tiling-tree (#314)
    - resolve issues #311 and #312 in claude_client.py
    
    ### Other
    
    - Update subagent models: default to Sonnet 4.6, add Haiku 4.5 support
    
  • SKILL.md 3.8 KB
    ---
    name: tiling-tree
    description: Exhaustive problem space exploration using the MIT Synthetic Neurobiology "tiling tree" method. Partitions a problem into MECE (Mutually Exclusive, Collectively Exhaustive) subsets recursively via parallel subagents, then evaluates leaf ideas against specified criteria. Use when users say "tiling tree", "tile the solution space", "exhaustively explore approaches to", "what are all the ways to", or request a MECE breakdown of a problem. Requires orchestrating-agents skill.
    metadata:
      version: 1.0.1
      depends_on: orchestrating-agents
    ---
    
    # Tiling Tree
    
    Implements the MIT Synthetic Neurobiology tiling tree method: recursively partition a problem space into non-overlapping, collectively exhaustive subsets until reaching actionable leaf ideas, then evaluate those leaves.
    
    ## Core Concept
    
    The method's power comes from MECE splits forcing exploration of unfamiliar territory. A split is only valid when you can state precisely what each branch **excludes** — if you can't, the criterion is too vague and branches will overlap.
    
    Key insight from the source method: always look for the "third option" that falls outside an obvious binary split. The bloodstream-secretion approach to neural recording only emerged because "wired vs. wireless" was defined precisely enough to reveal it covered neither case.
    
    ## When to Use
    
    - "What are all the ways we could solve X?"
    - "Apply the tiling tree method to Y"
    - "Exhaustively map the solution space for Z"
    - Any request for MECE decomposition of a problem domain
    
    ## Setup
    
    Requires `orchestrating-agents` skill to be installed. Load it first:
    
    ```python
    import sys
    sys.path.insert(0, '/mnt/skills/user/orchestrating-agents/scripts')
    
    from claude_client import invoke_claude, invoke_parallel, parse_json_response
    ```
    
    ## Running the Tiling Tree
    
    ```bash
    # Basic usage
    python3 /mnt/skills/user/tiling-tree/scripts/tiling_tree.py "Your problem here"
    
    # With options
    python3 /mnt/skills/user/tiling-tree/scripts/tiling_tree.py \
      "How can we record neural activity?" \
      --depth 3 \
      --criteria "impact,novelty,feasibility" \
      --output /mnt/user-data/outputs/neural_recording_tree.md
    ```
    
    ## Parameters
    
    | Parameter | Default | Notes |
    |-----------|---------|-------|
    | `problem` | required | Natural language problem statement |
    | `--depth` | 2 | Max recursion depth. Depth 2 ≈ 16 leaves, depth 3 ≈ 64 leaves |
    | `--criteria` | `impact,novelty,feasibility` | Comma-separated evaluation dimensions |
    | `--output` | `tiling_tree.md` | Output markdown path |
    
    **Depth guidance:** Start with depth 2 to validate the problem framing. Increase to 3 only when the domain genuinely warrants it — depth 3 generates ~64 leaves and ~40 API calls.
    
    ## Architecture
    
    - **Orchestrator** (this script): builds tree skeleton, dispatches parallel split jobs per level, merges results, detects gaps
    - **Branch agents** (`invoke_parallel`): each receives one node to split, returns MECE branches with explicit exclusion statements
    - **Evaluator** (`invoke_claude`): single agent scores all leaves for cross-leaf consistency
    
    Parallel splitting happens level-by-level (not node-by-node), so a depth-2 tree makes only 2 API round-trips for the splitting phase regardless of branching factor.
    
    ## Output
    
    A markdown file containing:
    1. Full tree diagram with split criteria and evaluation scores at leaves
    2. Ranked leaf table sorted by overall score
    
    ## Interpreting Results
    
    Good trees have:
    - Split criteria that are definitions, not questions ("energy source type" not "is it renewable?")
    - Leaf exclusions that confirm non-overlap
    - A "surprising" branch — something you wouldn't have thought of without the tree
    
    If all leaves feel obvious, the split criteria were too coarse. Redo the tree with more precise definitions at the branch level where it went flat.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related