From a80f945701ae752587890cfb9d65dbd1f2d5b1d0 Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 16 Mar 2026 12:45:01 -0500 Subject: [PATCH] Add CLAUDE.md with versioned changelog, update README - Created CLAUDE.md with instructions to update changelog and README on every commit, version number (v1.2.0), and full changelog from v1.0.0 - Updated README: document-scope BLIGHT:: syntax, processing order, two-line failure format, complete_document() in AI provider section Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9710d16 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,45 @@ +# CLAUDE.md — BLIGHT: CUE + +## Instructions for Claude + +- **Every commit**: Update the Changelog section below with a summary of what changed and bump the version number if appropriate. +- **Every commit**: If the changes affect anything documented in README.md (trigger syntax, failure behavior, setup, project structure, AI provider info, etc.), update README.md in the same commit. + +--- + +## Version + +**v1.2.0** + +--- + +## Changelog + +### v1.2.0 +- Fixed loop re-processing: AI responses are sanitized by replacing `BLIGHT:` with `BLIGHT:` before being written to the document, preventing the service's own commits from triggering another processing cycle. +- Branch awareness: branch is now extracted from `refs/heads/` in the push payload and passed to all Gitea read/write calls, so pushes to non-default branches are handled correctly. +- Commit messages now include the file path (e.g. `BLIGHT: process triggers in notes/todo.md`). + +### v1.1.0 +- Added `BLIGHT::` (double colon) document-scope trigger syntax. Unlike `BLIGHT:` which replaces only the trigger line, `BLIGHT::` replaces the entire file content with the AI's rewritten document. +- Multiple `BLIGHT::` triggers in one file are processed sequentially, each operating on the result of the previous. +- Inline `BLIGHT:` triggers are always processed before `BLIGHT::` triggers. +- Both trigger types are now case-insensitive (`blight:`, `BLIGHT:`, `Blight::`, etc. all match). +- Failure comments updated to two-line format: + ``` + + + ``` +- Added `complete_document()` to `AIProvider` ABC and `GeminiProvider`, with a dedicated system prompt instructing the model to return the full rewritten document. + +### v1.0.0 — Initial release +- Flask webhook server listening for Gitea push events. +- HMAC-SHA256 signature verification on all incoming webhooks. +- Scans changed `.md` files for `BLIGHT: ` trigger lines. +- Sends full document + instruction to Google Gemini 2.5 Flash-Lite. +- Replaces trigger line with AI response in-place and commits back to Gitea. +- Retry logic: 3 attempts with exponential backoff (1s, 2s, 4s). +- Processes webhooks in background threads to return 200 immediately. +- Deduplicates file paths across multiple commits in a single push. +- Self-updates on startup via `git pull --ff-only`. +- Pluggable `AIProvider` ABC for swapping AI backends. diff --git a/README.md b/README.md index 604c7f2..6d21ebc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A module in the **BLIGHT** ecosystem. -BLIGHT: CUE monitors Gitea repositories containing markdown files. When a push is received, it scans changed files for `BLIGHT:` trigger lines, sends the surrounding document to an AI model along with the instruction, and writes the result back to the file in-place — fully automated. +BLIGHT: CUE monitors Gitea repositories containing markdown files. When a push is received, it scans changed files for `BLIGHT:` trigger lines, sends the document to an AI model along with the instruction, and writes the result back to the file in-place — fully automated. --- @@ -10,16 +10,25 @@ BLIGHT: CUE monitors Gitea repositories containing markdown files. When a push i 1. You write a `BLIGHT:` trigger anywhere in a markdown file and push it to Gitea. 2. Gitea sends a webhook POST to this server. -3. The server fetches the file, finds all `BLIGHT:` triggers, and processes them one by one. -4. Each trigger is replaced with the AI's response at the exact position of the trigger line. -5. The updated file is committed back to the repo automatically. +3. The server fetches the file, finds all `BLIGHT:` triggers, and processes them. +4. Each trigger is replaced with the AI's response, then the updated file is committed back automatically. ### Trigger Syntax +Triggers are case-insensitive — `BLIGHT:`, `blight:`, `Blight::`, etc. all work. + +**Inline trigger** — replaces only the trigger line with the AI's response: + ``` BLIGHT: ``` +**Document-scope trigger** — replaces the entire file with the AI's rewritten version: + +``` +BLIGHT:: +``` + Examples: ```markdown @@ -31,22 +40,30 @@ BLIGHT: Explain the key differences between は and が based on the paragraph a ``` ```markdown -BLIGHT: Spell check this entire document and list any errors found. +BLIGHT: Write a conclusion paragraph for this document. ``` ```markdown -BLIGHT: Write a conclusion paragraph for this document. +BLIGHT:: Spellcheck and lightly reformat this entire document. ``` +### Processing Order + +When a file contains multiple triggers: + +1. All inline (`BLIGHT:`) triggers are processed first, in document order. +2. All document-scope (`BLIGHT::`) triggers are processed next, in document order — each one operates on the result of the previous. + ### Failure Behavior If the AI call fails after 3 attempts, the trigger is replaced with: ```html + ``` -You can re-trigger processing by editing the file to restore the original `BLIGHT:` line and pushing again. +You can re-trigger processing by editing the file to restore the original trigger line and pushing again. --- @@ -224,12 +241,17 @@ from abc import ABC, abstractmethod class AIProvider(ABC): def complete(self, document: str, instruction: str) -> str: + """Return text to insert in place of an inline BLIGHT: trigger.""" + ... + + def complete_document(self, document: str, instruction: str) -> str: + """Return the full rewritten document for a BLIGHT:: trigger.""" ... ``` To add a new provider (e.g. OpenRouter): -1. Create `ai/openrouter.py` and implement `AIProvider`. +1. Create `ai/openrouter.py` and implement both methods of `AIProvider`. 2. In `processor.py`, replace `GeminiProvider()` with your new class. ---