docs: replace AGENTS.md with a CLAUDE.md written for this repo

One agent doc per repo, and it is CLAUDE.md. Two agent docs drift, and
the one nobody read is always the one holding the rule that mattered —
this repo had a CLAUDE.md whose entire content was an instruction to go
read the other file.

Composed fresh rather than reformatted. Everything factual carries over;
the structure follows what someone working here actually needs first.

Three corrections made while carrying content across:

  - The release flow instructed `git add -A`. That is denied by policy
    and sweeps in whatever else is dirty, including secrets. Now: stage
    by name.
  - The feature-branch mandate is gone. Linear history everywhere, no
    per-repo exceptions as of 2026-08-08.
  - The 8778/8089 split is stated explicitly rather than left implicit
    in two separate sections. 8778 is wakeup.sh's reload server, 8089 is
    the container — testing the wrong one silently exercises the wrong
    build. Both ports verified against wakeup.sh and the deployed stack
    before writing them down.

Adds the live double-ingestion defect (T-1) where someone touching
ingestion will see it, including the part that is not yet established:
whether it merely wastes GPU or actually corrupts Qdrant and Neo4j.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-09 00:00:10 +02:00
co-authored by Claude
parent aac293a053
commit c1cedddd08
2 changed files with 94 additions and 107 deletions
-97
View File
@@ -1,97 +0,0 @@
# AGENTS.md
> **Start every session by reading this file.**
> This file outlines the operational protocols, coding standards, and architectural decisions for this FastAPI project.
## 1. Agent Operational Protocols
### 🧠 Work Patterns (Plan-Act-Reflect)
* **Plan:** Before writing code, briefly outline your plan. Identify which files you will touch and what the side effects might be.
* **Act:** Execute the changes in small, atomic steps.
* **Reflect:** After coding, verify your work. Did you break existing tests? Did you add new tests?
### 📋 Work Tracking
* **Outstanding work lives in pql, not in a markdown file.** `TODO.md` was migrated
on 2026-08-08 and removed.
* `pql ticket list` — open work. `pql plan whatsnext` — the next unblocked item with
context. `pql ticket show T-N --with-children` — detail.
* File new work with `pql ticket new bug|task|story|epic "title"` rather than adding a
TODO section. Tickets travel with the repo: `.pql/changelog/` is committed and
replayed by the git hooks, while the databases are ignored and rebuildable
(`pql plan rebuild`).
### 🛡️ Git Discipline
* **History is linear — no merge commits.** Work goes onto `main` directly, or onto a short-lived branch that is fast-forwarded and deleted. Never create a merge commit. (This replaced a feature-branch mandate on 2026-08-08, to match the workspace convention; `tatlock` remains the one repo that requires branches.)
* **Commit Messages:** Use the [Conventional Commits](https://www.conventionalcommits.org/) format.
* `feat: add user login endpoint`
* `fix: resolve database connection timeout`
* `refactor: split monolith dependency file`
* **Atomic Commits:** Keep commits small. One logical change = one commit.
### 📝 Changelog Maintenance
* **Update `CHANGELOG.md`** with every user-facing change.
* Format: `## [Unreleased] - YYYY-MM-DD` followed by `### Added`, `### Changed`, or `### Fixed`.
### 🚀 Release Flow
When changes are ready for deployment:
1. **Ask user if deploy cycle is desired **
2. **Update version** in `pyproject.toml`:
- Bug fixes: bump patch version (1.8.3 → 1.8.4)
- New features: bump minor version (1.8.4 → 1.9.0)
3. **Update CHANGELOG.md**:
- Move items from `[Unreleased]` to new version section
- Add release date: `## [1.8.4] - 2025-12-16`
4. **Commit and tag**:
```bash
git add -A
git commit -m "fix: description of changes"
git tag v1.8.4
git push origin main --tags
```
5. **CI/CD triggers automatically**:
- Gitea CI builds Docker image on new tag
- Watchtower pulls and deploys to production
- Verify deployment: `curl http://192.168.86.149:8089/health`
---
### 🧪 Local Development Setup
* **Always test locally first** before committing and deploying. The build-deploy loop is slow.
* **Start the local server** with `./wakeup.sh` - logs are written to `logs/server.log` for easy tailing
* **Auto-reload**: The wakeup script runs uvicorn in reload mode - code changes are picked up automatically without restart (except for requirements.txt changes)
* **Test REST endpoints** against `http://localhost:8778` using curl or similar tools
* **Only deploy** when a phase or feature is complete and tested locally
* **Environment**: Copy `.env.example` to `.env` and configure for your local setup (Ollama, Redis, Neo4j, Qdrant, Wiki.js hosts)
* **Running tests**: Always use the venv explicitly to avoid environment mismatches:
```bash
.venv/bin/python -m pytest tests/ # All tests
.venv/bin/python -m pytest tests/ -v # Verbose output
```
---
## 2. FastAPI Architecture & Best Practices
*Reference: [FastAPI Best Practices](https://github.com/zhanymkanov/fastapi-best-practices)*
### 📂 Project Structure (Directory-based, NOT File-type based)
Do **not** group files by type (e.g., one huge `routers` folder). Group by **domain/module** inside a `src/` directory.
**Correct Structure:**
```text
src/
├── auth/
│ ├── router.py # Endpoints
│ ├── schemas.py # Pydantic models
│ ├── service.py # Business logic (CRUD, etc.)
│ ├── dependencies.py# Module-specific dependencies
│ └── config.py # Module-specific settings
├── posts/
│ ├── router.py
│ └── ...
└── main.py # App entry point
+94 -10
View File
@@ -1,17 +1,101 @@
# Claude Code Instructions # CLAUDE.md — Library Desk
**MANDATORY: Read AGENTS.md instead of this file.** FastAPI service that ingests Wiki.js content and serves retrieval over it. Talks to
Postgres (Wiki.js DB + `LISTEN/NOTIFY`), Qdrant (vectors), Neo4j (graph), Ollama
(embeddings) and Redis (job manager). Deployed on tower-of-joy at **:8089**.
This project uses a unified configuration file for all LLM coding agents. ## Ports — these differ, deliberately
## Instructions | | Port | How |
|---|---|---|
| Local dev | **8778** | `./wakeup.sh`, uvicorn reload mode, logs to `logs/server.log` |
| Production | **8089** | container; health at `http://192.168.86.149:8089/health` |
1. **Read and follow AGENTS.md** - All project guidelines are located there Testing `localhost:8089` on the dev box hits the *container*, not your reload server.
2. **Do not modify this file** - Only update AGENTS.md
3. **Do not create or modify other agent-specific files** - Use AGENTS.md as the single source of truth
This approach ensures consistent behavior across all LLM coding agents without managing separate configuration files. ## Work tracking
--- Work lives in **pql**, not a markdown file. `TODO.md` was migrated and removed 2026-08-08.
If you need to update project guidelines, edit AGENTS.md, not this file. ```bash
pql ticket list # open work
pql plan whatsnext # next unblocked item, with context
pql ticket show T-1 # detail
pql ticket new bug "title" # file new work
```
Tickets travel with the repo — `.pql/changelog/` is committed and replayed by the git
hooks; the databases are ignored and rebuildable with `pql plan rebuild`. Do not add a
TODO section to a markdown file.
## Known live defect
**Every wiki page change is ingested twice** (T-1, proven against v1.9.1). The Dockerfile
runs `uvicorn --workers 2`, `startup_event` creates a `WikiChangeListener` per worker, and
Postgres delivers `NOTIFY` to *every* listening session. The debounce in
`wiki_change_listener.py` is an in-process dict and cannot dedupe across workers.
Relevant when touching ingestion: duplicate work reaches Ollama, Qdrant and Neo4j. Whether
it merely wastes GPU or actually corrupts state is **not yet established** — check before
assuming either.
## Working here
**Plan, act, reflect.** Outline which files you will touch and the side effects before
writing. Change in small atomic steps. Afterwards, verify: did existing tests break, and
does the new behaviour have a test?
**Test locally first — the build-deploy loop is slow.** `./wakeup.sh` auto-reloads on code
changes (not on `requirements.txt` changes). Deploy only when a feature is complete and
tested.
Run tests through the venv explicitly, to avoid environment mismatch:
```bash
.venv/bin/python -m pytest tests/
```
Copy `.env.example` to `.env` and configure Ollama, Redis, Neo4j, Qdrant and Wiki.js hosts.
## Git
- **History is linear — no merge commits.** Work on `main`, or a short-lived branch that is
fast-forwarded and deleted. (A feature-branch mandate was retired 2026-08-08 to match the
workspace convention, which now has no per-repo exceptions.)
- **Conventional Commits**: `feat:`, `fix:`, `refactor:`, `docs:`, `chore:`.
- **Atomic commits** — one logical change each.
- **Stage explicitly. Never `git add -A`** — it is denied by policy, and it sweeps in
whatever else is dirty, including secrets.
- Update `CHANGELOG.md` with every user-facing change, under `[Unreleased]` in `Added` /
`Changed` / `Fixed`.
## Releasing
Ask whether a deploy is wanted first — it is not automatic.
1. Bump the version in `pyproject.toml` (patch for fixes, minor for features).
2. Move `[Unreleased]` entries into a dated version section in `CHANGELOG.md`.
3. Stage the changed files by name, commit, tag `vX.Y.Z`, `git push origin main --tags`.
4. Gitea CI builds the image on the tag; Watchtower deploys it.
5. Verify: `curl http://192.168.86.149:8089/health`.
## Architecture
Group by **domain, not by file type**. A single large `routers/` folder is the thing to
avoid.
```text
src/
├── auth/
│ ├── router.py # endpoints
│ ├── schemas.py # pydantic models
│ ├── service.py # business logic
│ ├── dependencies.py # module-scoped dependencies
│ └── config.py # module-scoped settings
└── main.py # app entry point
```
Reference: [FastAPI best practices](https://github.com/zhanymkanov/fastapi-best-practices).
The live contract is always `http://localhost:8089/openapi.json` (70 paths) — generated from
running code, so it cannot drift the way this file can.