Metadata-Version: 2.4
Name: ghost-reader
Version: 0.0.1
Summary: Persona-driven fiction review simulator CLI
Author-email: Kevin Chin <kevin@kevindchin.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/clchinkc/ghost-reader
Project-URL: Repository, https://github.com/clchinkc/ghost-reader
Project-URL: Documentation, https://github.com/clchinkc/ghost-reader/blob/main/agent-setup.md
Keywords: fiction,beta-reader,writing,feedback,review,persona
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Text Processing :: General
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyYAML>=6.0.2
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Dynamic: license-file

# Ghost Reader CLI

Local-first persona-driven fiction review simulator for structured beta-reader-style feedback.

[![PyPI version](https://img.shields.io/pypi/v/ghost-reader)](https://pypi.org/project/ghost-reader/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

**Source:** https://github.com/clchinkc/ghost-reader

## For AI agents

Agents with web fetch and shell access should start here:

1. Fetch [agent-setup.md](agent-setup.md) (short bootstrap; do not scrape HTML report templates).
2. Install [uv](https://docs.astral.sh/uv/) if needed, then install the CLI from `main`:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install 'git+ssh://git@github.com/clchinkc/ghost-reader.git'
ghost-reader help
ghost-reader update check
```

Requires access to the private repo (SSH key or `gh auth login` for HTTPS git URLs).

3. Install the skill: copy `skills/ghost-reader/` into your harness skill directory, or invoke `Skill(ghost-reader)` when available.
4. Read the operational contract: [skills/ghost-reader/SKILL.md](skills/ghost-reader/SKILL.md) (workflow) and [skills/ghost-reader/reference.md](skills/ghost-reader/reference.md) (data model, Phase 3 roadmap).

## Documentation map

| Document | Audience | Role |
|----------|----------|------|
| [agent-setup.md](agent-setup.md) | Agents | Bootstrap, install, 11-step workflow |
| [skills/ghost-reader/SKILL.md](skills/ghost-reader/SKILL.md) | Agents | Operational contract |
| [skills/ghost-reader/reference.md](skills/ghost-reader/reference.md) | Agents | Schemas, paths, HTTP API |
| [llms.txt](llms.txt) | Agents | Command index |
| [examples/README.md](examples/README.md) | Everyone | Canonical sample trace (committed) |
| [AGENTS.md](AGENTS.md) / [CLAUDE.md](CLAUDE.md) | Harness | Pointers to the above |

No hosted web service, no authentication server, no API keys. The `serve` command binds to `127.0.0.1` only — local-first by design.

## Current status (Phase 2)

- Local CLI with iterative refinement rounds (`round init`, `refine snapshot`).
- Structured YAML for personas, reviews, feedback, and revision prompts.
- Local HTML reports from `report/payload.json` and swappable templates.
- Bidirectional feedback via `ghost-reader serve` (`POST /api/feedback`, `/api/dialogue`).
- Persona dialogue (`dialogue append`, `dialogue context`).
- Content-safe local telemetry and local sync bundles.
- Verification statuses (per session): `review_ready_feedback_pending` → `refinement_complete` → `phase1_complete` (these are **verify** outputs, not separate product phases).

Artifact contracts: review and feedback **schema v2 only**; sessions use **round-*** directories (no flat legacy layout).

No hosted web app. Phase 3 persona recommendation is **planned** (not in the CLI yet); see roadmap below.

## Install (users)

Install [uv](https://docs.astral.sh/uv/getting-started/installation/) first.

| Method | Command |
|--------|---------|
| **pipx** (recommended) | `pipx install ghost-reader` |
| **uv tool** (recommended) | `uv tool install ghost-reader` |
| **uvx** (no install) | `uvx ghost-reader help` |
| **Git (private repo)** | `uv tool install 'git+ssh://git@github.com/clchinkc/ghost-reader.git'` |
| **Dev (clone)** | `git clone git@github.com:clchinkc/ghost-reader.git && cd ghost-reader && uv sync --extra dev` then `uv run ghost-reader help` |

`uv tool install` places `ghost-reader` on your PATH (typically `~/.local/bin`).
`pipx install` places it in a pipx-managed virtualenv.

```bash
ghost-reader init   # run from your story project directory
ghost-reader help
```

### Build wheel locally

```bash
uv build
uv tool install dist/*.whl
```

### Version management

Published to PyPI via OIDC trusted publishing on `git tag v*`. The version in `pyproject.toml` is the single source of truth — keep it in sync with `src/ghost_reader/__init__.py` and `src/ghost_reader/.release-version`.

## Sample trace

The repo includes a full **review_ready_feedback_pending** example at [examples/sample-trace/](examples/sample-trace/). See [examples/README.md](examples/README.md).

```bash
cd examples/sample-trace
export GHOST_READER_HOME="$PWD/.ghostreader-home"
ghost-reader init
ghost-reader verify --session chapter-1
ghost-reader serve --session chapter-1
```

Regenerate after contract changes: `uv run python scripts/refresh_sample_trace.py`

## Quick workflow

Run all commands from the **story project directory** (where `.ghostreader/` lives), not from a clone of this repo unless you are developing Ghost Reader itself.

```bash
cd /path/to/your-story-project
ghost-reader init
ghost-reader session create --id chapter-3 --story-unit "chapter 3" --personas mara,dex,pip
# LLM writes review YAML per persona, then:
ghost-reader artifact write --session chapter-3 --type review --persona mara --from mara.review.yaml
ghost-reader render --session chapter-3
ghost-reader verify --session chapter-3
ghost-reader serve --session chapter-3 --timeout 600
```

After reviews render, **`serve` is the primary user path**: the user selects items in the browser and clicks **Submit Feedback**, which writes `feedback/feedback.yaml`. The agent then polls `ghost-reader feedback summary --session chapter-3`, runs `ghost-reader prompt revision`, rerenders, and verifies `phase1_complete`.

If `serve` is unavailable, open `file://` on `.ghostreader/sessions/<id>/round-<n>/report/index.html` and use the copy-paste **Ghost Reader Prompt** fallback.

### Pasted text (no story repo yet)

```bash
mkdir -p ~/ghost-reader-projects/my-chapter
cd ~/ghost-reader-projects/my-chapter
export GHOST_READER_HOME="$PWD/.ghostreader-home"
ghost-reader init
ghost-reader session create --id ch1 --story-unit "chapter 1"
```

Use `/tmp/ghost-reader-*` only for disposable tests.

### Developer setup (this repo)

```bash
git clone git@github.com:clchinkc/ghost-reader.git
cd ghost-reader
uv sync --extra dev
uv run ghost-reader update check

cd /path/to/story-project
uv run --project /path/to/ghost-reader --no-editable ghost-reader init
```

## Report design contract

- Source text stays readable; annotations tie to cited passages.
- Full reader reasons live in persona sections, not only tooltips.
- Quiet, dense layout; no marketing-style chrome.

## Test

```bash
uv lock --check
uv run --with ruff ruff check .
uv run --with pytest pytest
```

## Code structure

| Module | Role |
|--------|------|
| `cli.py` | Command surface |
| `server.py` | Local bidirectional HTTP (`serve`) |
| `feedback_store.py` | Shared feedback persist + telemetry |
| `validators.py` | Artifact contracts |
| `report.py` | HTML from `payload.json` |
| `verify.py` | Session gates |
| `telemetry.py` / `sync.py` | Local events and export bundles |

## Roadmap

### Phase 1 — local CLI (shipped)
Local-first persona-driven review, structured YAML, HTML report, validation gates.

### Phase 2 — iterative rounds (shipped)
Multi-round workflow, dialogue with personas, bidirectional serve UI, content-safe telemetry, local sync bundle. See [skills/ghost-reader/SKILL.md](skills/ghost-reader/SKILL.md).

### Phase 2.5 — CLI feedback-loop extension (planned, doc-first)
Extend the existing CLI loop (`serve` → `feedback add/summary` → `prompt revision`) for future remote-catalog sync without breaking local-first operation. Outbound: content-safe events + selected persona IDs + acted-on feedback categories + catalog refs + recommendation receipts. Inbound: catalog metadata + recommendation candidates + receipt IDs. **Raw story text never syncs by default.** No new command surface in this phase — `sync` is extended in docs first, then code.

### Phase 3 — hosted option + remote catalog + recommendation engine (planned)
Persona recommendation as a spatial HTML comparison artifact (`recommendation.html`) and `ghost-reader recommend` are **not implemented yet**. Recommendation scores, usage analytics, and marketplace ranking live **server-side** (not in local persona YAML) per D003. Until then, users choose personas manually (`mara`, `dex`, `pip`, or optional `elena`, `rook`; or any custom persona validated via `persona show`). Design notes: [skills/ghost-reader/reference.md](skills/ghost-reader/reference.md#phase-3-persona-recommendation-planned).

## Custom personas (skill-mediated, not a CLI command)

There is **no `ghost-reader persona import` or `persona export` command** in any phase. Custom personas are created by the LLM, validated by the CLI:

1. The skill emits canonical YAML matching the persona schema.
2. Place the file at `$GHOST_READER_HOME/personas/<id>.yaml`.
3. CLI validates via `ghost-reader persona show <id>` (calls `read_persona()` and the Pydantic schema).
4. The persona is then usable in `ghost-reader session create --personas <id>,...`.

Local persona YAML may carry `source`, `catalog_ref`, `tags` for provenance. It must NOT carry `matching`, `analytics`, `weights`, `telemetry`, `posture`, or `tolerance` (enforced in `models.py:check_forbidden_fields`). See [skills/ghost-reader/SKILL.md](skills/ghost-reader/SKILL.md#custom-persona-ingestion-llm-driven-not-a-cli-command) and [reference.md](skills/ghost-reader/reference.md#custom-personas-skill-mediated-not-a-cli-command).
