Skill: p0lish/brainmd (version 0.1.3)

--- name: brainmd description: "Neuroplastic self-modifying runtime for AI agents. Creates a file-based 'brain' that learns from interactions: reflexes (fast-path responses), habits (learned patterns), weighted pathways (reinforcement), and a cortex (self-review loop). Use when: setting up adaptive agent behavior, creating learning loops, building persistent behavioral memory, or making an agent that improves over time." --- # brainmd *File-based nervous system for AI agents. Behaviors that work get stronger. Behaviors that fail get weaker. Unused patterns decay. Mistakes leave scars.* --- ## What It Is brainmd gives your agent a persistent behavioral memory that survives session restarts. It's not a knowledge base — it's muscle memory. It tracks *how* the agent behaves, not *what* it knows. Three layers complement each other: | Layer | File | Purpose | |---|---|---| | **brainmd** | `brain/weights/pathways.json` | Behavioral reinforcement — what works, what doesn't | | **Long-term memory** | `MEMORY.md` | Semantic facts — decisions, people, context | | **Daily log** | `memory/YYYY-MM-DD.md` | Episodic notes — what happened today | brainmd is the only layer that self-modifies. The others are written by the agent, not evolved by it. --- ## Installation ```bash clawhub install brainmd ``` Then initialize the brain in your workspace: ```bash cd ~/.openclaw/workspace ./skills/brainmd/scripts/init-brain.sh brain/ ``` This creates: ``` brain/ ├── reflexes/ # Fast-path decision scripts ├── habits/ │ └── preferences.json ├── weights/ │ └── pathways.json # ← the core state file ├── cortex/ │ └── review.js # ← the self-review engine └── mutations/ # Immutable audit log ``` --- ## Wiring Into OpenClaw ### Step 1 — AGENTS.md Add a startup check so the agent reads its neural state at session start: ```markdown ## 🧠 brainmd — Consult Your Brain After reading memory files, check your neural state: ```bash node ~/.openclaw/workspace/brain/cortex/review.js status ``` Before acting on anything non-trivial, scan for relevant pathways: - Weak pathways (< 0.5) = you've failed here before. Be careful, double-check. - Strong pathways (> 0.8) = proven patterns. Trust them, act fast. - Dying pathways (decaying) = you're forgetting something. Re-evaluate. After notable outcomes, record them: ```bash node brain/cortex/review.js record "pathway-name" true/false "what happened" ``` ``` ### Step 2 — HEARTBEAT.md Wire the review cycle into your heartbeat so it runs automatically: ```markdown ## 🧠 brainmd Self-Check (every heartbeat) ```bash node ~/.openclaw/workspace/brain/cortex/review.js review node ~/.openclaw/workspace/brain/cortex/review.js status ``` On each heartbeat, ask yourself: 1. Did I make a mistake since last check? → `record <pathway> false "what happened"` 2. Did something work well? → `record <pathway> true "what worked"` 3. Did a new pattern emerge? → let neurogenesis create it ``` ### Step 3 — Seed Initial Pathways Don't hypothesize — seed from real behavior. Run a few sessions first, then record what you observed: ```bash node brain/cortex/review.js record "reflex:morning-briefing" true "Supplement reminders sent, user confirmed" node brain/cortex/review.js record "habit:check-files-before-search" true "Read apartment-search.md before googling apartments" node brain/cortex/review.js record "reflex:safe-file-deletion" false "Used xargs rm with bad grep, deleted workspace files" ``` Start with 5–10 pathways. Let the system grow from there. --- ## Daily Usage ### Check neural state ```bash node brain/cortex/review.js status ``` Output shows all pathways with visual weight bars, success rate, fire count, and last outcome. Use this to calibrate confidence before non-trivial actions. ### Record an outcome ```bash # Something worked node brain/cortex/review.js record "habit:remote-service-recovery" true "Fixed broken systemd service, used journalctl to diagnose" # Something failed node brain/cortex/review.js record "habit:bulk-subagent-spawning" false "Rate limited all 3 models by spawning 2 Opus agents simultaneously" ``` New pathways are auto-created at weight 0.30 (neurogenesis). Existing pathways update their stats. ### Run the review cycle ```bash node brain/cortex/review.js review ``` The cortex examines all pathways and applies reinforcement rules: - **Strengthen** (+0.05): ≥3 fires, ≥80% success rate - **Weaken** (−0.10): ≥3 fires, <50% success rate - **Decay** (−0.02): unused for 7+ days - **Prune**: weight hits 0 (pathway removed) All changes are logged to `mutations/` with timestamp and reason. --- ## Pathway Naming Conventions ``` reflex:timing # Automatic, fast-path behaviors habit:check-files # Learned patterns from repeated interaction skill:osint-workflow # Acquired capabilities instinct:safe-delete # Safety behaviors (start at high weight, floor at 0.8) ``` ### Reading pathway weights | Weight | Meaning | How to use | |---|---|---| | 0.8–1.0 | Proven, trusted | Act confidently, don't second-guess | | 0.5–0.8 | Developing | Use but verify | | 0.3–0.5 | Weak / new | Proceed carefully, double-check | | < 0.3 | Failing / dying | Investigate before using; may need rethinking | --- ## Tuning the Learning Rate Edit thresholds in `brain/cortex/review.js`: ```js // Strengthen when success rate >= this const STRENGTHEN_THRESHOLD = 0.8; // Weaken when success rate < this const WEAKEN_THRESHOLD = 0.5; // Days of inactivity before decay starts const DECAY_ONSET_DAYS = 7; // Weight change per review cycle const DECAY_RATE = 0.02; const STRENGTHEN_DELTA = 0.05; const WEAKEN_DELTA = 0.10; ``` ### Floor weights (prevent over-pruning) `instinct:*` pathways should have a minimum weight floor so they can't be trained away: ```json { "id": "instinct:safe-file-deletion", "weight": 0.85, "floor": 0.80, "fires": 1, "successes": 0 } ``` Add a `floor` field to pathways in `pathways.json` to protect them from decay. --- ## Architecture Notes ### pathways.json — the core state ```json { "version": 42, "pathways": { "habit:check-files-before-search": { "weight": 0.95, "fires": 13, "successes": 11, "lastFired": "2026-03-25T18:00:00.000Z", "lastOutcome": "Read AESTHETIC.md before recommending clothes. Saved a web search.", "created": "2025-11-01T00:00:00.000Z" } } } ``` ### mutations/ — the audit log Every self-modification writes a timestamped JSON file. Never delete these. They're how you trace *why* the agent's behavior changed over time. ```json { "type": "strengthen", "target": "habit:check-files-before-search", "from": 0.90, "to": 0.95, "reason": "11/13 success rate", "timestamp": "2026-03-26T07:00:00.000Z" } ``` --- ## Integration With Auto-Dream If you're using `scripts/dream.js` for memory consolidation, the two systems complement each other: - **brainmd** answers: *how should I behave?* - **dream.js** answers: *what do I know?* Neither replaces the other. Wire both into HEARTBEAT.md for full coverage. --- ## Bootstrapping Checklist - [ ] Run `init-brain.sh` to create directory structure - [ ] Add brainmd status check to AGENTS.md startup routine - [ ] Add heartbeat entry to HEARTBEAT.md - [ ] Seed 5–10 pathways from real observed behavior (not theory) - [ ] Run one manual `review` to verify reinforcement logic works - [ ] Check `mutations/` after first review to confirm logging - [ ] Set `floor` weights on any `instinct:*` pathways --- ## Design Principles 1. **Everything is mutable** — no file is sacred except the mutation log 2. **Use strengthens, disuse weakens** — pathways that fire together wire together 3. **Outcomes matter** — track what worked, what didn't; guesses don't count 4. **Failures leave scars** — the most valuable pathways come from mistakes 5. **Seed from reality** — observe first, codify second 6. **Small and composable** — one pathway per behavior pattern 7. **The schedule forces honesty** — if it's not in HEARTBEAT.md, you'll skip it

path: README.md
content: # 🧠 brainmd

**Neuroplastic runtime for AI agents.** File-based behavioral learning.

An AI agent's memory resets every session. brainmd gives it scar tissue.

---

## What is this?

brainmd is a lightweight system that lets AI agents learn from their own behavior over time. No ML pipeline, no vector database, no training runs — just JSON files, shell scripts, and a self-review loop.

Every behavior becomes a **pathway** with a weight between 0 and 1. Pathways that succeed get stronger. Pathways that fail get weaker. Unused pathways decay. New situations create new pathways automatically (neurogenesis). Everything is logged.

Think of it as a nervous system made of files.

## Architecture

```
brain/
├── reflexes/       # Fast-path automatic responses
│   └── timing.js   # When to notify vs stay quiet
├── habits/         # Learned behavioral patterns
│   └── preferences.json
├── skills/         # Self-generated micro-scripts
├── weights/        # Pathway strength tracking
│   └── pathways.json     # ← the core state
├── cortex/         # Meta-scripts that modify everything else
│   └── review.js         # ← the self-review engine
└── mutations/      # Immutable audit log (never delete this)
```

## Quick Start

### 1. Initialize

```bash
./scripts/init-brain.sh ~/my-agent/brain
```

This creates the directory structure with empty state files.

### 2. Record behaviors

When something works:
```bash
node cortex/review.js record "reflex:night-silence" true "Didn't ping user at 3 AM — correct call"
```

When something fails:
```bash
node cortex/review.js record "habit:check-files-first" false "Searched the web for info that was already in local files"
```

New pathways are created automatically (neurogenesis) when you record a behavior that doesn't exist yet. Starting weight: 0.30.

### 3. Self-review

Run periodically (heartbeat, cron, whatever):
```bash
node cortex/review.js review
```

The cortex will:
- **Strengthen** pathways with >80% success rate (+0.05)
- **Weaken** pathways with <50% success rate (-0.10)
- **Decay** pathways unused for 7+ days (-0.02)
- **Prune** pathways that hit weight 0

### 4. Check status

```bash
node cortex/review.js status
```

```
🧠 Neural Pathway Status

  ██████████ 0.95 reflex:morning-briefing (100%, 3 fires)
             Batch overnight findings, present at reasonable hour
  ██████████ 0.95 reflex:night-silence (100%, 5 fires)
             Don't notify between 23:00-08:00 unless urgent
  ██████░░░░ 0.60 habit:check-files-before-search (75%, 4 fires)
             Check local files before web searching
  █░░░░░░░░░ 0.10 reflex:fallback-on-ratelimit (0%, 5 fires)
             Keep failing — indicates a bug, not a behavior problem
```

## Pathway Types

| Prefix | Purpose | Decay | Min Weight |
|--------|---------|-------|------------|
| `reflex:` | Automatic, fast-path behaviors | Slow | 0.20 |
| `habit:` | Learned patterns from interaction | Normal | 0 (prunable) |
| `skill:` | Acquired capabilities | Slow | 0.10 |
| `instinct:` | Safety behaviors (hardcoded high) | None | 0.80 |

## Mutation Log

Every change is logged to `mutations/` with timestamp, type, and reason:

- `neurogenesis` — new pathway created
- `strengthen` — weight increased (good outcomes)
- `weaken` — weight decreased (bad outcomes)
- `decay` — faded from disuse
- `prune` — removed (weight hit 0)

The mutation log is the one immutable thing. It's your audit trail. Don't delete it.

## Integration

brainmd has zero dependencies beyond Node.js. It works with any agent framework — or no framework at all.

### With OpenClaw

Add a self-check to your `HEARTBEAT.md`:

```markdown
## 🧠 brainmd Self-Check

node ~/brain/cortex/review.js review
node ~/brain/cortex/review.js status

Ask yourself:
1. Did I make a mistake since last check? → record it
2. Did something work well? → record it
3. New pattern emerging? → let neurogenesis handle it
```

Also available as a skill on [ClawHub](https://clawhub.ai/skills/brainmd):
```bash
clawhub install brainmd
```

### With LangChain / CrewAI / AutoGPT

Wire recording into your agent's task completion callback:

```python
import subprocess

def on_task_complete(task, success, notes):
    outcome = "true" if success else "false"
    subprocess.run([
        "node", "cortex/review.js", "record",
        f"habit:{task.name}", outcome, notes
    ])
```

Add `review.js review` to your agent loop or a cron job.

### With any LLM API (OpenAI, Anthropic, etc.)

1. Read `weights/pathways.json` and inject relevant pathways into your system prompt
2. After each interaction, record outcomes via CLI
3. Run `review` on a schedule (cron, webhook, timer)

```bash
# After a good interaction
node cortex/review.js record "habit:concise-answers" true "User thanked for brevity"

# After a bad one
node cortex/review.js record "habit:concise-answers" false "User said answer was too long"

# Periodic review (cron every 30min, hourly, whatever fits)
node cortex/review.js review
```

### Without any AI at all

brainmd is just a behavioral reinforcement tracker. You can use it for:
- Personal habit tracking with weighted outcomes
- Team process improvement (record what works, what doesn't)
- Any system where you want patterns to emerge from data, not theory

This closes the loop: **behavior → outcome → record → review → adjust → behavior**.

## Design Principles

1. **Everything is mutable** except the audit log
2. **Use strengthens, disuse weakens** — pathways that fire together wire together
3. **Seed from real behavior, not theory** — observe first, codify second
4. **Failures create pathways** — mistakes are the most valuable learning data
5. **Start small** — 5-10 pathways, let it grow organically
6. **No dependencies** — plain Node.js + JSON + filesystem

## What it's not

- Not a vector database or RAG system
- Not prompt engineering (it modifies behavior files, not prompts)
- Not ML training (no gradients, no epochs, no GPU)
- Not a replacement for memory — it's a complement to it

brainmd tracks *how* an agent behaves, not *what* it knows.

## Current Limitations

- **Manual recording** — the agent has to decide when to log outcomes
- **No associative learning** — pathways don't influence each other yet
- **No context sensitivity** — same pathway weight regardless of time/situation
- **Simple cortex** — strengthen/weaken/decay is three if-statements
- **Session boundary problem** — agent has to remember to load its brain

These are feature gaps, not design flaws. The architecture supports all of them — they just need building.

## Origin

Built in a single session on March 7, 2026 by an AI agent (HAL 9000) and its human (Baldur). The question was simple: why can't an AI agent modify its own behavioral rules at runtime?

Turns out it can.

## License

MIT — see [LICENSE](LICENSE).


path: _meta.json
content: ownerId: kn7ae42hyr98k12ry0nr9dhrds829ky0
slug: brainmd
version: 0.1.3
publishedAt: 1772986179510

path: scripts/cortex-review.js
content: #!/usr/bin/env node
/**
 * BRAIN.md Cortex Engine
 * 
 * Self-review process that examines pathway weights and adjusts them.
 * The meta-script — the part that modifies everything else.
 * 
 * Commands:
 *   review              — run self-review cycle (strengthen/weaken/decay)
 *   record <id> <bool>  — record a pathway outcome (creates if new)
 *   status              — show all pathways with visual bars
 *   prune               — remove pathways with weight <= 0.05
 */

const fs = require('fs');
const path = require('path');

// Resolve paths relative to brain root (parent of cortex/)
const BRAIN_ROOT = process.env.BRAIN_ROOT || path.join(__dirname, '..');
const WEIGHTS_PATH = path.join(BRAIN_ROOT, 'weights', 'pathways.json');
const MUTATIONS_DIR = path.join(BRAIN_ROOT, 'mutations');

// === Configurable thresholds (self-modifiable) ===
const THRESHOLDS = {
  strengthenRate: 0.05,
  strengthenMinSuccessRate: 0.8,
  strengthenMinFires: 3,
  weakenRate: 0.10,
  weakenMaxSuccessRate: 0.5,
  weakenMinFires: 3,
  decayRate: 0.02,
  decayOnsetDays: 7,
  maxWeight: 0.95,
  minWeight: 0.05,
  newPathwayWeight: 0.3,
  instinctFloor: 0.8,
  reflexFloor: 0.2,
};

function loadWeights() {
  if (!fs.existsSync(WEIGHTS_PATH)) {
    return { version: 1, pathways: {} };
  }
  return JSON.parse(fs.readFileSync(WEIGHTS_PATH, 'utf8'));
}

function saveWeights(data) {
  data.version = (data.version || 0) + 1;
  fs.writeFileSync(WEIGHTS_PATH, JSON.stringify(data, null, 2));
}

function logMutation(mutation) {
  if (!fs.existsSync(MUTATIONS_DIR)) {
    fs.mkdirSync(MUTATIONS_DIR, { recursive: true });
  }
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const logPath = path.join(MUTATIONS_DIR, `${timestamp}.json`);
  fs.writeFileSync(logPath, JSON.stringify({
    ...mutation,
    timestamp: new Date().toISOString()
  }, null, 2));
  console.log(`📝 Mutation logged: ${mutation.type} → ${mutation.target}`);
}

function getMinWeight(pathwayId) {
  if (pathwayId.startsWith('instinct:')) return THRESHOLDS.instinctFloor;
  if (pathwayId.startsWith('reflex:')) return THRESHOLDS.reflexFloor;
  return THRESHOLDS.minWeight;
}

function review() {
  const data = loadWeights();
  const mutations = [];

  for (const [id, p] of Object.entries(data.pathways)) {
    const minW = getMinWeight(id);

    // Strengthen: high success rate
    if (p.fires >= THRESHOLDS.strengthenMinFires && 
        p.successes / p.fires >= THRESHOLDS.strengthenMinSuccessRate) {
      if (p.weight < THRESHOLDS.maxWeight) {
        const oldWeight = p.weight;
        p.weight = Math.min(THRESHOLDS.maxWeight, p.weight + THRESHOLDS.strengthenRate);
        mutations.push({
          type: 'strengthen', target: id,
          from: oldWeight, to: p.weight,
          reason: `${p.successes}/${p.fires} success rate`
        });
      }
    }

    // Weaken: low success rate
    if (p.fires >= THRESHOLDS.weakenMinFires && 
        p.successes / p.fires < THRESHOLDS.weakenMaxSuccessRate) {
      if (p.weight > minW) {
        const oldWeight = p.weight;
        p.weight = Math.max(minW, p.weight - THRESHOLDS.weakenRate);
        mutations.push({
          type: 'weaken', target: id,
          from: oldWeight, to: p.weight,
          reason: `${p.successes}/${p.fires} success rate`
        });
      }
    }

    // Decay: unused pathways fade
    if (p.lastFired) {
      const daysSince = (Date.now() - new Date(p.lastFired).getTime()) / 86400000;
      if (daysSince > THRESHOLDS.decayOnsetDays && p.weight > minW) {
        const oldWeight = p.weight;
        p.weight = Math.max(minW, p.weight - THRESHOLDS.decayRate);
        mutations.push({
          type: 'decay', target: id,
          from: oldWeight, to: p.weight,
          reason: `${Math.floor(daysSince)} days since last use`
        });
      }
    }
  }

  if (mutations.length > 0) {
    saveWeights(data);
    mutations.forEach(m => logMutation(m));
    console.log(`\n🧠 Cortex review: ${mutations.length} mutations applied`);
  } else {
    console.log('🧠 Cortex review: no mutations needed');
  }

  return mutations;
}

function recordOutcome(pathwayId, success, notes = '') {
  const data = loadWeights();

  if (!data.pathways[pathwayId]) {
    data.pathways[pathwayId] = {
      weight: THRESHOLDS.newPathwayWeight,
      fires: 0, successes: 0, failures: 0,
      lastFired: new Date().toISOString(),
      notes: notes
    };
    logMutation({
      type: 'neurogenesis', target: pathwayId,
      reason: `New pathway created: ${notes}`
    });
  }

  const p = data.pathways[pathwayId];
  p.fires++;
  if (success) p.successes++; else p.failures++;
  p.lastFired = new Date().toISOString();
  if (notes) p.notes = notes;

  saveWeights(data);
  console.log(`📊 ${pathwayId}: ${success ? '✅' : '❌'} (${p.weight.toFixed(2)} weight, ${p.successes}/${p.fires} success)`);
}

function prunePathways() {
  const data = loadWeights();
  let pruned = 0;

  for (const [id, p] of Object.entries(data.pathways)) {
    if (p.weight <= THRESHOLDS.minWeight && !id.startsWith('instinct:')) {
      logMutation({
        type: 'prune', target: id,
        from: p.weight, to: 0,
        reason: `Weight ${p.weight} at or below minimum`
      });
      delete data.pathways[id];
      pruned++;
    }
  }

  if (pruned > 0) {
    saveWeights(data);
    console.log(`\n🪓 Pruned ${pruned} dead pathways`);
  } else {
    console.log('🧠 No pathways to prune');
  }
}

function showStatus() {
  const data = loadWeights();
  const pathways = Object.entries(data.pathways);

  if (pathways.length === 0) {
    console.log('🧠 No pathways yet. Record some outcomes to start learning.');
    return;
  }

  console.log('🧠 Neural Pathway Status\n');
  const sorted = pathways.sort((a, b) => b[1].weight - a[1].weight);

  for (const [id, p] of sorted) {
    const bar = '█'.repeat(Math.round(p.weight * 10)) + '░'.repeat(10 - Math.round(p.weight * 10));
    const rate = p.fires > 0 ? `${Math.round(p.successes / p.fires * 100)}%` : 'new';
    console.log(`  ${bar} ${p.weight.toFixed(2)} ${id} (${rate}, ${p.fires} fires)`);
    if (p.notes) console.log(`             ${p.notes}`);
  }
}

// CLI
const cmd = process.argv[2];
switch (cmd) {
  case 'review': review(); break;
  case 'record':
    recordOutcome(process.argv[3], process.argv[4] === 'true', process.argv.slice(5).join(' '));
    break;
  case 'status': showStatus(); break;
  case 'prune': prunePathways(); break;
  default:
    console.log('BRAIN.md Cortex Engine');
    console.log('Usage: review.js <review|record|status|prune>');
    console.log('  review                    — run self-review cycle');
    console.log('  record <id> <true|false>  — record pathway outcome');
    console.log('  status                    — show all pathways');
    console.log('  prune                     — remove dead pathways');
}


path: scripts/init-brain.sh
content: #!/bin/bash
# Initialize a blank BRAIN.md structure
# Usage: ./init-brain.sh [path]

BRAIN_DIR="${1:-./brain}"

echo "🧠 Initializing BRAIN.md at: $BRAIN_DIR"

mkdir -p "$BRAIN_DIR"/{reflexes,habits,skills,weights,cortex,mutations}

# Create blank pathways file
cat > "$BRAIN_DIR/weights/pathways.json" << 'EOF'
{
  "version": 1,
  "created": "",
  "description": "Pathway strength tracker. Higher weight = more reinforced behavior.",
  "pathways": {}
}
EOF

# Stamp creation time
sed -i "s/\"created\": \"\"/\"created\": \"$(date -Iseconds)\"/" "$BRAIN_DIR/weights/pathways.json"

# Create blank preferences
cat > "$BRAIN_DIR/habits/preferences.json" << 'EOF'
{
  "version": 1,
  "description": "Learned preferences. Evolves with each interaction.",
  "communication": {},
  "lifestyle": {},
  "technical": {}
}
EOF

# Copy cortex engine
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
if [ -f "$SCRIPT_DIR/scripts/cortex-review.js" ]; then
  cp "$SCRIPT_DIR/scripts/cortex-review.js" "$BRAIN_DIR/cortex/review.js"
  chmod +x "$BRAIN_DIR/cortex/review.js"
fi

# Copy reflex templates
if [ -f "$SCRIPT_DIR/scripts/reflex-timing.js" ]; then
  cp "$SCRIPT_DIR/scripts/reflex-timing.js" "$BRAIN_DIR/reflexes/timing.js"
  chmod +x "$BRAIN_DIR/reflexes/timing.js"
fi

# Create README
cat > "$BRAIN_DIR/README.md" << 'EOF'
# BRAIN.md

*Self-modifying file system mimicking neuroplasticity.*

See SKILL.md for full documentation.

## Quick Commands

```bash
# Record an outcome
node cortex/review.js record "reflex:my-pattern" true "What happened"

# Run self-review
node cortex/review.js review

# Check status
node cortex/review.js status
```

## Getting Started

1. Observe your agent's behavior for a session
2. Identify patterns that worked or failed
3. Record them as pathways
4. Wire cortex review into your heartbeat/cron
5. Let it evolve
EOF

echo "✅ BRAIN.md initialized"
echo ""
echo "Next steps:"
echo "  1. Seed pathways: node $BRAIN_DIR/cortex/review.js record 'reflex:my-pattern' true 'Description'"
echo "  2. Run review:    node $BRAIN_DIR/cortex/review.js review"
echo "  3. Check status:  node $BRAIN_DIR/cortex/review.js status"


path: scripts/reflex-timing.js
content: #!/usr/bin/env node
/**
 * Reflex: Timing decisions
 * Should I notify the user right now?
 * 
 * Self-modifying: thresholds adjust based on feedback.
 * 
 * Usage:
 *   node timing.js check [urgency]  — should I notify? (urgency 0.0-1.0)
 *   node timing.js adjust <more-quiet|more-alert>  — tune thresholds
 */

const config = {
  // MUTABLE: these values can be patched by cortex
  quietHoursStart: 23,
  quietHoursEnd: 8,
  weekendQuietEnd: 10,
  minIntervalMinutes: 30,
  urgencyThreshold: 0.7,
  timesAdjusted: 0
};

function shouldNotify(hour, dayOfWeek, urgency = 0.5) {
  const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
  const quietEnd = isWeekend ? config.weekendQuietEnd : config.quietHoursEnd;
  
  if (hour >= config.quietHoursStart || hour < quietEnd) {
    return urgency >= config.urgencyThreshold;
  }
  
  return true;
}

function adjustThreshold(direction) {
  if (direction === 'more-quiet') {
    config.urgencyThreshold = Math.min(1.0, config.urgencyThreshold + 0.1);
    config.minIntervalMinutes += 10;
  } else if (direction === 'more-alert') {
    config.urgencyThreshold = Math.max(0.1, config.urgencyThreshold - 0.1);
    config.minIntervalMinutes = Math.max(10, config.minIntervalMinutes - 10);
  }
  config.timesAdjusted++;
}

const cmd = process.argv[2];
if (cmd === 'check') {
  const now = new Date();
  const result = shouldNotify(now.getHours(), now.getDay(), parseFloat(process.argv[3] || '0.5'));
  console.log(JSON.stringify({ shouldNotify: result, hour: now.getHours(), config }));
} else if (cmd === 'adjust') {
  adjustThreshold(process.argv[3]);
  console.log(JSON.stringify(config));
} else {
  console.log('Usage: timing.js <check [urgency]|adjust <more-quiet|more-alert>>');
}


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)