Metadata-Version: 2.4
Name: fact-toolkit
Version: 0.1.0
Summary: Focused Agentic Context Toolkit — Spec Kit + RPI for Claude Code
Project-URL: Homepage, https://github.com/holaPymbu/fact
Project-URL: Repository, https://github.com/holaPymbu/fact
Project-URL: Issues, https://github.com/holaPymbu/fact/issues
Author: FACT contributors
License: MIT
Keywords: agent,ai,claude-code,rpi,skills,spec-kit
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.110
Requires-Dist: httpx>=0.27
Requires-Dist: jinja2>=3.1
Requires-Dist: markdown-it-py>=3.0
Requires-Dist: pygments>=2.17
Requires-Dist: rich>=13.7
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.29
Requires-Dist: watchdog>=4.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# FACT — Focused Agentic Context Toolkit

> A harness that turns Claude Code into an agent that follows
> [Spec Kit](https://github.com/github/spec-kit) + RPI by default,
> with a local dashboard for progress, tokens, and cost — and a
> hook-driven audit layer that pauses the workflow on real
> security / architecture / quality / testing issues until the
> human approves.

**Status**: v0.1 (private repo). Battle-tested on a 46-task
greenfield FastAPI project with continuous security & quality audits.

---

## Table of contents

- [What is FACT](#what-is-fact)
- [Install](#install)
- [Quickstart](#quickstart)
- [Dashboard tour](#dashboard-tour)
- [The workflow](#the-workflow)
- [Audits](#audits)
- [CLI reference](#cli-reference)
- [Slash commands](#slash-commands)
- [Skills shipped with FACT](#skills-shipped-with-fact)
- [Project layout](#project-layout)
- [Continuity](#continuity)
- [Configuration](#configuration)
- [Troubleshooting](#troubleshooting)
- [Design principles](#design-principles)

---

## What is FACT

FACT is the glue between three independent pieces:

1. **[Spec Kit](https://github.com/github/spec-kit)** — GitHub's
   spec-driven development toolkit. Constitution → Spec → Plan →
   Tasks → Implement.
2. **RPI** (Research-Plan-Implement) — HumanLayer's discipline:
   stay under the 40% context window, fork context with sub-agents,
   write semantic summaries at every phase boundary.
3. **Skills** — Anthropic's procedural-knowledge format. FACT ships
   seven base skills and pulls domain skills from
   [skills.sh](https://skills.sh) on demand for audits.

It runs **alongside** Claude Code, never wrapping it. Hooks
observe the session and feed three things:

- a **local dashboard** showing the kanban of stories, token
  cost, and the file tree,
- a **session-state file** that survives crashes so the agent can
  resume cleanly tomorrow,
- a **hook-driven audit layer** that triggers security /
  architecture / quality / testing reviews via sub-agents loaded
  with domain skills, and pauses the workflow until the human
  approves.

---

## Install

### Prerequisites

| Tool                                         | Why                                                                      |
| -------------------------------------------- | ------------------------------------------------------------------------ |
| Python 3.10+                                 | FACT and its hooks (Claude Code calls FACT's Python helpers directly — no shell required, including on Windows) |
| [Claude Code](https://claude.com/claude-code) on `PATH` | the agent harness FACT plugs into                              |
| `git`                                        | repo operations + Spec Kit                                               |
| [`gh`](https://cli.github.com/) *(only while the repo is private)* | `gh auth login` is the simplest way to authenticate `git` for the install |
| [`uv`](https://docs.astral.sh/uv/) *or* [`pipx`](https://pipx.pypa.io/) | to install FACT in an isolated env                |

`specify-cli` (Spec Kit) is auto-installed on first `fact init`.

### From a fresh machine — macOS

```bash
# 1. Homebrew (skip if already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 2. Prerequisites
brew install python git uv
# Claude Code: download the desktop installer from https://claude.com/claude-code

# 3. Install FACT (pick the line that matches your situation — see below)
uv tool install fact-toolkit                                                    # PyPI (once published)
# or, while the repo is private / for unreleased dev builds:
# brew install gh && gh auth login
# uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
```

### From a fresh machine — Windows (PowerShell)

```powershell
# 1. Prerequisites via winget
winget install --id Python.Python.3.12 -e
winget install --id Git.Git -e
# Claude Code: download from https://claude.com/claude-code

# 2. uv (recommended over pipx — avoids the broken-launcher problem when Python is upgraded)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# >>> Close and reopen PowerShell so PATH refreshes <<<

# 3. Install FACT
uv tool install fact-toolkit                                                    # PyPI (once published)
# or, while the repo is private:
# winget install --id GitHub.cli -e ; gh auth login
# uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
```

> FACT hooks are pure Python — no `bash`, no Git Bash on PATH required.

> **Why not pipx on Windows?** pipx installs a `pipx.exe` shim hard-coded to one
> Python install. If you upgrade or reinstall Python the shim breaks with
> `Unable to create process using ...python.exe`. `uv` doesn't have this
> problem. If you must use pipx, sidestep the shim: `python -m pipx install ...`.

### Already have the prerequisites? Pick one:

#### Option A — `uv tool` (recommended)

```bash
uv tool install fact-toolkit                                                    # PyPI
# or for unreleased dev builds:
uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
```

`uv` handles the isolated environment for you.

#### Option B — `pipx`

```bash
pipx install fact-toolkit                                                       # PyPI
# or:
pipx install git+https://github.com/holaPymbu/fact.git
```

#### Option C — clone for development

```bash
gh repo clone holaPymbu/fact ~/.fact
python3 -m venv ~/.fact/.venv
~/.fact/.venv/bin/pip install -e ~/.fact
echo "alias fact='~/.fact/.venv/bin/fact'" >> ~/.zshrc
```

After install, `fact --help` should work in any directory.

### Updating

```bash
uv tool upgrade fact-toolkit                          # Option A
pipx upgrade fact-toolkit                             # Option B
git -C ~/.fact pull                                   # Option C
```

After updating FACT itself, run `fact upgrade` inside any project
to refresh its bundled skills, commands, and hooks.

### Releasing to PyPI (maintainers)

The repo ships a [trusted-publishing](https://docs.pypi.org/trusted-publishers/)
workflow at `.github/workflows/release.yml`. One-time setup on PyPI:

1. Claim the project name (`fact-toolkit`) — first manual upload, or by
   reserving via the PyPI account UI.
2. On the project's *Publishing* page, add a Trusted Publisher for
   owner `holaPymbu`, repository `fact`, workflow `release.yml`,
   environment `release`.
3. In this repo's *Settings → Environments*, create an environment
   named `release` (no secrets needed — OIDC handles it).

Then to cut a release:

```bash
# bump the version in pyproject.toml, commit, push
git tag v0.1.0
git push --tags
```

The workflow checks the tag matches `pyproject.toml`, builds the sdist
+ wheel, and publishes them to PyPI. No tokens, no secrets to rotate.

---

## Quickstart

In a new directory (greenfield) or an existing repo (brownfield):

```bash
cd my-project/
fact init           # one-time setup. Creates .specify/, .claude/, CLAUDE.md.
                    # Auto-installs specify-cli. Starts the dashboard.
claude              # open Claude Code in the same directory
> /fact-start       # picks workflow (greenfield/brownfield/demo) and begins
```

`fact init` opens the dashboard at `http://localhost:7842`. Keep
that tab open while you work; it updates in real time as the agent
edits files and tasks close.

---

## Dashboard tour

![FACT dashboard](docs/img/dashboard-overview.png)

A single-page local app on port 7842. Four zones, all live:

### Header (top)

- **Brand** — `FACT  •  <project-name>  •  <phase>`. Phase pill
  reflects the current Spec Kit phase (`constitution`, `specify`,
  `plan`, `tasks`, `implement`, `done`).
- **TASKS** — `<done> / <total>` aggregated across the visible
  scope (one feature or all features).
- **TOKENS** — total tokens read from the Claude Code transcript,
  formatted as K/M. Hover to see the input / output / cache
  breakdown.
- **COST** — total session cost in USD, computed from
  `pricing.json`. If a model wasn't priced, it's flagged with `?`.
- **SAVED VS OPUS** — counterfactual: what the workload would have
  cost if every sub-agent had been Opus. The bigger this number,
  the more the Haiku/Sonnet sub-agent strategy is paying off.

### Sidebar (left)

- **Files tree** — every `.md` file in the project, recursive.
  Click any to open it in a markdown-rendered modal. Folders are
  collapsible; defaults expand `.specify/`, `.specify/specs/`,
  `.specify/fact/sessions/`, `.specify/memory/`. Ignored
  automatically: `node_modules`, `.venv`, `.git`, `__pycache__`,
  `dist`, `build`, `*.egg-info`, etc.
- **By model** — token spend grouped by model (`opus-4-7`,
  `sonnet-4-6`, `haiku-4-5`). Cost + total tokens per model. Hover
  for the input/output/cache split.

### Kanban (center)

Stories go into Pending / In Progress / Done columns. A **story**
is one of:

| Kind                | Source                               | Visual                          |
| ------------------- | ------------------------------------ | ------------------------------- |
| **foundation**      | the project's Constitution alone     | yellow border, `foundation` badge |
| **workflow**        | per-feature pre-implement tasks      | yellow border, `workflow` badge |
| **user_story**      | a `tasks.md` section labeled `User Story N`, enriched with the title from `spec.md` | blue border, `US N` badge, optional `P1/P2/P3` priority pill |
| **phase**           | any other `tasks.md` section (Setup, Foundational, Polish, …) | gray border, `phase` badge      |

Each card shows:
- a **feature badge** (which feature it belongs to, e.g. `001·tea`),
- the **kind badge** + optional **priority pill**,
- a **counter pill** `done/total`,
- a slim **progress bar** (done | in-progress | pending),
- three **count pills** `✓ N done · ● N in progress · ○ N pending`.

Click a card to open the **story detail modal** — it lists every
task underneath with chips for tags (`P`, `US1`, `REVIEW`, …),
files referenced (clickable, opens the file viewer), and
dependencies (clickable, jumps to that task's detail).

### In-progress signal

When the agent is currently working in a story, the card has:

- a **pulsing blue glow** around the border (CSS keyframes, 2.4s),
- a **blinking blue dot** next to the kind badge,
- a `started Xm ago` footer that updates every 20 seconds.

If a `[P]` task is delegated to a sub-agent in a worktree, that
specific task pulses **violet** instead of blue, and the card
shows a `⤵ subagent · model` chip indicating which model is
running it.

### Toolbar above the kanban

- **Search** — matches story title or any field of any task in it
  (id, title, file, tag, dependency). Tip: press `/` from anywhere
  to focus the search.
- **Feature picker** — switches between features, or `All
  features` (default when there are >1).
- **Filter dropdown** — grouped: story kind (User Story / Phase /
  Workflow / Foundation), priority (P1 / P2 / P3), and task tag
  (P, US1, US2, …).
- **Hide workflow** — toggles foundation + workflow cards off, so
  you only see real implementation stories.
- **`tags?`** — opens the tag legend explaining `P`, `US N`,
  `REVIEW`, `BLOCKED`, etc.

### Footer

A live status line: `live · updated HH:MM:SS` when the WebSocket
is connected, `reconnecting…` when it's down. The dashboard
auto-reconnects.

---

## The workflow

`/fact-start` asks for the project type:

### 1. Greenfield

Loads `fact-discovery`, which conducts a structured Q&A
(target users, problem, core features, references, stack, constraints)
to produce a vision draft. Then runs Spec Kit in order:

```
/speckit.constitution   → 4–6 principles derived from the vision
/speckit.specify        → first spec.md
/speckit.clarify        → resolves ambiguities with the user
/speckit.plan           → tech stack, architecture, code snippets
[ pre-implement audit gate ]   ← MANDATORY (see Audits section)
/speckit.tasks          → decompose plan into T-NNN tasks
/speckit.implement      → write code, file by file
```

### 2. Brownfield

Loads `fact-research`, which spawns parallel sub-agents
(Haiku/Sonnet) to map structure, stack, conventions, modules,
tests, and CI configs of the existing codebase. Produces a
`research.md` map. Then constitution + delta spec + plan + audit
gate + tasks + implement.

### 3. Demo

Quick experiment via the `tinyspec` extension. Skips discovery
and clarify; one shot from idea → plan → implement.

Between every phase, the agent writes a session summary to
`.specify/fact/sessions/<UTC>.md` (`What was done`, `What was
decided`, `What's pending / next`). These power continuity (see
below).

---

## Audits

FACT runs continuous audits driven by hooks. Hooks are pure
triggers — they never run linters or audit logic themselves.
When a hook fires, it emits a structured prompt that pauses the
workflow and instructs the agent to load the `fact-audit` skill.
The skill then orchestrates the actual review using sub-agents
loaded with domain skills from [skills.sh](https://skills.sh).

```
Edit / Stop                                        Agent next turn
    │                                                    │
    ▼                                                    ▼
Hook fires  ─►  emits structured trigger  ─►  Agent loads fact-audit
                  + exits with code 2                    │
                                                         ▼
                                              Spawns sub-agents per
                                              dimension, each loaded
                                              with a domain skill
                                              from skills.sh
                                                         │
                                                         ▼
                                              Aggregates findings,
                                              shows them verbatim
                                              to the user
                                                         │
                                                         ▼
                                              User picks: fix /
                                              manually / override /
                                              rollback
                                                         │
                                                         ▼
                                              Workflow resumes
```

### Three triggers

| Trigger        | When                            | Sub-agent       | Dimensions                            |
| -------------- | ------------------------------- | --------------- | ------------------------------------- |
| `source-edit`  | every Edit/Write to `.py`/`.ts`/`.go`/etc | Haiku   | security, quality                     |
| `task-close`   | edit to `tasks.md` (likely a task closed) | Sonnet  | security, architecture, quality       |
| `session-stop` | the agent tries to close session | Sonnet (×3 parallel) | security, architecture, quality, testing |

Tests run via `pytest` / `npm test` / `cargo test` if available.
Test failures count as `critical`.

### User-approval flow

When findings of severity ≥ `high` exist, the agent shows them
**verbatim** and offers four options:

1. **Fix automatically** — agent edits the affected files. The
   next file write re-triggers the audit; it must come back clean
   for the workflow to resume.
2. **Fix manually** — agent pauses while the human edits.
3. **Override** — agent records the override + the user's
   reason in the session summary, then continues.
4. **Rollback** — agent proposes the inverse of its last edit;
   on confirmation, applies it.

Lower-severity findings (medium/low/info) are mentioned in passing
without blocking.

### Pre-implement gate

Not hook-triggered — explicitly invoked by `fact-discovery` /
`fact-research` after `/speckit.plan` and before `/speckit.tasks`.
Three Sonnet sub-agents review the plan against constitution +
spec. Critical findings → return to plan iteration.

### On demand

```
> /fact-audit                 # run all dimensions on full session changes
> /fact-audit security        # only that one
> /fact-audit architecture
> /fact-audit quality
```

### Reports

Every audit writes a markdown report to
`.specify/fact/audits/<UTC>-<dim>.md` with YAML frontmatter
(severity counts, scope, skill used). They surface in the file
tree but **not** as a dashboard panel — the conversation between
agent and user is the canonical audit surface.

---

## CLI reference

| Command                  | What it does                                                       |
| ------------------------ | ------------------------------------------------------------------ |
| `fact init`              | Idempotent project setup. Auto-installs `specify-cli`.             |
| `fact init --port 7900`  | Use a non-default dashboard port.                                  |
| `fact init --no-dashboard` | Set up the project without starting the dashboard.               |
| `fact init --no-speckit` | Skip the auto-install of `specify-cli`.                            |
| `fact dashboard`         | Start (or check) the dashboard server.                             |
| `fact dashboard --restart` | Force restart the dashboard.                                     |
| `fact stop`              | Stop the dashboard.                                                |
| `fact doctor`            | Diagnose: what's missing, what's broken.                           |
| `fact doctor --fix`      | Try to install anything missing (currently: `specify-cli`).        |
| `fact upgrade`           | Re-copy bundled skills / commands / hooks into the project.        |

---

## Slash commands

| Command          | What it does                                                                          |
| ---------------- | ------------------------------------------------------------------------------------- |
| `/fact-start`    | First time: pick workflow type and begin. Resumed sessions: detects continuity.       |
| `/fact-next`     | Continue the current phase or advance to the next.                                    |
| `/fact-status`   | Quick status report in chat (≤10 lines).                                              |
| `/fact-audit`    | Run an audit on demand. Optional arg: `security` / `architecture` / `quality` / `all`. |

Plus all of Spec Kit's `/speckit.*` commands (`constitution`,
`specify`, `clarify`, `plan`, `tasks`, `implement`,
`verify-tasks`, …) which the FACT skills call internally.

---

## Skills shipped with FACT

| Skill                    | When loaded                                  | What it does                                                                |
| ------------------------ | -------------------------------------------- | --------------------------------------------------------------------------- |
| `fact-onboarding`        | first thing in `/fact-start`                 | Detects continuity, asks for project type, hands off to a workflow skill.   |
| `fact-rpi-harness`       | always loaded                                | The 40% rule, sub-agent strategy, intentional compaction, session summaries. |
| `fact-discovery`         | greenfield workflow                          | Structured Q&A → vision → constitution → specify → clarify → plan.          |
| `fact-research`          | brownfield workflow                          | Parallel sub-agents map the codebase → research.md → delta spec.            |
| `fact-implement`         | implement phase                              | Per-task discipline: read plan, apply skills, write code, mark done.        |
| `fact-skill-installer`   | when an external skill is needed             | Search skills.sh, present to user, install with explicit confirmation.      |
| `fact-audit`             | when a hook trigger arrives                  | Orchestrates security / architecture / quality / testing reviews.           |

---

## Project layout

When FACT manages a project:

```
my-project/
├── .claude/
│   ├── skills/
│   │   ├── fact-*/SKILL.md                  (FACT base skills, listed above)
│   │   └── speckit-*/SKILL.md               (Spec Kit's own skills)
│   ├── commands/
│   │   ├── fact-start.md
│   │   ├── fact-next.md
│   │   ├── fact-status.md
│   │   └── fact-audit.md
│   ├── hooks/                               (pure-Python — Claude Code calls them directly)
│   │   ├── fact_hook.py                     (FACT observation; tool/session/subagent events)
│   │   ├── fact_audit.py                    (per-file audit trigger on PostToolUse)
│   │   ├── fact_audit_stop.py               (testing-audit helper, invoked on demand)
│   │   ├── fact_compact_progress.py         (60% context-window compaction trigger)
│   │   ├── fact_compact.py                  (compaction helper, invoked on demand)
│   │   └── fact_session_resume.py           (resume nudge on SessionStart)
│   └── settings.json                        (hook wiring)
├── .specify/
│   ├── memory/
│   │   └── constitution.md                  (Spec Kit)
│   ├── specs/
│   │   └── <NNN-feature>/                   (Spec Kit per-feature)
│   │       ├── spec.md, plan.md, tasks.md, research.md
│   │       ├── checklists/, contracts/, …
│   └── fact/                                (FACT operational state)
│       ├── config.json                      (port, host, agent type)
│       ├── dashboard.pid                    (running dashboard pid)
│       ├── events.jsonl                     (append-only hook log)
│       ├── session_state.json               (mechanical state)
│       ├── sessions/<UTC>.md                (semantic summaries)
│       ├── audits/<UTC>-<dim>.md            (audit reports)
│       └── .stop-audit-<id>.fired           (loop guard markers)
├── CLAUDE.md                                (~20 lines, points at skills)
└── (your code: src/, tests/, etc)
```

Key principle: **everything FACT writes lives under
`.specify/fact/`**. There is no parallel `~/.fact/` or `./fact/`
directory in the project. If you `rm -rf .specify/`, you reset
both Spec Kit AND FACT — clean slate.

---

## Continuity

FACT persists state continuously, **not** at session-close. If you
Ctrl+C Claude or the process crashes, the latest snapshot is
already on disk. On reopen:

1. `fact-onboarding` reads `session_state.json` for mechanical
   state (active task, recent files, model, last update).
2. It reads the latest `sessions/<UTC>.md` summary for semantic
   state (decisions, what was tried, what's next).
3. It presents a continuity message and asks if you want to
   continue from where you were.

Three resumption cases handled by the skill:

- **Clean close** — last task was marked `[x]`. Asks: continue
  with the next pending task?
- **Mid-task abandon** — last task was `[ ]` but files were
  modified. Asks: pick up where I left, or reset and start over?
- **Corrupt state** — `session_state.json` missing/garbled. Falls
  back to the Spec Kit files alone, asks the user what to do.

If both layers are gone (`rm -rf .specify/fact/`), FACT degrades
to Spec Kit-only — exactly how Spec Kit projects work without FACT.

---

## Configuration

### Dashboard port

Default: `7842`. Override at init time:

```bash
fact init --port 7900
```

Or edit `.specify/fact/config.json`:

```json
{
  "version": "0.1.0",
  "agent": "claude-code",
  "dashboard": { "host": "127.0.0.1", "port": 7842 }
}
```

### Pricing

Token costs come from `pricing.json` shipped with FACT. Verify
against [Anthropic's pricing page](https://www.anthropic.com/pricing)
at release time; update via `fact upgrade` when models change.

### Hooks

`.claude/settings.json` is managed by `fact init` / `fact upgrade`.
Don't hand-edit unless you know what you're doing — re-running
`fact upgrade` will preserve your additions but might add FACT
entries again if the markers change.

---

## Troubleshooting

| Problem                                                  | Fix                                                                                                                                  |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Dashboard shows nothing — empty kanban                   | The agent hasn't run `/speckit.tasks` yet. Phase cards still appear; T-NNN cards arrive when `tasks.md` is generated.                |
| Dashboard isn't reflecting changes                       | Hard refresh the browser (`Cmd+Shift+R`). Cache headers should prevent this but a stale tab can stick.                               |
| `specify` not found / install failed                     | Run `fact doctor --fix`. If still failing, install manually with `uv tool install --from git+https://github.com/github/spec-kit.git specify-cli`. |
| `🔒 FACT AUDIT` keeps re-firing on Stop                  | Update FACT (`fact upgrade`). The Stop hook now fires at most once per session.                                                       |
| Cost shows `$0.00` despite agent activity                | The dashboard reads tokens from the Claude Code transcript. Make sure the project was init'd with `fact init`; then `fact upgrade` to refresh hook helpers. |
| Agent forgot to write `active_task_id`                   | The dashboard infers in-progress from the recent file edit buffer. Should self-correct after the next file edit.                     |
| `fact upgrade` says nothing changed                      | That's fine — it's idempotent. To force a refresh, delete `.claude/skills/fact-*` and re-run.                                       |
| I want to restart from scratch                           | `fact stop && rm -rf .specify .claude/skills/fact-* .claude/commands/fact-* .claude/hooks && fact init`. Your code is untouched.    |
| Windows: `pipx install ...` fails with `Unable to create process using ...python.exe` | The pipx shim is hard-coded to a Python that no longer exists at that path. Either reinstall pipx (`python -m pip install --user --upgrade pipx`) or switch to `uv` (recommended on Windows). |
| Hooks don't fire / dashboard stays empty                 | Hook commands in `.claude/settings.json` reference an absolute path to the Python interpreter that ran `fact init`. If that interpreter has since moved or been uninstalled, the hooks silently fail. Re-run `fact upgrade` to refresh the paths.                                       |
| Claude Code shows `Unknown hook event "SubagentEnd"`     | Old FACT version. Run `fact upgrade` inside the project — it renames the event to `SubagentStop` (Claude Code's current name) and removes the stale entry from `settings.json`.              |

---

## Design principles

These guide every implementation decision in FACT. If a change
violates one, the change is wrong, not the principle.

1. **Single source of truth: Spec Kit `.md` files.** FACT never
   writes parallel state files as a substitute. Every derived
   view (dashboard, status command) reads from the Spec Kit files.
2. **The agent never spends tokens maintaining FACT metadata.**
   What FACT needs to know is deduced from hooks, the filesystem,
   and the files Spec Kit already generates. Semantic summaries
   the agent writes are the same it would write under good RPI
   practice.
3. **`CLAUDE.md` is 20 lines or less.** Detailed rules live in
   skills, loaded on demand.
4. **RPI rules are non-negotiable.** The 40% smart-zone, intentional
   compaction, sub-agents for forking context, code snippets in
   plans — these aren't bendable.
5. **Sub-agents fork context, not roles.** No "frontend agent" or
   "backend agent". Sub-agents are a compression mechanism.
6. **Sub-agents use differentiated models.** Haiku for lookup,
   Sonnet for synthesis, the main model for deep reasoning.
7. **External skills require explicit user confirmation.** The
   agent never downloads a skill without a clear "yes" in chat.
8. **FACT runs alongside, never in the middle.** No wrapping, no
   proxying.
9. **Cheap extensibility, not expensive.** A single Protocol
   (`AgentAdapter`), one concrete impl. No plugin registry.
10. **Honest metrics.** If a number can't be computed accurately,
    show a placeholder, never fabricate.
11. **One project folder.** Everything FACT writes is under
    `.specify/fact/`. No parallel root directories.
12. **Continuity is automatic.** The user never runs a `pause` or
    `save` ritual. Close anytime, reopen, the agent catches up.

---

## License

MIT.
