## MEMORY COMPACTION RULES

Apply these at session end when thresholds are hit. No external scripts needed.

- `dbt_archive.md` > 80 items: compress the oldest 40 into a 3-line paragraph per PWA (date range + key milestones only). Keep full detail for the most recent 40.
- `parallel_sessions.md` lock history: enforce last-10 trim immediately after appending a new entry. Never let it exceed 15 rows.
- `dbt_[pwa].md`: if a PWA has had no work in 30+ days AND has no pending items, collapse to a 5-line status paragraph (SW version, last migration, stable date).
- Freshness rule: if a memory file contains file paths, function names, or version numbers and was last updated > 21 days ago, verify against current code before using.

---

## PLAYWRIGHT TEST RUNNER

Install path: /var/www/360lm/
Config: /var/www/360lm/playwright.config.js
Tests: /var/www/360lm/tests/[pwa].spec.js
Reports: /var/www/360lm/test_reports/

### Run Commands
Single PWA test (background):
  cd /var/www/360lm && npx playwright test tests/[pwa].spec.js \
  --reporter=json > test_reports/pw_[pwa]_$(date +%Y%m%d_%H%M).json 2>&1 &

All tests:
  cd /var/www/360lm && npx playwright test

Read last report:
  cat /var/www/360lm/test_reports/last_run.json

### Rules
- Always fire Playwright AFTER self-test, in background
- Use _template.spec.js as base for every new PWA test file
- If Playwright test FAILS: do not deploy to staging
- Update [pwa].spec.js whenever new form fields or
  screens are added to that PWA

## PWA DevGuide & /new-pwa (ADR-099)

`pwa_dev_style.md` is an INDEX, not the guide. Content lives in `docs/style/<topic>.md` — load only the topics the task needs. For any NEW PWA, invoke the `/new-pwa` skill first (mandatory questionnaire Q0.1–Q0.14), then load the topic files its answers point to. Never re-inline guide content into one file.

---

## Agent orchestration (2-core VPS)

Max 2 concurrent claude sessions on this VPS (see parallel_sessions.md) and, within a session, prefer 1 orchestrator + at most 2 background agents. Continue long-lived agents (SendMessage/resume) instead of respawning. Overflow or heavy fan-out work goes to claude.ai/code cloud sessions, not this box. Nightly automation (tests 01:00, graphify 02:00, analysis 04:30 IST, weekly compaction Sun 03:30 IST) owns the small hours — avoid scheduling other heavy jobs there.

---

## Model routing

- Routine work (dbt updates, small fixes, extraction runs, test runs): default session model (sonnet, medium effort).
- Architecture, MDDs, DB migrations design, cross-PWA changes, frontend/design passes: switch to opus (or the highest available tier) at high effort — start the session with it or ask the user to.
- Subagents stay on haiku (`CLAUDE_CODE_SUBAGENT_MODEL`) unless the subtask is verification-critical.

---

## ponytail

Ponytail full mode is always active in this project. No need to type `/ponytail` — treat it as permanently on.

**Scope boundary:** ponytail governs logic, architecture, and code volume — NOT visual design. Typography, color, spacing, motion, and polish follow the frontend-design skill and `shared/theme-v2.css` (ADR-100); visual craft is never "unrequested complexity" and must not be stripped by the YAGNI ladder.

Before writing any code, walk the decision ladder: Does it need to exist (YAGNI)? → Reuse existing helper? → Stdlib? → Platform/framework? → Installed dep? → One-liner? → Only then write minimal code.

No unrequested abstractions, no speculative features, no new deps if avoidable. Mark deliberate shortcuts with `// ponytail: <what> <ceiling> <upgrade trigger>`.

Deactivate only if user explicitly says "stop ponytail", "normal mode", or `/ponytail off`.

---

## adr-kit

Architecture Decision Records live at `docs/adr/`. Installed: skill (`/adr`), agent (`adr-generator`), template, index, coding rules.

Rules:
- Before any architecturally significant change, check `docs/adr/README.md` for an existing ADR governing that area.
- If none exists and the change affects multiple PWAs, shared infra, hub session format, SW cache contract, or proxy routing → create an ADR first via the `adr-generator` agent.
- Full coding rules: `docs/adr/adr-coding-rules.md`

---

## graphify

This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships.

Rules:
- For codebase questions, first run `graphify query "<question>"` when graphify-out/graph.json exists. Use `graphify path "<A>" "<B>"` for relationships and `graphify explain "<concept>"` for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output.
- If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
- After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost).

---

## markitdown MCP — Limitation Gate

Before calling `convert_to_markdown(uri)`, check the file type against the known limitation table below.
If the file falls into a limited category, STOP and present the limitation + options to the user.
Wait for explicit user confirmation before proceeding.

| File type / situation | Known limitation | Alternative to offer |
|---|---|---|
| Styled PDF (columns, headings, tables) | Flattens to plain paragraphs — structure lost | Try `--llm` mode (Gemini/Claude vision); or extract text manually |
| PDF with embedded diagrams/charts | Graphics silently dropped — only surrounding text extracted | Use Gemini Vision or screenshot-based OCR instead |
| JS-rendered HTML (SPAs, dashboards) | Dynamic content not captured — only static HTML shell | Pre-render with Playwright, save static HTML, then convert |
| Scanned PDF / image-only PDF (no text layer) | Returns empty or near-empty output | Use Tesseract OCR or Gemini Vision directly |
| Audio (WAV/MP3) | Transcription quality depends on speech-to-text model accuracy | Review transcript before using; re-run with better model if garbled |
| PPTX with heavy visuals | Slide text extracted but images/diagrams lost | Export slides as PNGs first, then use image OCR per slide |

**Standard confirmation prompt to show the user:**
> ⚠️ markitdown limitation detected for `[filename]`: [specific limitation].
> Options:
> A) Proceed with markitdown anyway (accept partial output)
> B) Use alternative: [specific alternative]
> C) Skip this file
> Which do you prefer?

If user chooses A: call `convert_to_markdown`, then explicitly note what may be missing in the result summary.
If user chooses B: execute the alternative they selected.
If user chooses C: skip and continue with remaining files.
