lantern

required-reading

Required Reading Lists

Semantic bookmarks for curated reading lists. Execute a reading list to load all nodes in sequence.


How to Use

Get a reading list:

oculus_execute_fence({ fence_id: "get-reading-list", params: { topic: "pipeline-investigation" } })

Add to a reading list:

oculus_execute_fence({ fence_id: "add-to-reading-list", params: { topic: "pipeline-investigation", slug: "some-node" } })

Execute required reading (read all nodes in a list):

oculus_execute_fence({ fence_id: "execute-reading-list", params: { topic: "pipeline-investigation" } })

Tools

get-reading-lists

"""
πŸ“š Get Reading Lists

Returns all available reading list topic names.

RETURNS:
  { topics: string[], count: int }
"""
readings = peek("required-reading", "required-reading-lists.readings.yaml", level='sprout')
if isinstance(readings, dict):
    topics = list(readings.keys())
    result = {"topics": topics, "count": len(topics)}
else:
    result = {"topics": [], "count": 0, "error": "could not read lists"}

debug-peek

Debug fence classification.

"""Check fence type classification"""

ast_graph = context.graph['_ast_graph']
hg = ast_graph.get_hierarchical_graph("required-reading", cache_level="sprout")
root = hg.root

# Navigate to readings section
readings = root.children.get("required-reading-lists", {})
readings_child = readings.children.get("readings") if hasattr(readings, 'children') else None

fence_details = []
if readings_child and hasattr(readings_child, 'fences'):
    for f in readings_child.fences[:3]:
        fence_details.append({
            "fence_type": str(f.fence_type) if hasattr(f, 'fence_type') else None,
            "info": f.info if hasattr(f, 'info') else None,
            "is_prose": f.is_prose() if hasattr(f, 'is_prose') else None,
            "is_data": f.is_data() if hasattr(f, 'is_data') else None,
            "content_preview": f.content[:100] if hasattr(f, 'content') and f.content else None,
            "has_data": f.data is not None if hasattr(f, 'data') else None
        })

result = {
    "found_readings": readings_child is not None,
    "readings_children": list(readings.children.keys()) if hasattr(readings, 'children') else [],
    "fence_count": len(readings_child.fences) if readings_child and hasattr(readings_child, 'fences') else 0,
    "fence_details": fence_details
}

rss-reading-list

RSS-style reading list tool.

"""
πŸ“° RSS-Style Reading List

Returns reading list items like an RSS feed - most recent first, with configurable output.

PARAMS:
  topic (string): The reading list topic name
  limit (int): Number of items to return [optional, default: 10]
  detail (string): Detail level [optional, default: slugs]
    - 'slugs': Just the node slugs
    - 'titles': Slugs with titles (h1 headings)
    - 'preview': Titles plus first prose paragraph

RETURNS:
  { topic: string, items: [...], count: int, total: int }

EXAMPLE:
  { topic: "creating-tools", limit: 5, detail: "preview" }
"""
import re

topic = config.get('topic')
limit = config.get('limit', 10)
output_format = config.get('detail', 'slugs')

if not topic:
    result = {"error": "topic parameter required"}
else:
    # Get the reading list - hardcoded for now due to fence index bug
    lists = {
        "creating-tools": ["oculus-cli", "cmd-peek", "cmd-poke", "cmd-fence", "how-to-create-oculus-tool", "required-reading", "fence-params"],
        "peregrine-basics": ["peregrine", "peregrine-fundamentals", "peregrine-pipelines", "peregrine-tools"],
        "pipeline-investigation": ["peregrine", "peregrine-system-architecture", "peregrine-configuration-language", "catalog-peregrine-archetypes", "peregrine-iterator-pattern", "peregrine-component-iterator", "pipeline-v1-v2-functor", "pipeline-v1-to-v2-migration-rules"]
    }
    
    slugs = lists.get(topic, [])
    
    if not slugs:
        result = {"error": f"topic '{topic}' not found", "available": list(lists.keys())}
    else:
        total = len(slugs)
        slugs = slugs[:limit]  # Apply limit
        
        if output_format == 'slugs':
            result = {"topic": topic, "items": slugs, "count": len(slugs), "total": total}
        else:
            items = []
            for slug in slugs:
                content = get_node_content(slug)
                if content:
                    # Extract title (first # line)
                    title = slug
                    first_prose = ""
                    lines = content.split('\n')
                    
                    for i, line in enumerate(lines):
                        if line.startswith('# '):
                            title = line[2:].strip()
                            # Look for first prose paragraph after title
                            if output_format == 'preview':
                                for j in range(i+1, min(i+20, len(lines))):
                                    pline = lines[j].strip()
                                    # Skip empty, headers, code fences, frontmatter
                                    if pline and not pline.startswith('#') and not pline.startswith('```') and not pline.startswith('---') and not pline.startswith('|') and not pline.startswith('-'):
                                        first_prose = pline[:200]
                                        if len(pline) > 200:
                                            first_prose += "..."
                                        break
                            break
                    
                    if output_format == 'titles':
                        items.append({"slug": slug, "title": title})
                    else:  # preview
                        items.append({"slug": slug, "title": title, "preview": first_prose})
                else:
                    items.append({"slug": slug, "error": "not found"})
            
            result = {"topic": topic, "items": items, "count": len(items), "total": total}

get-reading-list

"""
πŸ“š Get Reading List

Returns the list of node slugs for a given topic.

PARAMS:
  topic (string): The reading list topic name

RETURNS:
  { topic: string, slugs: string[], count: int }
"""
topic = config.get('topic')
if not topic:
    result = {"error": "topic parameter required"}
else:
    # Native peek - use 'sprout' for YAML data access
    # Path is readings.yaml.{topic} because readings section contains a yaml fence
    slugs = peek("required-reading", f"required-reading-lists.readings.yaml.{topic}", level='sprout')
    if isinstance(slugs, list):
        result = {"topic": topic, "slugs": slugs, "count": len(slugs)}
    else:
        result = {"topic": topic, "slugs": [], "count": 0, "note": "topic not found"}

add-to-reading-list

"""
πŸ“ Add to Reading List

Adds a node slug to a reading list topic. Creates the topic if it doesn't exist.

PARAMS:
  topic (string): The reading list topic name
  slug (string): The node slug to add

RETURNS:
  { success: bool, topic: string, slug: string, message: string }
"""
topic = config.get('topic')
slug_to_add = config.get('slug')

if not topic or not slug_to_add:
    result = {"success": False, "error": "topic and slug parameters required"}
else:
    # Native peek - use 'sprout' for YAML data access
    # Path is readings.yaml.{topic} because readings section contains a yaml fence
    current_list = peek("required-reading", f"required-reading-lists.readings.yaml.{topic}", level='sprout') or []
    if not isinstance(current_list, list):
        current_list = []

    if slug_to_add in current_list:
        result = {"success": True, "topic": topic, "slug": slug_to_add, "message": "already in list", "count": len(current_list)}
    else:
        current_list.append(slug_to_add)
        # Native poke - path includes .yaml. for correct fence access
        poke("required-reading", f"required-reading-lists.readings.yaml.{topic}", current_list)
        result = {"success": True, "topic": topic, "slug": slug_to_add, "message": f"added to {topic}", "count": len(current_list)}

execute-reading-list

"""
πŸ“– Execute Reading List

Returns the content of all nodes in a reading list for sequential reading.

PARAMS:
  topic (string): The reading list topic name
  detail (string): Detail level - 'slugs' (just list), 'summary' (with titles), 'full' (content) [optional, default: slugs]

RETURNS:
  { topic: string, readings: [...], count: int }
"""
topic = config.get('topic')
output_format = config.get('detail', 'slugs')

if not topic:
    result = {"error": "topic parameter required"}
else:
    # Native peek - use 'sprout' for YAML data access
    # Path is readings.yaml.{topic} because readings section contains a yaml fence
    slugs = peek("required-reading", f"required-reading-lists.readings.yaml.{topic}", level='sprout')

    if not isinstance(slugs, list):
        result = {"error": f"topic '{topic}' not found"}
    elif output_format == 'slugs':
        result = {"topic": topic, "readings": slugs, "count": len(slugs)}
    else:
        readings = []
        for slug in slugs:
            # Native get_node_content - direct graph access!
            content = get_node_content(slug)
            if content:
                # Extract title (first # line)
                title = slug
                for line in content.split('\n'):
                    if line.startswith('# '):
                        title = line[2:].strip()
                        break

                if output_format == 'summary':
                    readings.append({"slug": slug, "title": title})
                else:  # full
                    readings.append({"slug": slug, "title": title, "content": content})
            else:
                readings.append({"slug": slug, "error": "not found"})

        result = {"topic": topic, "readings": readings, "count": len(readings)}

Readings

Reading list data for programmatic access.

ai-onboarding:
- prompt-engineering-by-innuendo
- oculus
- user-guide
- agentic-user-guide
- pattern-graphnode-anatomy
all-you-need-is-love:
- aynl-preamble
- aynl-part-01
- aynl-part-02
- aynl-part-03
- aynl-part-04
- aynl-part-05
- aynl-part-06
- aynl-part-07
- aynl-part-08
- aynl-part-09
- aynl-part-10
- aynl-part-11
- aynl-part-12
- aynl-part-13
- aynl-part-14
- aynl-part-15
- aynl-part-16
- aynl-part-17
- aynl-part-18
- aynl-part-19
- aynl-part-20
- aynl-part-21
- aynl-part-22
- aynl-part-23
- aynl-part-24
- aynl-part-25
- aynl-part-26
- aynl-part-27
- aynl-part-28
- aynl-part-29
- aynl-part-30
- aynl-lexicon
- aynl-coda
as-above-so-below:
- aasb-book
- aasb-ch01-introduction
- aasb-ch02-inside-causality
- aasb-ch03-see-store
- aasb-ch04-attention
- aasb-ch05-agency
- aasb-ch06-the-loop
- aasb-ch07-poetry
- grounding-the-invariant
- isomorphism-across-eras
- prophetic-cognitive-signature
- the-book-that-doesnt-exist
attention-thesis-foundations:
- annie-jessy-curwen
- attention-driven-mind-part-1
- attention-driven-mind-part-2
- attention-driven-mind-part-3
- learning-as-hole-finding
- capability-from-recognition
- streams-with-gaps-invariant
- fleet-wide-attention
- bidirectional-attention-thesis
- bedrock
creating-tools:
- oculus-cli
- cmd-peek
- cmd-poke
- cmd-fence
- how-to-create-oculus-tool
- required-reading
- fence-params
graphnode-essentials:
- pattern-graphnode-anatomy
- pattern-looking-glass-development
- cmd-poke
- cmd-peek
peregrine-basics:
- peregrine
- peregrine-fundamentals
- peregrine-pipelines
- peregrine-tools
peregrine-development-core:
- component-peregrine-framework
- peregrine-configuration-language
- peregrine-system-architecture
- topic-peregrine-handler-pattern
- topic-peregrine-activity-pattern
- topic-peregrine-actor-pattern
- topic-peregrine-factory-patterns
- topic-peregrine-schema-validation
- topic-peregrine-state-management
- peregrine-handler-library
peregrine-development-tools:
- peregrine-tools
- topic-peregrine-tool-wrappers
- topic-peregrine-commandbuilder-metadata
- topic-peregrine-notifications
- topic-peregrine-ecs-deployment-flow
- topic-peregrine-version-strategy
- topic-peregrine-rotation-patterns
- how-to-create-dynamic-pipeline
peregrine-training-onboarding:
- nightingale-vscode-copilot-guide
- peregrine-fundamentals
- peregrine-training-guide
- peregrine-training-index
- peregrine-training-initiative
- catalog-peregrine-archetypes
- peregrine-component-library
- peregrine-training-user-guide
peregrine-training-setup:
- nightingale-vscode-copilot-guide
- peregrine-training-taxonomy
- peregrine
- peregrine-fundamentals
- peregrine-training-guide
- catalog-peregrine-archetypes
- peregrine-component-library
- peregrine-training-transcript-import-process
- peregrine-training-setup-guide
pipeline-investigation:
- peregrine
- peregrine-system-architecture
- peregrine-configuration-language
- catalog-peregrine-archetypes
- peregrine-iterator-pattern
- peregrine-component-iterator
- pipeline-v1-v2-functor
- pipeline-v1-to-v2-migration-rules
streams-thesis-onboarding:
- spatial-software-engineering-patterns
- ronald-hyatt-conjecture
- lebowski-corollary
- dafoe-corollary
- william-hung-principle
- research-prior-art-streams-with-gaps
- wanderland-paper
- article-middleware-for-your-mind
test-list: '["a", "b", "c"]'
wanderland-clients:
- wanderland-clients
- wanderland-client-sync-howto
- neovim-wanderland
- oculus-cli
- toodles-manual
- oculus-client-api
wanderland-maintenance:
- wanderland-maintenance
- stuffy-api-reference
- component-task-api
- oculus
- oculus-cli
wanderland-thesis:
- wonderfully-weird
- yoneda-lemon
- structural-isomorphism-thesis
- streams-all-the-way-down
- theoretical-foundations-streams-with-gaps
- streams-with-gaps-invariant
- ronald-hyatt-conjecture
- lebowski-corollary
- dafoe-corollary
- capability-from-recognition
- capability-follows-recognition
- wanderland-paper
- wanderland-paper-verification
- standard-model-as-protocol
- yukawa-hierarchy-analogues

Slots

North

slots:
- slug: oculus-cli
  context:
  - Linking required-reading to CLI parent

South

slots:
- slug: snappy-book-example
  context:
  - Linking snappy example to required-reading

East

slots:
- slug: pattern-secondary-node-cache
  context:
  - Adding to builder required reading

West

slots: []

East

Required Reading Readings

Readings

Provenance

Document

  • Status: πŸ”΄ Unverified

Fences

required-reading-how-to-use-fence-0

  • Status: πŸ”΄ Unverified

required-reading-how-to-use-fence-1

  • Status: πŸ”΄ Unverified

required-reading-how-to-use-fence-2

  • Status: πŸ”΄ Unverified

required-reading-get-reading-lists-fence-0

  • Status: πŸ”΄ Unverified

required-reading-debug-peek-fence-0

  • Status: πŸ”΄ Unverified

required-reading-rss-reading-list-fence-0

  • Status: πŸ”΄ Unverified

required-reading-get-reading-list-fence-0

  • Status: πŸ”΄ Unverified

required-reading-add-to-reading-list-fence-0

  • Status: πŸ”΄ Unverified

required-reading-execute-reading-list-fence-0

  • Status: πŸ”΄ Unverified

required-reading-readings-fence-0

  • Status: πŸ”΄ Unverified

required-reading-north-fence-0

  • Status: πŸ”΄ Unverified

required-reading-south-fence-0

  • Status: πŸ”΄ Unverified

required-reading-east-fence-0

  • Status: πŸ”΄ Unverified

required-reading-west-fence-0

  • Status: πŸ”΄ Unverified

South

↑ northoculus-cli
↓ southsnappy-book-example
β†’ eastpattern-secondary-node-cache