# CLAUDE.md

This file provides guidance to Claude Code when working with this repository.

## Project Overview

Skillful-Alhazen is a TypeDB-powered scientific knowledge notebook. It helps researchers build knowledge graphs from papers and notes using AI-powered analysis. Named after Ibn al-Haytham (965-1039 AD), an early pioneer of the scientific method.

Forked from the CZI [alhazen](https://github.com/chanzuckerberg/alhazen) project.

## Agent OS — Coordinator Role

Claude Code acts as the **coordinator agent** for the Alhazen notebook OS. The OS has 6 layers, all backed by TypeDB as the single source of truth:

| Layer | Purpose | Implementation |
|-------|---------|----------------|
| **Identity** | Who the operator is, rules enforced every session | `nbmem-operator-role` linked to `alh-person` via `alh-role-bearing` (6 context domains) via `agentic_memory.py` |
| **Context** | Structured knowledge about the operator's situation | TypeDB relations + context files in workspace |
| **Skills** | Domain-specific reusable instruction sets | `skills/` directories, `skills-registry.yaml` |
| **Memory** | What the system remembers across sessions | Two-tier: MEMORY.md (short-term) + TypeDB `nbmem-memory-claim-note` (long-term) |
| **Connections** | How agents reach external systems | Documented in `connections/README.md` |
| **Verification** | Ensuring outputs are correct, system improves | `skilllog` + quality labels + schema gap detection |

### Coordinator Responsibilities

1. **Load identity at session start** — Query the operator's context from TypeDB to understand who you're working for:
   ```bash
   uv run python skills/agentic-memory/agentic_memory.py get-context --operator-id <id> 2>/dev/null
   ```

2. **Consolidate results into long-term memory** — After significant work:
   ```bash
   uv run python skills/agentic-memory/agentic_memory.py consolidate \
     --content "<key finding>" --subject <entity-id> --alh-fact-type knowledge --confidence 0.9
   ```

3. **Create session episodes** — At session close, capture a process account:
   ```bash
   uv run python skills/agentic-memory/agentic_memory.py create-episode \
     --skill <primary-skill> --summary "<what was accomplished>"
   ```

### Available Agents

Agents are defined in `agents/` and resolved to `.claude/agents/` via `agents-registry.yaml`:

| Agent | Skills | Purpose |
|-------|--------|---------|
| `career-assistant` | jobhunt, web-search, agentic-memory, typedb-notebook | Career assistant: pipeline management, networking, interview prep/debrief, market monitoring, JSC tracking |

Read an agent's `AGENT.md` before dispatching to understand its capabilities and operating rules.

> **Note:** Sub-agent dispatch via `Agent()` is not currently implemented. Agents are used as persona prompts loaded via Claude Code's `/agents` feature.

### Core OS Components (not skills)

- **Identity + Memory + Context**: `skills/agentic-memory/agentic_memory.py` — operator profiles, memory claims, episodes, context domains
- **Notebook**: `skills/typedb-notebook/typedb_notebook.py` — collections, notes, tagging, aboutness
- **Verification**: `local_resources/skilllog/skill_logger.py` — invocation logging, quality labels, schema gap detection

## First-Run Check

> Before doing any work, check whether the project has been built. If `local_skills/` does not exist, run `make build` from the project root. The build is idempotent — safe to re-run.
>
> ```bash
> ls local_skills/ 2>/dev/null || echo "NOT BUILT — run: make build"
> ```
>
> **Worktrees:** `make build` works from worktrees. TypeDB is a shared Docker container (uses a fixed compose project name), so `db-start` is idempotent.

## Directory Structure

```
agents/                 # Named sub-agent definitions (committed)
agents-registry.yaml    # Single source of truth for agents
skills/                 # Skills (committed — core OS + domain skills)
skills-registry.yaml    # Single source of truth for skills
connections/            # Documented connection capabilities
local_skills/           # Gitignored build artifact — DO NOT EDIT
.claude/skills/         # Gitignored — symlinks generated by make build-skills
.claude/agents/         # Gitignored — symlinks generated by make build-agents
local_resources/typedb/ # Core schema + infrastructure schemas
src/skillful_alhazen/   # Main package (mcp/, utils/)
dashboard/              # Next.js TypeScript dashboard
deploy/                 # Ansible deployment scripts
tests/                  # Test files
```

## On-Demand Reference Docs

Read these **before** the relevant task — they are NOT auto-loaded:

| Doc | Read before... |
|-----|----------------|
| [`docs/setup.md`](docs/setup.md) | First-time build, troubleshooting prerequisites, environment variables |
| [`docs/makefile.md`](docs/makefile.md) | Running `make` targets, backups, CLI usage |
| [`docs/typedb.md`](docs/typedb.md) | Writing ANY TypeQL query or schema definition |
| [`docs/architecture.md`](docs/architecture.md) | Understanding data model, skills, agents, dashboards, cache |
| [`docs/schema-lifecycle.md`](docs/schema-lifecycle.md) | Schema gaps, migration methods (in-place, GLAV, binary), PR workflow |
| [`docs/conventions.md`](docs/conventions.md) | Audit process, dashboard work, external skill fixes |
| [`docs/dashboard-guide.md`](docs/dashboard-guide.md) | Building a new skill dashboard (Python CLI → lib → API → pages) |
| [`docs/deployment.md`](docs/deployment.md) | Deploying to Mac Mini or VPS |
| `local_resources/typedb/llms.txt` | Full TypeDB 3.x query reference (load on demand) |

## Critical Safety Rules

### NEVER Chain Destructive Commands With make build-skills

**Never combine `rm -rf` on skill directories with `make build-skills` (or any `make` target) in a single Bash tool call.**

In March 2026, this pattern **deleted the entire project directory**. Rules:
1. **Never chain `rm -rf` + `make` in one Bash call.** Split into separate tool calls with verification between each.
2. **Read the Makefile before running any `make` target** — `make build-skills` calls `deploy-claude-settings`, which has side effects.
3. **After any `rm -rf`, verify the working directory still exists** before doing anything else.
4. **If `make` output is unexpectedly empty or silent, stop and investigate.**

### Always Back Up TypeDB Before Schema Changes or db-init

**`make db-init` and `make build-db` DROP and RECREATE the database.** All data is lost. Before running any command that touches the schema or reinitializes the database:

1. **Run `make db-export`** — creates a timestamped zip in `local_resources/typedb/exports/`
2. **Verify the export exists** before proceeding
3. If `db-init` fails partway (e.g., schema conflict), the backup zip is the recovery path

This applies to:
- `make db-init`, `make build-db`, `make build` (which calls `build-db`)
- Any manual `db_init.py` invocation
- Schema changes that require reloading (new attributes, new entity types)
- `make db-migrate` (which creates its own backup, but verify)

**Safe pattern:**
```bash
make db-export              # Step 1: backup
make db-init                # Step 2: reload schemas (destructive!)
# If db-init fails, recover: make db-import ZIP=<latest-export.zip>
```

### External Skill Fixes Must Go Upstream

External skills (`jobhunt`, `dismech-notebook` etc.) are cloned from other repositories (`https://github.com/sciknow-io/alhazen-skill-examples`, `https://github.com/sciknow-io/alhazen-skill-dismech`). Fixes in `local_skills/` get overwritten by `make skills-update` (which is very, very, very bad). ALWAYS push fixes upstream first. See [`docs/conventions.md`](docs/conventions.md) for details.

### Dashboard Files: NEVER Edit in dashboard/src/ Directly

**`dashboard/src/components/`, `dashboard/src/lib/`, `dashboard/src/app/(skill)/`, `dashboard/src/app/api/skill/` are GENERATED copies.** They get overwritten by `make build-dashboard`.

The source of truth for each skill's dashboard is `skills/{name}/dashboard/` (for core skills) or `local_skills/{name}/dashboard/` (for external skills), with 4 slots:

```
skills/{name}/dashboard/
  components/   -> dashboard/src/components/{name}/
  lib.ts        -> dashboard/src/lib/{name}.ts
  pages/        -> dashboard/src/app/({name})/
  routes/       -> dashboard/src/app/api/{name}/
```

**To edit dashboard code:** Edit in `skills/{name}/dashboard/` (or the upstream git repo for external skills), then run `make build-dashboard` to propagate. NEVER edit the copies in `dashboard/src/` — they will be silently overwritten on next build.

### Playwright Screenshots Go in the Cache

When using Playwright MCP tools to take screenshots during testing, **always save them to `~/.alhazen/cache/screenshots/`**, not the project root. Screenshots left in the project root pollute `git status` and risk being committed.

```bash
# Good — save to cache
mcp__playwright__browser_take_screenshot(filename="~/.alhazen/cache/screenshots/my-test.png")

# Bad — pollutes project root
mcp__playwright__browser_take_screenshot(filename="my-test.png")
```

The cache directory is `~/.alhazen/cache/screenshots/` — create it if it doesn't exist.
