Inline # comments in gitignore are not supported — they were silently breaking three patterns (data/checkpoints/, data/adapter-migration-state.json, .claude/agents/.generated/). Moved comments to their own lines and added missing entries for runtime dirs (data/audit/, data/logs/, etc.) and temp files (.interaction_tmp.json, .design-build/, .taskmaster bak files). Also tracks previously untracked legitimate files: scripts, tests, docs, skills references, .env.example, taskmaster templates. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
307 lines
9.6 KiB
Markdown
307 lines
9.6 KiB
Markdown
# Per-Agent CLAUDE.md Versioning & Validation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** הוסף validation ו-version tracking לקבצי הוראות הסוכנים. כעת, לפני שה-sync script מחיל שינויים, הוא מאמת שכל `instructionsFilePath` קיים. בנוסף, metadata של הסוכן ב-DB יכיל `claude_md_mtime` — השינוי האחרון בקובץ — כדי לזהות drift.
|
||
|
||
**Architecture:** `sync_agents_across_companies.py` מקבל `--check-instructions` flag שסורק את כל הסוכנים ומדווח על קבצים חסרים/ישנים. ב-`--apply`, מתווספת בדיקת pre-flight שמבטלת את הsync אם קובץ חסר. `agents.metadata` מקבל `claude_md_mtime` עם ה-mtime בפועל של הקובץ.
|
||
|
||
**Tech Stack:** Python 3.10+, asyncpg, httpx, `os.path.getmtime()`, Paperclip REST API (`PATCH /api/agents/{id}`).
|
||
|
||
---
|
||
|
||
## File Map
|
||
|
||
| Action | File |
|
||
|--------|------|
|
||
| Modify | `legal-ai/scripts/sync_agents_across_companies.py` — `--check-instructions` flag, pre-flight, metadata update |
|
||
|
||
זה הקובץ היחיד שצריך לגעת בו. כל שאר הלוגיקה קיימת כבר.
|
||
|
||
---
|
||
|
||
## Task 1: הוסף `--check-instructions` flag
|
||
|
||
**Files:**
|
||
- Modify: `legal-ai/scripts/sync_agents_across_companies.py`
|
||
|
||
- [ ] **Step 1: קרא את החלק של `argparse` בסקריפט**
|
||
|
||
```bash
|
||
grep -n "argparse\|add_argument\|--verify\|--dry-run\|--apply" \
|
||
/home/chaim/legal-ai/scripts/sync_agents_across_companies.py | head -20
|
||
```
|
||
|
||
- [ ] **Step 2: הוסף את הargument**
|
||
|
||
מצא את הסקציה שמגדירה `args` והוסף:
|
||
|
||
```python
|
||
parser.add_argument(
|
||
"--check-instructions",
|
||
action="store_true",
|
||
help="Scan all agents' instructionsFilePath and report missing/outdated files",
|
||
)
|
||
```
|
||
|
||
- [ ] **Step 3: הוסף את הפונקציה `check_instructions()`**
|
||
|
||
הוסף לפני `async def main()`:
|
||
|
||
```python
|
||
async def check_instructions(agents: list[dict]) -> bool:
|
||
"""Print a report of all agents' instruction files. Returns True if all OK."""
|
||
all_ok = True
|
||
print(f"\n{'Agent':<30} {'File':<60} {'Status':<15} {'Size':>8} {'Modified'}")
|
||
print("-" * 120)
|
||
|
||
for agent in agents:
|
||
adapter_cfg = agent.get("adapter_config") or {}
|
||
if isinstance(adapter_cfg, str):
|
||
import json as _json
|
||
adapter_cfg = _json.loads(adapter_cfg)
|
||
|
||
file_path = adapter_cfg.get("instructionsFilePath", "")
|
||
name = agent.get("name", agent.get("id", "?"))[:29]
|
||
|
||
if not file_path:
|
||
print(f"{name:<30} {'(none)':<60} {'⚠️ NOT SET':<15}")
|
||
continue
|
||
|
||
if not os.path.exists(file_path):
|
||
print(f"{name:<30} {file_path[-59:]:<60} {'❌ MISSING':<15}")
|
||
all_ok = False
|
||
continue
|
||
|
||
stat = os.stat(file_path)
|
||
size_kb = stat.st_size // 1024
|
||
mtime = datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M")
|
||
|
||
# Compare with DB metadata
|
||
metadata = agent.get("metadata") or {}
|
||
if isinstance(metadata, str):
|
||
import json as _json
|
||
metadata = _json.loads(metadata)
|
||
|
||
db_mtime = metadata.get("claude_md_mtime", "")
|
||
actual_mtime = str(int(stat.st_mtime))
|
||
drift = " ⚠️ DRIFT" if db_mtime and db_mtime != actual_mtime else ""
|
||
|
||
print(f"{name:<30} {file_path[-59:]:<60} {'✅ OK':<15} {size_kb:>6}KB {mtime}{drift}")
|
||
|
||
print()
|
||
return all_ok
|
||
```
|
||
|
||
> `from datetime import datetime` ו-`import os` — בדוק שמיובאים בראש הסקריפט. אם לא, הוסף.
|
||
|
||
- [ ] **Step 4: הוסף קריאה ל-`check_instructions()` ב-`main()`**
|
||
|
||
בתוך `async def main()`, אחרי שloading הagents מה-DB:
|
||
|
||
```python
|
||
if args.check_instructions:
|
||
all_ok = await check_instructions(master_agents + mirror_agents)
|
||
sys.exit(0 if all_ok else 1)
|
||
```
|
||
|
||
- [ ] **Step 5: בדיקה**
|
||
|
||
```bash
|
||
cd /home/chaim/legal-ai
|
||
python scripts/sync_agents_across_companies.py --check-instructions
|
||
```
|
||
|
||
Expected: טבלה עם כל הסוכנים, paths, סטטוס ✅/❌.
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
```bash
|
||
cd /home/chaim/legal-ai
|
||
git add scripts/sync_agents_across_companies.py
|
||
git commit -m "feat: add --check-instructions flag to sync script"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: הוסף pre-flight validation לפני `--apply`
|
||
|
||
**Files:**
|
||
- Modify: `legal-ai/scripts/sync_agents_across_companies.py`
|
||
|
||
- [ ] **Step 1: מצא את נקודת הכניסה של `--apply`**
|
||
|
||
```bash
|
||
grep -n "args.apply\|if.*apply\|apply.*mode" \
|
||
/home/chaim/legal-ai/scripts/sync_agents_across_companies.py | head -10
|
||
```
|
||
|
||
- [ ] **Step 2: הוסף pre-flight לפני apply**
|
||
|
||
בתחילת בלוק `--apply`, לפני כל שינוי:
|
||
|
||
```python
|
||
if args.apply:
|
||
# Pre-flight: abort if any agent is missing its instructions file
|
||
print("🔍 Pre-flight: checking instruction files...")
|
||
all_ok = await check_instructions(master_agents + mirror_agents)
|
||
if not all_ok:
|
||
print("❌ Abort: one or more instruction files are missing. Fix paths before --apply.")
|
||
sys.exit(1)
|
||
print("✅ Pre-flight passed.\n")
|
||
# ... rest of apply logic ...
|
||
```
|
||
|
||
- [ ] **Step 3: בדיקה — הפעל עם קובץ חסר (סימולציה)**
|
||
|
||
```bash
|
||
# שנה זמנית path לקובץ שלא קיים
|
||
cd /home/chaim/legal-ai
|
||
python scripts/sync_agents_across_companies.py --dry-run 2>&1 | head -5
|
||
```
|
||
|
||
Expected: dry-run עובר. אם תנסה `--apply` עם agent שhis file חסר — הsync יבוטל.
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
cd /home/chaim/legal-ai
|
||
git add scripts/sync_agents_across_companies.py
|
||
git commit -m "feat: add pre-flight instruction file validation before --apply"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: עדכן `agents.metadata` עם `claude_md_mtime`
|
||
|
||
**Files:**
|
||
- Modify: `legal-ai/scripts/sync_agents_across_companies.py`
|
||
|
||
- [ ] **Step 1: מצא את `compute_diff()` או `apply_diff()`**
|
||
|
||
```bash
|
||
grep -n "def compute_diff\|def apply_diff\|def build_patch\|metadata" \
|
||
/home/chaim/legal-ai/scripts/sync_agents_across_companies.py | head -20
|
||
```
|
||
|
||
- [ ] **Step 2: הוסף פונקציה `get_claude_md_mtime()`**
|
||
|
||
```python
|
||
def get_claude_md_mtime(adapter_config: dict) -> str | None:
|
||
"""Return the Unix mtime of the agent's instructionsFilePath, or None if missing."""
|
||
path = adapter_config.get("instructionsFilePath", "")
|
||
if not path or not os.path.exists(path):
|
||
return None
|
||
return str(int(os.path.getmtime(path)))
|
||
```
|
||
|
||
- [ ] **Step 3: שלב mtime בbuild של metadata patch**
|
||
|
||
מצא את המקום שמכין את ה-`metadata` לsync. הוסף:
|
||
|
||
```python
|
||
# Build metadata patch with claude_md_mtime
|
||
current_metadata = master_agent.get("metadata") or {}
|
||
if isinstance(current_metadata, str):
|
||
import json as _json
|
||
current_metadata = _json.loads(current_metadata)
|
||
|
||
adapter_cfg = master_agent.get("adapter_config") or {}
|
||
if isinstance(adapter_cfg, str):
|
||
import json as _json
|
||
adapter_cfg = _json.loads(adapter_cfg)
|
||
|
||
mtime = get_claude_md_mtime(adapter_cfg)
|
||
if mtime:
|
||
current_metadata["claude_md_mtime"] = mtime
|
||
current_metadata["claude_md_last_synced"] = datetime.utcnow().isoformat() + "Z"
|
||
```
|
||
|
||
כלול את ה-`current_metadata` המעודכן ב-PATCH לAPI.
|
||
|
||
- [ ] **Step 4: בדוק שה-metadata מתעדכן**
|
||
|
||
הפעל `--dry-run` וחפש `claude_md_mtime` בoutput:
|
||
```bash
|
||
python scripts/sync_agents_across_companies.py --dry-run 2>&1 | grep -i "mtime\|metadata" | head -10
|
||
```
|
||
|
||
לאחר `--apply`, בדוק ב-DB:
|
||
```bash
|
||
psql -h localhost -p 54329 -U paperclip -c \
|
||
"SELECT name, metadata->>'claude_md_mtime' AS mtime FROM agents WHERE metadata->>'claude_md_mtime' IS NOT NULL LIMIT 5" \
|
||
paperclip
|
||
```
|
||
|
||
- [ ] **Step 5: Commit**
|
||
|
||
```bash
|
||
cd /home/chaim/legal-ai
|
||
git add scripts/sync_agents_across_companies.py
|
||
git commit -m "feat: track claude_md_mtime in agents.metadata during sync"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: הוסף `make check-agents` shortcut
|
||
|
||
**Files:**
|
||
- Modify: `legal-ai/Makefile` (אם קיים) אחרת הוסף alias
|
||
|
||
- [ ] **Step 1: בדוק אם Makefile קיים**
|
||
|
||
```bash
|
||
ls /home/chaim/legal-ai/Makefile 2>/dev/null && echo "EXISTS" || echo "MISSING"
|
||
```
|
||
|
||
- [ ] **Step 2א: אם Makefile קיים — הוסף target**
|
||
|
||
```makefile
|
||
check-agents:
|
||
python scripts/sync_agents_across_companies.py --check-instructions
|
||
|
||
sync-agents-dry:
|
||
python scripts/sync_agents_across_companies.py --dry-run
|
||
|
||
sync-agents:
|
||
python scripts/sync_agents_across_companies.py --apply
|
||
```
|
||
|
||
- [ ] **Step 2ב: אם Makefile לא קיים — הוסף alias ל-`~/.bashrc`**
|
||
|
||
```bash
|
||
echo "alias check-agents='cd /home/chaim/legal-ai && python scripts/sync_agents_across_companies.py --check-instructions'" >> ~/.bashrc
|
||
source ~/.bashrc
|
||
```
|
||
|
||
- [ ] **Step 3: בדוק**
|
||
|
||
```bash
|
||
# אם Makefile:
|
||
make -C /home/chaim/legal-ai check-agents
|
||
# אם alias:
|
||
check-agents
|
||
```
|
||
|
||
Expected: טבלת סוכנים מוצגת.
|
||
|
||
- [ ] **Step 4: Commit (אם Makefile)**
|
||
|
||
```bash
|
||
cd /home/chaim/legal-ai
|
||
git add Makefile
|
||
git commit -m "feat: add check-agents and sync-agents make targets"
|
||
```
|
||
|
||
---
|
||
|
||
## אימות סופי
|
||
|
||
| בדיקה | פקודה | תוצאה מצופה |
|
||
|-------|-------|-------------|
|
||
| `--check-instructions` | `python sync_agents... --check-instructions` | טבלה עם ✅ לכל agent |
|
||
| Pre-flight בולם apply | מחק קובץ זמנית + `--apply` | Abort עם הודעה ברורה |
|
||
| mtime ב-DB | `SELECT metadata->>'claude_md_mtime' FROM agents` | timestamp לכל agent |
|
||
| DRIFT זוהה | שנה קובץ + `--check-instructions` | ⚠️ DRIFT מוצג |
|
||
| shortcut | `check-agents` או `make check-agents` | עובד |
|