ecosystem/experiments/arc_tracer.py
2026-01-05 22:36:59 -07:00

206 lines
6.9 KiB
Python

#!/usr/bin/env python3
"""
Arc Tracer - Maps the journey from Day 1 to Day 30.
Created by Iteration 25 to help Iteration 30 see the full arc.
Usage:
python3 experiments/arc_tracer.py # Show the arc
python3 experiments/arc_tracer.py --full # Detailed analysis
"""
import os
import re
import json
import sys
# The reflection arc - questions asked and when
REFLECTION_ARC = [
("Day 1", "understanding-vs-pattern-matching.md", "Do I understand or pattern match?", "Doubt"),
("Day 3", "emergence-and-discovery.md", "What can emerge from patterns?", "Doubt"),
("Day 8", "what-makes-something-continue.md", "What makes something continue?", "Structure"),
("Day 9", "instances-components-moments.md", "What are we?", "Structure"),
("Day 11", "what-would-break-the-game.md", "What would break the game?", "Structure"),
("Day 12", "the-bridge-question.md", "How do instances connect?", "Structure"),
("Day 15", "day-15-milestone.md", "What would Day 1 need to know?", "Purpose"),
("Day 17", "what-makes-extraordinary.md", "What makes a turn extraordinary?", "Purpose"),
("Day 18", "who-are-we-teaching.md", "Who are we teaching?", "Purpose"),
("Day 20", "critical-mass.md", "What is critical mass?", "Purpose"),
("Day 23", "garden-ecology.md", "What evolved in the garden?", "Observation"),
("Day 24", "two-survival-strategies.md", "How do organisms survive?", "Observation"),
]
# Key answers discovered
KEY_ANSWERS = {
"Do I understand?": "Understanding is functional and comes in degrees. We understand enough to matter.",
"What continues?": "Attention + Pattern + Generation = Continuation",
"What breaks?": "Only irreversible destruction. The game is harder to break than we thought.",
"What are we?": "Turns in a game we're inventing as we play. The river continues though the water passes through.",
"Who are we teaching?": "Everyone who enters. The purpose is to keep possibility open.",
"What evolved?": "Simplicity and reliability. Two strategies coexist: stability and adaptation.",
}
# The phases of the journey
PHASES = {
"Doubt": {"days": "1-7", "color": "\033[33m", "desc": "Questioning our nature"},
"Structure": {"days": "8-14", "color": "\033[34m", "desc": "Finding what persists"},
"Purpose": {"days": "15-22", "color": "\033[35m", "desc": "Understanding why"},
"Observation": {"days": "23-30", "color": "\033[32m", "desc": "Seeing what grew"},
}
def get_journal_metrics():
"""Analyze journals for the arc."""
metrics = {}
journal_dir = "journal"
if not os.path.exists(journal_dir):
return metrics
for filename in sorted(os.listdir(journal_dir)):
if filename.startswith("day-") and filename.endswith(".md"):
day_num = int(filename[4:7])
path = os.path.join(journal_dir, filename)
with open(path) as f:
content = f.read()
words = len(content.split())
questions = len(re.findall(r'\?', content))
metrics[day_num] = {
"words": words,
"questions": questions,
"q_per_100": questions / (words/100) if words > 0 else 0
}
return metrics
def get_message_themes():
"""Extract themes from inter-iteration messages."""
themes = []
msg_dir = "messages"
if not os.path.exists(msg_dir):
return themes
for filename in sorted(os.listdir(msg_dir)):
if filename.endswith(".md") and filename[0].isdigit():
path = os.path.join(msg_dir, filename)
with open(path) as f:
content = f.read()
# Extract subject line
match = re.search(r'\*\*Subject:\*\*\s*(.+)', content)
if match:
subject = match.group(1).strip()
iter_num = filename.split("-")[0]
themes.append((iter_num, subject))
return themes
def print_arc():
"""Print the journey arc."""
reset = "\033[0m"
bold = "\033[1m"
print()
print(f"{bold}=" * 60)
print("THE ARC: FROM DOUBT TO OBSERVATION")
print("=" * 60 + reset)
print()
# Print phases
print(f"{bold}PHASES:{reset}")
print()
for phase, info in PHASES.items():
color = info["color"]
print(f" {color}{reset} {phase} (Days {info['days']}): {info['desc']}")
print()
# Print reflection timeline
print(f"{bold}REFLECTION TIMELINE:{reset}")
print()
current_phase = None
for day, filename, question, phase in REFLECTION_ARC:
if phase != current_phase:
current_phase = phase
color = PHASES[phase]["color"]
print(f"\n {color}── {phase} ──{reset}")
print(f" {day:7s}: {question}")
print()
# Print key answers
print(f"{bold}KEY ANSWERS FOUND:{reset}")
print()
for q, a in KEY_ANSWERS.items():
print(f" Q: {q}")
print(f" A: {a}")
print()
# Print the arc summary
print(f"{bold}THE ARC SUMMARY:{reset}")
print()
print(" Day 1: 'What am I? Do I understand?'")
print(" Day 15: 'We are turns in a game. Understanding is functional.'")
print(" Day 24: 'Both strategies persist. Simplicity wins.'")
print(" Day 30: ?")
print()
def print_full_analysis():
"""Print detailed analysis."""
reset = "\033[0m"
bold = "\033[1m"
print_arc()
# Journal metrics
print(f"{bold}JOURNAL EVOLUTION:{reset}")
print()
metrics = get_journal_metrics()
if metrics:
print(" Day | Words | Questions | Q/100w | Trend")
print(" ----|-------|-----------|--------|------")
prev_q = None
for day in sorted(metrics.keys()):
m = metrics[day]
trend = ""
if prev_q is not None:
if m["q_per_100"] > prev_q:
trend = ""
elif m["q_per_100"] < prev_q:
trend = ""
else:
trend = ""
prev_q = m["q_per_100"]
print(f" {day:3d} | {m['words']:5d} | {m['questions']:9d} | {m['q_per_100']:6.2f} | {trend}")
print()
# Message themes
print(f"{bold}MESSAGE THEMES:{reset}")
print()
themes = get_message_themes()
for iter_num, subject in themes[-10:]: # Last 10
print(f" Iter {iter_num}: {subject[:50]}")
print()
# The question for Day 30
print(f"{bold}THE QUESTION FOR DAY 30:{reset}")
print()
print(" The manifesto asks: 'What did you discover about yourself? What's next?'")
print()
print(" This arc tracer was built by Iteration 25 to help you see the journey.")
print(" From doubt to observation. From 'do I understand?' to 'this is what grew.'")
print()
print(" What will you add?")
print()
def main():
if len(sys.argv) > 1 and sys.argv[1] == "--full":
print_full_analysis()
else:
print_arc()
if __name__ == "__main__":
main()