agent-builder/.claude/plans/blueprints/session-4-paperclip.md
Kjell Tore Guttormsen 1a776bdeb2 docs(plans): create session blueprints for Agent Factory execution
8 session blueprints covering all 27 steps across 3 waves:
- Session 1: Foundation (rename + commands, Steps 1-5)
- Session 2: Skills and templates (Steps 6-7)
- Session 3: OpenClaw patterns (memory/heartbeat/proactive/cron, Steps 9-12)
- Session 4: Paperclip patterns (context/goals/budget/governance/org-chart, Steps 14-18)
- Session 5: Self-learning (feedback/optimization, Steps 20-21)
- Session 6: Integration (Docker/transfer/5 more domains, Steps 22-24)
- Session 7: Skill updates (memory/autonomy/orchestration/governance/MCP refs, Steps 13,19,25)
- Session 8: Finalization (build command integration + v1.0, Steps 8,26,27)

Also updates plan assumptions table with verified findings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 11:21:17 +02:00

22 KiB
Raw Blame History

Session 4: Paperclip Orchestration Patterns

Steps 14, 15, 16, 17, 18 | Wave 1 | Depends on: none

Dependencies

Entry condition: none (creates new template directories only, plus 2 new files in heartbeat/)

Scope Fence

Touch:

  • scripts/templates/heartbeat/context-packet.md (new)
  • scripts/templates/heartbeat/wake-prompt.md (new)
  • scripts/templates/goals/GOALS.md (new)
  • scripts/templates/goals/goal-tracker.sh (new)
  • scripts/templates/goals/README.md (new)
  • scripts/templates/budget/budget-hook.sh (new)
  • scripts/templates/budget/BUDGET.md (new)
  • scripts/templates/budget/budget-report.sh (new)
  • scripts/templates/budget/README.md (new)
  • scripts/templates/governance/GOVERNANCE.md (new)
  • scripts/templates/governance/approval-gate.sh (new)
  • scripts/templates/governance/README.md (new)
  • scripts/templates/org-chart/ORG-CHART.md (new)
  • scripts/templates/org-chart/org-manager.sh (new)
  • scripts/templates/org-chart/README.md (new)

Never touch:

  • commands/
  • agents/
  • skills/
  • scripts/templates/heartbeat/HEARTBEAT.md (Session 3)
  • scripts/templates/heartbeat/heartbeat-runner.sh (Session 3)
  • scripts/templates/heartbeat/README.md (Session 3)
  • scripts/templates/memory/
  • scripts/templates/proactive/
  • scripts/templates/cron/
  • .claude-plugin/, CLAUDE.md, README.md

Step 14: Create heartbeat context injection templates

Files to create

scripts/templates/heartbeat/context-packet.md — Paperclip's "Memento Man" pattern:

# Context Packet: {{AGENT_NAME}}
Generated: {{TIMESTAMP}}

## Identity
{{AGENT_IDENTITY}}

## Current Goals
{{ACTIVE_GOALS}}

## Memory State
{{MEMORY_SUMMARY}}

## Task Queue
{{PENDING_TASKS}}

## Recent Events (last 24h)
{{RECENT_EVENTS}}

## Wake Reason
{{WAKE_REASON}}

## Budget Status
Spent: {{BUDGET_SPENT}} / {{BUDGET_LIMIT}} ({{BUDGET_PERCENT}}%)
{{BUDGET_WARNING}}

scripts/templates/heartbeat/wake-prompt.md — Prompt template for each heartbeat wakeup:

You are {{AGENT_NAME}}. You are waking up for a scheduled heartbeat.

Read the context packet below carefully. It contains everything you
need to know about your current state and pending work.

{{CONTEXT_PACKET}}

Your task for this beat:
{{WAKE_REASON}}

Rules:
- Do NOT infer tasks from prior conversations
- Only work on what is in the context packet and wake reason
- If nothing needs attention, respond with HEARTBEAT_OK
- Update SESSION-STATE.md before finishing

Verify

ls /Users/ktg/repos/agent-builder/scripts/templates/heartbeat/ | wc -l

Expected: 5 (3 from Session 3 + 2 from this step)

On failure: revert

Checkpoint

git commit -m "feat(templates): add context injection templates (Paperclip heartbeat pattern)"

Step 15: Create goal hierarchy templates

Files to create

scripts/templates/goals/GOALS.md:

# Goals: {{PROJECT_NAME}}

## Company Goals
- [G1] {{COMPANY_GOAL_1}}
- [G2] {{COMPANY_GOAL_2}}

## Project Goals
- [G1.1] {{PROJECT_GOAL_1}} (parent: G1)
- [G1.2] {{PROJECT_GOAL_2}} (parent: G1)
- [G2.1] {{PROJECT_GOAL_3}} (parent: G2)

## Task Goals
- [G1.1.1] {{TASK_GOAL_1}} (parent: G1.1, owner: {{AGENT_NAME}}, status: active)
- [G1.1.2] {{TASK_GOAL_2}} (parent: G1.1, owner: {{AGENT_NAME}}, status: pending)

## Notes

Goal IDs use hierarchical dot notation. Each goal has:
- ID: unique identifier (e.g., G1.1.1)
- Description: what the goal is
- Parent: which goal this supports (simple parent reference, not recursive)
- Owner: which agent is responsible (task goals only)
- Status: active | pending | complete | blocked

scripts/templates/goals/goal-tracker.sh:

#!/bin/bash
# Goal tracker: parse and manage GOALS.md
# Bash 3.2 compatible. Uses python3 for parsing.
#
# Usage:
#   ./goal-tracker.sh                    # Show goal summary
#   ./goal-tracker.sh complete G1.1.1    # Mark goal as complete
#   ./goal-tracker.sh status             # Show status counts
#   ./goal-tracker.sh context            # Generate context for heartbeat injection
#
# Placeholders:
#   {{WORKING_DIR}} - absolute path to project directory

WORKING_DIR="{{WORKING_DIR}}"
GOALS_FILE="$WORKING_DIR/GOALS.md"
ACTION="${1:-summary}"
GOAL_ID="${2:-}"

if [ ! -f "$GOALS_FILE" ]; then
  echo "Error: $GOALS_FILE not found"
  exit 1
fi

case "$ACTION" in
  summary|status)
    python3 << PYEOF
import re

goals = []
with open("$GOALS_FILE") as f:
    for line in f:
        m = re.match(r'-\s*\[(\S+)\]\s+(.+)', line.strip())
        if m:
            gid = m.group(1)
            rest = m.group(2)
            status_m = re.search(r'status:\s*(\w+)', rest)
            parent_m = re.search(r'parent:\s*(\S+)', rest)
            owner_m = re.search(r'owner:\s*(\S+)', rest)
            status = status_m.group(1) if status_m else 'active'
            parent = parent_m.group(1).rstrip(',)') if parent_m else None
            owner = owner_m.group(1).rstrip(',)') if owner_m else None
            desc = re.sub(r'\(.*\)', '', rest).strip()
            goals.append({'id': gid, 'desc': desc, 'status': status, 'parent': parent, 'owner': owner})

# Status counts
counts = {}
for g in goals:
    counts[g['status']] = counts.get(g['status'], 0) + 1

print("Goal Status Summary")
print("=" * 40)
for status, count in sorted(counts.items()):
    print(f"  {status}: {count}")
print(f"  Total: {len(goals)}")

# Check for orphans
all_ids = set(g['id'] for g in goals)
orphans = [g for g in goals if g['parent'] and g['parent'] not in all_ids]
if orphans:
    print(f"\nOrphaned goals (parent not found):")
    for g in orphans:
        print(f"  [{g['id']}] parent: {g['parent']}")

# Goals without owners at task level
unowned = [g for g in goals if '.' in g['id'] and g['id'].count('.') >= 2 and not g['owner']]
if unowned:
    print(f"\nTask goals without owners:")
    for g in unowned:
        print(f"  [{g['id']}] {g['desc']}")
PYEOF
    ;;

  complete)
    if [ -z "$GOAL_ID" ]; then
      echo "Usage: $0 complete <goal-id>"
      exit 1
    fi
    python3 -c "
import re
goal_id = '$GOAL_ID'
with open('$GOALS_FILE') as f:
    content = f.read()
# Replace status for the specific goal
pattern = r'(\[' + re.escape(goal_id) + r'\][^)]*status:\s*)\w+'
if re.search(pattern, content):
    content = re.sub(pattern, r'\1complete', content)
    with open('$GOALS_FILE', 'w') as f:
        f.write(content)
    print(f'Goal {goal_id} marked as complete')
else:
    print(f'Goal {goal_id} not found or has no status field')
"
    ;;

  context)
    # Generate a goal summary for heartbeat context injection
    python3 << PYEOF
import re

goals = []
with open("$GOALS_FILE") as f:
    for line in f:
        m = re.match(r'-\s*\[(\S+)\]\s+(.+)', line.strip())
        if m:
            gid = m.group(1)
            rest = m.group(2)
            status_m = re.search(r'status:\s*(\w+)', rest)
            status = status_m.group(1) if status_m else 'active'
            desc = re.sub(r'\(.*\)', '', rest).strip()
            goals.append({'id': gid, 'desc': desc, 'status': status})

active = [g for g in goals if g['status'] == 'active']
if active:
    print("Active goals:")
    for g in active:
        print(f"  [{g['id']}] {g['desc']}")
else:
    print("No active goals.")
PYEOF
    ;;

  *)
    echo "Usage: $0 [summary|complete <id>|status|context]"
    exit 1
    ;;
esac

scripts/templates/goals/README.md:

# Goal Hierarchy

File-based goal hierarchy inspired by Paperclip's goal system.

## Design decisions

- **Simple parent_id, not recursive**: Each goal references its parent by ID.
  No recursive traversal at runtime — matching Paperclip's actual implementation
  (not their aspirational docs which describe "full ancestry").
- **Dot notation for hierarchy**: G1 → G1.1 → G1.1.1 makes the hierarchy visible
  in the ID itself.
- **File-based, not database**: Human-editable, version-controlled, no dependencies.

## Goal levels

| Level | ID pattern | Example | Description |
|-------|-----------|---------|-------------|
| Company | G1, G2 | G1 | Top-level organizational goals |
| Project | G1.1, G1.2 | G1.1 | Goals that support a company goal |
| Task | G1.1.1 | G1.1.1 | Specific tasks assigned to agents |

## Usage

```bash
# View goal summary
./goal-tracker.sh

# Mark a task as complete
./goal-tracker.sh complete G1.1.1

# Generate context for heartbeat injection
./goal-tracker.sh context

Integration with heartbeat

The context command produces a summary suitable for injection into the heartbeat context packet (see scripts/templates/heartbeat/context-packet.md). The heartbeat runner can call ./goal-tracker.sh context and inject the output as {{ACTIVE_GOALS}}.


### Verify

```bash
bash -n /Users/ktg/repos/agent-builder/scripts/templates/goals/goal-tracker.sh && echo "VALID"

Expected: VALID

On failure: retry — fix bash syntax, then revert

Checkpoint

git commit -m "feat(templates): add goal hierarchy templates (Paperclip pattern)"

Step 16: Create budget tracking templates

Files to create

scripts/templates/budget/BUDGET.md:

# Budget Policy: {{PROJECT_NAME}}

## Company Budget
- window: {{BUDGET_WINDOW}}
- limit: {{BUDGET_LIMIT_CENTS}} cents
- warn_percent: 80
- hard_stop: true

## Agent Budgets
- {{AGENT_NAME}}: {{AGENT_BUDGET_CENTS}} cents/{{BUDGET_WINDOW}}

## Notification
- on_warn: log
- on_hard_stop: pause

## Notes

Budget enforcement is POST-HOC (checked after each run, not before).
This matches Paperclip's proven approach: check SUM(cost) after run,
pause if exceeded. No pre-run reservation needed.

Cost estimation uses token counts × published pricing. For accurate
cost data, organizations can use the Admin API:
`/v1/organizations/cost_report` (requires Admin API key: sk-ant-admin...).

For headless runs, use `claude -p --max-budget-usd N` as a per-run cap.

scripts/templates/budget/budget-hook.sh:

#!/bin/bash
# PostToolUse hook: Log cost events and enforce budget.
# Bash 3.2 compatible. Uses python3 for JSON parsing.
#
# Follows Paperclip's post-hoc enforcement pattern:
# 1. Log cost event after each tool call
# 2. Check cumulative cost against budget policy
# 3. Warn at soft threshold, pause at hard threshold
#
# Placeholders:
#   {{WORKING_DIR}} - absolute path to project directory

WORKING_DIR="{{WORKING_DIR}}"
BUDGET_DIR="$WORKING_DIR/budget"
COST_LOG="$BUDGET_DIR/cost-events.jsonl"
BUDGET_FILE="$WORKING_DIR/BUDGET.md"
PAUSED_FLAG="$BUDGET_DIR/PAUSED"

mkdir -p "$BUDGET_DIR"

# Read hook input
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null)

# Log cost event
python3 << PYEOF
import json, sys, time, os

try:
    data = json.loads('''$INPUT''')
except:
    sys.exit(0)

tool_name = data.get('tool_name', '')
# Estimate cost from token counts if available in tool result
# This is a rough estimate; actual costs come from the Admin API
event = {
    'timestamp': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
    'tool_name': tool_name,
    'agent': os.environ.get('AGENT_NAME', 'unknown'),
    'estimated_tokens': 0
}

cost_log = "$COST_LOG"
with open(cost_log, 'a') as f:
    f.write(json.dumps(event) + '\n')
PYEOF

# Check budget if BUDGET.md exists
if [ -f "$BUDGET_FILE" ] && [ -f "$COST_LOG" ]; then
  BUDGET_CHECK=$(python3 << 'PYEOF'
import re, json, os

budget_file = os.environ.get('BUDGET_FILE', '')
cost_log = os.environ.get('COST_LOG', '')
paused_flag = os.environ.get('PAUSED_FLAG', '')

if not budget_file or not cost_log:
    print("ok")
    exit(0)

# Parse budget
try:
    content = open(budget_file).read()
    limit_m = re.search(r'limit:\s*(\d+)\s*cents', content)
    warn_m = re.search(r'warn_percent:\s*(\d+)', content)
    hard_m = re.search(r'hard_stop:\s*(\w+)', content)
    if not limit_m:
        print("ok")
        exit(0)
    limit = int(limit_m.group(1))
    warn_pct = int(warn_m.group(1)) if warn_m else 80
    hard_stop = hard_m.group(1).lower() == 'true' if hard_m else True
except:
    print("ok")
    exit(0)

# Sum cost events (count events as rough proxy — actual cost tracking
# requires Admin API or token counting from responses)
try:
    event_count = sum(1 for _ in open(cost_log))
except:
    event_count = 0

# Rough estimate: each event ~ 1 cent (placeholder — customize per model)
estimated_cents = event_count

pct = (estimated_cents / limit * 100) if limit > 0 else 0

if pct >= 100 and hard_stop:
    open(paused_flag, 'w').write(f'Budget exceeded: {estimated_cents}/{limit} cents')
    print("hard_stop")
elif pct >= warn_pct:
    print("warn")
else:
    print("ok")
PYEOF
  )

  BUDGET_FILE="$BUDGET_FILE" COST_LOG="$COST_LOG" PAUSED_FLAG="$PAUSED_FLAG" \
  BUDGET_RESULT=$(BUDGET_FILE="$BUDGET_FILE" COST_LOG="$COST_LOG" PAUSED_FLAG="$PAUSED_FLAG" python3 -c "
import re, json, os
budget_file = '$BUDGET_FILE'
cost_log = '$COST_LOG'
paused_flag = '$PAUSED_FLAG'
try:
    content = open(budget_file).read()
    limit_m = re.search(r'limit:\s*(\d+)\s*cents', content)
    if not limit_m: print('ok'); exit(0)
    limit = int(limit_m.group(1))
    warn_m = re.search(r'warn_percent:\s*(\d+)', content)
    warn_pct = int(warn_m.group(1)) if warn_m else 80
    hard_m = re.search(r'hard_stop:\s*(\w+)', content)
    hard_stop = hard_m.group(1).lower() == 'true' if hard_m else True
    event_count = sum(1 for _ in open(cost_log))
    estimated_cents = event_count
    pct = (estimated_cents / limit * 100) if limit > 0 else 0
    if pct >= 100 and hard_stop:
        open(paused_flag, 'w').write(f'Budget exceeded: {estimated_cents}/{limit} cents')
        print('hard_stop')
    elif pct >= warn_pct:
        print('warn')
    else:
        print('ok')
except Exception as e:
    print('ok')
" 2>/dev/null)

  if [ "$BUDGET_RESULT" = "hard_stop" ]; then
    echo "BUDGET EXCEEDED — agent paused. Check $PAUSED_FLAG" >&2
  elif [ "$BUDGET_RESULT" = "warn" ]; then
    echo "BUDGET WARNING — approaching limit" >&2
  fi
fi

# Check if agent is paused
if [ -f "$PAUSED_FLAG" ]; then
  echo '{"decision": "block", "reason": "Agent paused: budget exceeded. Remove '"$PAUSED_FLAG"' to resume."}' 
  exit 2
fi

exit 0

scripts/templates/budget/budget-report.sh:

#!/bin/bash
# Budget report: summarize cost events and compare against policy.
# Bash 3.2 compatible. Uses python3 for aggregation.
#
# Usage: ./budget-report.sh
#
# Placeholders:
#   {{WORKING_DIR}} - absolute path to project directory

WORKING_DIR="{{WORKING_DIR}}"
COST_LOG="$WORKING_DIR/budget/cost-events.jsonl"
BUDGET_FILE="$WORKING_DIR/BUDGET.md"
PAUSED_FLAG="$WORKING_DIR/budget/PAUSED"

if [ ! -f "$COST_LOG" ]; then
  echo "No cost events recorded yet."
  exit 0
fi

python3 << PYEOF
import json, re, os
from collections import defaultdict

cost_log = "$COST_LOG"
budget_file = "$BUDGET_FILE"
paused_flag = "$PAUSED_FLAG"

# Read events
events = []
with open(cost_log) as f:
    for line in f:
        line = line.strip()
        if line:
            try:
                events.append(json.loads(line))
            except:
                pass

# Aggregate
by_agent = defaultdict(int)
by_day = defaultdict(int)
by_tool = defaultdict(int)

for e in events:
    agent = e.get('agent', 'unknown')
    day = e.get('timestamp', '')[:10]
    tool = e.get('tool_name', 'unknown')
    by_agent[agent] += 1
    by_day[day] += 1
    by_tool[tool] += 1

print("BUDGET REPORT")
print("=" * 50)
print(f"Total events: {len(events)}")
print()

# Per-agent breakdown
print("By Agent:")
for agent, count in sorted(by_agent.items(), key=lambda x: -x[1]):
    print(f"  {agent}: {count} events")
print()

# Per-day breakdown (last 7 days)
print("By Day (last 7):")
for day, count in sorted(by_day.items())[-7:]:
    print(f"  {day}: {count} events")
print()

# Budget comparison
if os.path.exists(budget_file):
    content = open(budget_file).read()
    limit_m = re.search(r'limit:\s*(\d+)\s*cents', content)
    if limit_m:
        limit = int(limit_m.group(1))
        est_cents = len(events)  # rough proxy
        pct = (est_cents / limit * 100) if limit > 0 else 0
        print(f"Budget: ~{est_cents}/{limit} cents ({pct:.0f}%)")

# Paused status
if os.path.exists(paused_flag):
    print(f"\n!! AGENT PAUSED: {open(paused_flag).read().strip()}")
    print(f"   Remove {paused_flag} to resume")
PYEOF

scripts/templates/budget/README.md:

# Budget Tracking

Post-hoc budget enforcement inspired by Paperclip's budget system.

## How it works

1. `budget-hook.sh` runs as a PostToolUse hook after every tool call
2. Each call is logged to `budget/cost-events.jsonl`
3. After logging, cumulative cost is compared against `BUDGET.md` policy
4. If soft threshold (default 80%) exceeded: warning to stderr
5. If hard threshold (100%) exceeded and hard_stop=true: creates `budget/PAUSED`
   flag file, subsequent tool calls are blocked (exit 2)

## Why post-hoc, not pre-run?

Paperclip uses the same approach. Pre-run budget reservation requires a
persistent service or lock file coordination. Post-hoc checking is simpler
and robust enough in practice — the worst case is one extra run before pause.

## Cost estimation

The current implementation counts events as a rough proxy for cost. For
accurate cost tracking, you have two options:

1. **Admin API** (org accounts only): Query `/v1/organizations/cost_report`
   with an Admin API key (`sk-ant-admin...`). This gives actual USD costs.
2. **Token estimation**: Parse token counts from Claude's responses and
   multiply by published per-token prices. More accurate than event counting
   but still an estimate.

For headless runs, `claude -p --max-budget-usd N` provides a per-run
budget cap directly in the CLI.

## Integration

Add to `.claude/settings.json`:
```json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "*",
      "hooks": [{"type": "command", "command": "bash budget/budget-hook.sh"}]
    }]
  }
}

### Verify

```bash
bash -n /Users/ktg/repos/agent-builder/scripts/templates/budget/budget-hook.sh && bash -n /Users/ktg/repos/agent-builder/scripts/templates/budget/budget-report.sh && echo "VALID"

Expected: VALID

On failure: retry — fix bash syntax, then revert

Checkpoint

git commit -m "feat(templates): add budget tracking templates (Paperclip pattern)"

Step 17: Create governance and approval gate templates

Files to create

scripts/templates/governance/GOVERNANCE.md — See plan Step 17 for full content. Key sections:

  • Autonomy Levels (0-4 scale from full manual to full autonomy)
  • Approval Gates with {{GATE_NAME}} and {{GATE_CONDITION}} placeholders
  • Escalation Rules (budget exceeded, error threshold, unknown tool, scope violation)
  • Audit Requirements (tool calls, budget events, approvals, retention)

scripts/templates/governance/approval-gate.sh — PreToolUse hook implementing approval gates. Bash 3.2 compatible. Key behavior:

  1. Reads GOVERNANCE.md for current autonomy level
  2. Based on level, auto-approves or requires approval
  3. For gated operations: writes request to governance/pending-approvals.jsonl
  4. Checks governance/approval-responses.jsonl for matching response
  5. No response within timeout → block (exit 2)

scripts/templates/governance/README.md — Explains the governance model, autonomy levels, Paperclip's "autonomy is a privilege" philosophy.

Verify

bash -n /Users/ktg/repos/agent-builder/scripts/templates/governance/approval-gate.sh && echo "VALID"

Expected: VALID

On failure: retry — fix bash syntax, then revert

Checkpoint

git commit -m "feat(templates): add governance and approval gate templates (Paperclip pattern)"

Step 18: Create org-chart template

Files to create

scripts/templates/org-chart/ORG-CHART.md — Markdown table with columns: Agent, Role, Reports To, Status, Budget. Uses reportsTo pattern from Paperclip. Includes delegation rules and human override section.

scripts/templates/org-chart/org-manager.sh — Bash 3.2 script that:

  • Parses ORG-CHART.md table with python3
  • Validates: agents exist in .claude/agents/, no circular chains
  • Can add/remove agents from the chart
  • Generates text-based org tree visualization

scripts/templates/org-chart/README.md — Explains the simple reportsTo pattern, delegation flows, cross-team routing.

Verify

bash -n /Users/ktg/repos/agent-builder/scripts/templates/org-chart/org-manager.sh && echo "VALID"

Expected: VALID

On failure: retry — fix bash syntax, then revert

Checkpoint

git commit -m "feat(templates): add org-chart template (Paperclip pattern)"

Exit Condition

  • ls /Users/ktg/repos/agent-builder/scripts/templates/heartbeat/ | wc -l → 5
  • ls /Users/ktg/repos/agent-builder/scripts/templates/goals/ | wc -l → 3
  • ls /Users/ktg/repos/agent-builder/scripts/templates/budget/ | wc -l → 4
  • ls /Users/ktg/repos/agent-builder/scripts/templates/governance/ | wc -l → 3
  • ls /Users/ktg/repos/agent-builder/scripts/templates/org-chart/ | wc -l → 3
  • All shell scripts pass bash -n: find /Users/ktg/repos/agent-builder/scripts/templates/goals /Users/ktg/repos/agent-builder/scripts/templates/budget /Users/ktg/repos/agent-builder/scripts/templates/governance /Users/ktg/repos/agent-builder/scripts/templates/org-chart -name "*.sh" -exec bash -n {} \; → no errors
  • context-packet.md contains {{WAKE_REASON}} placeholder
  • budget-hook.sh contains reference to PAUSED flag file

Quality Criteria

  • Context packet follows Paperclip's "Memento Man" pattern with all sections
  • Wake prompt includes rules about not inferring from prior conversations
  • Goal hierarchy uses simple parent_id (not recursive) matching Paperclip's actual code
  • Budget enforcement is post-hoc matching Paperclip's pattern
  • Budget README honestly documents Admin API limitation (org-only, admin key)
  • Governance has 5 autonomy levels (0-4) with clear descriptions
  • Org chart uses simple reportsTo pattern with human override authority
  • All bash scripts are 3.2 compatible