Architecture¶
How Area O1 turns your work into an evidence file, where it keeps everything, and how the code is laid out.
What it is¶
Area O1 is a local-first command center for building an extraordinary-ability immigration case (O-1A now, EB-1A too, more through community profiles). Underneath, it's evidence-grounded memory for long-running AI agents, applied first to O-1A and EB-1A: every fact it holds quotes its source, and you decide what counts.
Provenance follows the W3C PROV model. Area O1 makes no performance claims beyond what its evaluation harness measures, and that harness is still to come (see the roadmap).
Your case lives in a private workspace folder on your computer, its own git repo. The app repository holds only the app.
How it works¶
- Connectors (
areao1/sources/) discover your repos, models, datasets, papers and pages, snapshot their metrics intodata/metrics.csv, and propose evidence candidates. - Every raw response becomes an observation in
memory/, and every fact drawn from it becomes a claim that quotes its source verbatim, with offsets (for example"stargazers_count": 1840fromapi.github.com/repos/…). Claims are append-only: a new value supersedes the old one and nothing is overwritten, so you can ask what was known on any date. - Candidates land in the Inbox, where you can expand the exact claims behind each one. Nothing becomes evidence until you accept it. Accepting approves those claims, writes a capture file to
evidence/<criterion>/<criterion>_<yyyy-mm-dd>_<slug>.md, and logs it indata/exhibits.json. Approval records your decision; it doesn't certify legal sufficiency. - The criteria engine (
areao1/criteria/) scores exhibits against a YAML profile (profiles/o1a.yaml,profiles/eb1a.yaml): each criterion isbanked,building,gapordropped. An invitation is not a completion: only completed, published or granted evidence counts, and self-reported items never count. Switching profiles re-scores the same evidence. DASHBOARD.mdand the web dashboard show where you stand.
Chat-history imports follow the same path. Area O1 reads only your messages (never the assistant's) and suggests deadlines, pipeline items and letter writers. Those suggestions are self-reported: they keep your trackers current, but they can never count toward a criterion.
See How it works for each step in detail.
Plain files¶
All workspace data is plain JSON, JSONL, CSV and Markdown, each with a JSON Schema (generated from the models into areao1/core/schemas/, and copied into each workspace under .areao1/schemas/). You, the dashboard and any agent read the same files. areao1 validate checks them.
Every change a page or the agent makes goes through one service layer (areao1/service.py), which records it in data/changes.jsonl so it can be reviewed or undone.
The core knows nothing about immigration¶
The core (areao1/core/) holds the domain-agnostic models, the workspace store and the claim memory. It never imports from the immigration layer or mentions a specific profile, and a test enforces that. Profiles and scoring live in a separate layer (areao1/criteria/), so other domains could reuse the core.
Profiles are YAML files in profiles/. Each criterion has an id, the regulation it summarizes, its evidence types, its strength signals and a simple bank rule (min_exhibits, min_signals). A workspace can add or override profiles with its own profiles/*.yaml. See Contributing.
The workspace folder¶
A new workspace (from the first run or areao1 init) looks like this. Some folders appear only once you use the feature.
~/AreaO1/
├── areao1.yaml settings (no secrets)
├── DASHBOARD.md where you stand, regenerated by `areao1 run dashboard`
├── AGENTS.md instructions for Codex and other agents
├── .claude/skills/areao1/ the Claude Code skill pack
├── .gitignore keeps caches and .env out of git
├── data/
│ ├── person.json you
│ ├── sources.json connected sources (keychain entry names only)
│ ├── inbox.json candidates waiting for review
│ ├── exhibits.json accepted evidence
│ ├── criteria.json the scoreboard
│ ├── metrics.csv dated metrics history
│ ├── pipeline.json opportunities in progress
│ ├── deadlines.json deadlines
│ ├── letters.json letter writers
│ ├── opportunities.json
│ ├── calendar.ics deadlines and follow-ups, for your calendar app
│ ├── changes.jsonl every change, for review and undo (once you make one)
│ └── contacts.json, threads.json, outreach.json, mail.json (once you use Contacts and Gmail)
├── evidence/
│ └── <criterion>/<criterion>_<yyyy-mm-dd>_<slug>.<ext>
├── memory/
│ ├── observations.jsonl raw responses
│ ├── claims.jsonl facts, each quoting its source
│ ├── entities.jsonl, edges.jsonl, decisions.jsonl
│ └── sources/ snapshots of raw sources
├── drafts/letters/ letter drafts
├── agent/ conversations/, runs/ (once you use the agent)
├── vault/ the vault's log and findings (once it runs)
└── .areao1/
├── schemas/ JSON Schemas for every file
└── cache/ local caches and the vault index (gitignored)
The evidence/ folder has one subfolder per criterion id (awards, membership, press, judging, original_contributions, scholarly_articles, critical_role, high_salary, commercial_success, display). The O-1A and EB-1A profiles share these ids, so evidence carries across.
The package¶
| Path | What's in it |
|---|---|
areao1/cli.py |
The areao1 command |
areao1/core/ |
Domain-agnostic models, the workspace store, claim memory, secrets, JSON Schemas |
areao1/criteria/ |
The domain layer: profiles, scoring, the case, contacts, letters, the constellation, DASHBOARD.md |
areao1/sources/ |
Connectors: GitHub, Hugging Face, Semantic Scholar, OpenAlex, arXiv, ORCID, websites, chat exports |
areao1/google/ |
Gmail with an app password: mail, the Mail view, .eml import, outreach, opportunity checks |
areao1/agent/ |
The agent layer: tools, runner, prompts, guardrails, redaction, model routing, missions |
areao1/engine/ |
The engine behind the agent: the OpenAI Responses API |
areao1/vault/ |
The knowledge vault: official sources, snapshots, search, change signals, the rule check |
areao1/jobs/ |
Scheduled jobs and the scheduler |
areao1/notify/ |
Notifications: desktop, email, Slack, Discord, ntfy |
areao1/mcp/ |
The read-only MCP server |
areao1/onboarding/ |
Onboarding from your LinkedIn PDF |
areao1/server/ |
The FastAPI server and the built web UI |
areao1/service.py |
The service layer every write goes through |
areao1/extension/ |
The capture browser extension |
areao1/templates/workspace/ |
What a new workspace starts with |
profiles/ |
Criteria profiles (YAML) |
vault/sources.yaml |
The official sources the vault watches |
web/ |
The dashboard's source (React, built with Vite) |
Design records¶
Significant decisions are recorded as ADRs in docs/adr. An accepted ADR is never rewritten; a later one supersedes it.
| ADR | Decision |
|---|---|
| 0001 | Files are the source of truth |
| 0002 | An earlier naming decision, superseded by 0010 |
| 0003 | Product first, research second |
| 0004 | Append-only claim memory with verbatim excerpts |
| 0005 | Agent layer: engine adapters, grounded tools, the service layer, budgets |
| 0006 | Knowledge vault: tiered sources, content-addressed snapshots, local hybrid search |
| 0007 | Design system |
| 0008 | No demo data, a conversational onboarding, and agent guardrails |
| 0009 | Chat can do what the pages do; three model tiers; long chats |
| 0010 | The name is Area O1 |
| 0011 | The vault without babysitting |
| 0012 | The constellation memory map |
| 0013 | The front door: one line to a running onboarding |
| 0014 | Google, contacts and outreach |
| 0015 | OpenAI is the only engine |
| 0016 | The daily opportunity job |
The full plan is in SPEC.md.