# TX4H Project — Claude Instructions
# System Integration Guidance
You have access to my secondary developer knowledge base. Always cross-reference these local note configurations before making major structural or architectural changes:
- Architecture Strategy: @~/Dev-Brain/01-Projects/tx4h/tx4h-ADR.md
- Past Logged Bugs: @~/Dev-Brain/01-Projects/tx4h/tx4h-Bugs-Log.md
- Global Tech Snippets: @~/Dev-Brain/02-Snippets/
## Session Start Checklist
- Check deferred tools for `mcp__tx4h-live__mysql_query` — if absent, tell user to Reload Window before writing any SQL
- Check the mtime of `CLAUDE-db-schema-tx4h.md` — if it's more than 7 days old, offer to refresh it (also refresh on request, or before/after any task that changes DB structure). Regenerate by querying `information_schema.COLUMNS` for `TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE 'tx4h_%'` via `mcp__tx4h-live__mysql_query`, batching with `TABLE_NAME > '<last table>'` if results get capped at 500 rows (check the `truncated` flag), then use PowerShell (`ConvertFrom-Json` + `Group-Object`) to compact each table into one line — do not read the raw query results into context, they're large. Same refresh method applies to the other `CLAUDE-db-schema-*.md` files below, just swap the `LIKE` pattern.
- If the docker test env (`CLAUDE-docker-testenv.md`) will be used this session, refresh its DB from prod (`mysql_export` → `docker/import-dump.sh`) at the start rather than waiting to hit a stale-data symptom reactively — confirmed 2026-08-06 a 5-day-stale docker DB silently rendered an outdated Fabrik list config (missing a stats/bulk-approve feature) with no error, only caught by visual comparison against prod.
- Ensure Milvus Server (another docker env) is up and running whenever working on tx4h
---
## DB schema reference files — read before writing SQL against unfamiliar tables
The whole site shares one flat Joomla DB prefix (`jtbl_`, not the standard `#__`) — every
extension's tables live under that prefix, not their own. Pick the file by which tables the
task touches instead of querying `DESCRIBE` fresh each time:
| File | Covers | When to use |
|---|---|---|
| `CLAUDE-db-schema-tx4h.md` | `tx4h_%` — the site's own custom schema | Default for almost everything — member/family/payment/club data |
| `CLAUDE-db-schema-eventbooking.md` | `jtbl_eb_%` — Event Booking (`com_eventbooking`) | Event registration/booking work, or anything touching the shared Auth.net merchant account (see payment module notes) |
| `CLAUDE-db-schema-fabrik.md` | `jtbl_fabrik_%` — Fabrik core | Editing Fabrik forms/lists/elements/joins themselves, not a specific form's own data table |
| `CLAUDE-db-schema-pmform.md` | `jtbl_pf_%` — boss's legacy Payment Forms component | The `authaccepthosted_pmf_*.php` callback files, or anything referencing `com_pmform` |
Small single/few-table components have their DB schema folded into their existing topic doc
instead of a separate file: `jtbl_bgcheck_%` → end of [CLAUDE-bgcheck-sterling-api.md](CLAUDE-bgcheck-sterling-api.md);
`jtbl_mimic_log` → end of [CLAUDE-mimick.md](CLAUDE-mimick.md); `jtbl_scorm_rte` → end of
[CLAUDE-training.md](CLAUDE-training.md).
Plain Joomla core tables (`jtbl_users`, `jtbl_content`, `jtbl_menu`, etc. — no component
prefix) and untouched third-party extensions (eDocMan, HelpDesk Pro, Akeeba) have no dedicated
file — standard/well-documented Joomla schema, or not yet relevant to any work here. Generate
one on demand (same method as above) if a task ever actually needs it.
---
## Code search — prefer claude-context over Grep
Both are indexed via claude-context (semantic search):
- `C:\vsc-projects\tx4h` — the project itself
- `C:\vsc-source\tx4h` — read-only Joomla 5 + Fabrik source copy
For searches over either path, use `mcp__claude-context__search_code` first. Only fall back to Grep/Glob for exact string/symbol lookups or single known filenames. `mcp__claude-context__search_code` is deferred — `ToolSearch` for it if not already loaded. The index does not auto-update on file changes — re-run `mcp__claude-context__index_codebase` (with `force: true` if prompted) after a large batch of edits if search results seem stale.
If indexing results seem stale, wrong, or bloated after indexing `C:\vsc-source\tx4h` → [CLAUDE-claude-context-indexing.md](CLAUDE-claude-context-indexing.md) (known duplicate-chunk bug + fix + verification steps).
---
## Project Identity
Texas 4-H–specific rewrite of 4-H Online. Client: tx4h.tamu.edu.
Stack: Joomla 5 + Fabrik 4.6.4 + YooTheme Pro + UIkit 3 + PHP 8.x.
Working files: `C:/vsc-projects/tx4h/`. Editor: VS Code.
Never suggest Fabrik F5/F6 — not production-ready.
---
## Local Docker Test Environment
Full local copy of the live site (real prod code + refreshable prod data) for testing without touching the live site → [CLAUDE-docker-testenv.md](CLAUDE-docker-testenv.md). Read before bringing up, refreshing, or debugging it.
---
## Directory Structure
```
includes-4honline/ # All TX4H custom pages and business logic
includes/ # Shared vars, user profile, URL helpers, CSS
4h-variables.php # Standard include for all pages — loads $myApp, $myUser, $myTx4hUser, URL vars
4h-variables-urls.php # Shared URL variables (SEF paths, menu IDs)
4h-user-profile.php # $myTx4hUser builder
4h-membership-payment.php # Auth.net payment flow (active development)
4h-membership-training.php # AVT/CPT training module
plugins/ # Joomla plugins (backgroundcheck, mimic, xapi, scormrte, etc.)
components/ # Custom Joomla components (if any)
```
---
## Database
### Table prefix: `jtbl_`
All Joomla core tables use `jtbl_` (e.g. `jtbl_users`, `jtbl_user_usergroup_map`). Not the standard `j5_` or `#__`.
### MySQL MCP — use proactively
`mcp__tx4h-live__mysql_query` → read-only access to the **live production** database (tx4h.tamu.edu). Supports SELECT, SHOW, DESCRIBE, EXPLAIN, WITH — no writes.
**Before writing any SQL or Fabrik eval that references a table** — query schema first to confirm column names and types.
This is live data — treat query results as real member/PII data, not sample data.
### Schema gotcha — repeat county table
`tx4h_users_repeat_addl_county_id.parent_id` references `tx4h_users.id` (auto-increment PK), **not** `tx4h_users.userid` (Joomla user ID). Both columns needed when joining.
---
## Joomla User Groups
| Group | ID | Access scope |
|---|---|---|
| State Level | 13 | Sees everyone |
| Region Level | 12 | Sees everyone |
| District Level | 11 | Sees everyone |
| County Admin | 14 | Scoped to assigned counties |
| County Level | 10 | Blocked from manager pages |
| Club Manager | 15 | Blocked from manager pages |
| Pilot Testing Group | 16 | Feature-flag style access, not location-scoped |
| Help Desk Only | 17 | Not location-scoped |
| Employee | 18 | Not location-scoped |
| BG Check Reviewer | 19 | Orthogonal to the county/district/region/state hierarchy — stacks on top of a user's existing group rather than replacing it. Gates the background-check denial review dashboard. |
Priority map (lower = broader): State(1) > Region(2) > District(3) > CountyAdmin(4) > County(5) > Club(6). Pilot Testing Group, Help Desk Only, Employee, and BG Check Reviewer sit outside this ladder — they're independent permissions, not rungs on it.
Joomla view access levels:
- **13 = "County Admin Only"** — gates county_id prefilter to County Admin users
- **16 = "BG Check Reviewer Access"** — Administrator, Super Users, BG Check Reviewer
---
## $myTx4hUser — Composite User Profile
Composite user profile object (permissions, location scope, account fields) → [CLAUDE-user-profile.md](CLAUDE-user-profile.md). Read before writing code that checks a user's permissions, location scope, or profile data.
---
## Comment Style - Two Conventions
### Plugin files (`plugins/**/*.php`)
- Match Joomla/Fabrik native style so plugin code looks like it belongs in Joomla core
- Use `/** */` docblocks on methods/functions
- Use `//` comments inside method bodies
- Use standard Joomla variable names (`$app`, `$db`, `$query`) instead of TX4H `$my` names
### TX4H custom code (`includes-4honline/`, Fabrik evals, custom PHP)
- Use `//` inline comments only - no `/** */`, `/* */`, or banner blocks
- Place comments directly above the relevant code block, not as section headers
- Explain why, intent, context, and gotchas a newcomer needs; do not narrate what the code plainly does
- Keep comments terse, one line when possible
- Never write `Fix:` or task labels in code comments
- Skip comments only on self-evident one-liners
---
## Fabrik-Specific Rules
Snippet header convention, prefilter eval behavior, placeholder parsing context, databasejoin ORDER BY, FABRIKFILTER constants → [CLAUDE-fabrik-rules.md](CLAUDE-fabrik-rules.md). Read before writing or editing any Fabrik eval snippet, element, or filter.
---
## Progress-indicator sync points — read before touching payment/completion gating
"Is this member's payment/application complete" is independently re-judged in 9+ separate
places (PHP pages, Fabrik calc elements, 2 SQL views) instead of one shared source — adding a
new completion state (e.g. offline payment) means touching all of them or some page silently
drifts out of sync. Full list + the exact OR to repeat → the comment block directly above
`h_memberHasOfflinePaymentSelected()` in `includes-4honline/includes/helpers.php`. Check that
list whenever you add a new payment/completion gate, and add the new one to it.
---
## Source Research References
- **Bitbucket API:** `api.bitbucket.org/2.0/repositories/fabrikar/fabrik/src/master/{path}` — use `curl`, not `web_fetch`
- **Fabrik forum:** curl with session cookie `xf_user=78866%2CyFq1Y9TcvGoG3ikgtbIB5JG0kKboxdNdcQGoasmH`
- **Local source copy (read-only):** `C:\vsc-source\tx4h\` — full Joomla 5 + Fabrik install; dir index at `C:\vsc-source\tx4h-dirs.txt`
---
## Feature Module Docs
- Mimick/Impersonate plugin → [CLAUDE-mimick.md](CLAUDE-mimick.md)
- Training module (AVT/CPT) → [CLAUDE-training.md](CLAUDE-training.md)
- Payment module (Auth.net) → `includes-4honline/4h-membership-payment.php` (active development; no dedicated doc yet)
- Background check plugin's Sterling Volunteers API → [CLAUDE-bgcheck-sterling-api.md](CLAUDE-bgcheck-sterling-api.md) (vendor API reference + status matrix + go-live gotchas; raw doc capture in `plugins/system/backgroundcheck/docs/`)
Read those files when working on those features.
---
## Tooling
### Local model offload (Ollama)
Before reading a large file/log/diff (>~3000 lines or >~200KB of bulk text) into context
yourself, or before drafting repetitive mechanical edits across many files → [CLAUDE-ollama-offload.md](CLAUDE-ollama-offload.md).
### Subagent model
Spawned Explore/lookup subagents → always pass `model: "haiku"`.
### Deploying to the live server / raw SSH
- Committed-file deploys → `.claude/scripts/deploy-file.sh path/to/file` (refuses uncommitted/drifted files; drift-checks again right before writing). Read-only drift check alone → `.claude/scripts/check-server-drift.sh [files...]` (omit args to check everything).
- For anything deploy-file.sh doesn't cover (deleting a remote file, `ls`/inspecting server state, one-off commands): `source .claude/scripts/lib/ssh-conn.sh` from repo root, then `ssh_run "shell command"`. File transfer helpers: `scp_get remote local` / `scp_put local remote`. `REMOTE_ROOT="public_html"` is the doc-root prefix for paths under it.
- The library auto-prefers routing through WSL's OpenSSH (faster ControlMaster reuse); do not hand-roll a plain `ssh`/`scp` call — always go through `ssh_run`/`scp_get`/`scp_put` so that fallback logic stays in one place.
<!-- claude-mem-lite:begin v1 -->
## claude-mem-lite — persistent memory
PreToolUse hooks already run `mem_recall` for past lessons before Read/Edit/Write. The calls worth making proactively:
| When | Call |
|------|------|
| Before Edit/Write | hook already recalled; if a `#NN` lesson was injected, cite `#NN` next time you produce user-visible text (citing = adopting the feedback; uncited lessons decay) |
| After fixing a non-trivial bug | `mem_save(type="bugfix", lesson_learned="<root cause + fix>", importance=2)` |
| After a non-obvious architecture decision | `mem_save(type="decision", lesson_learned="<constraint + tradeoff>")` |
| Deferring to a future session | `mem_defer({title, priority:1|2|3, detail})`; when fixed, add `closes_deferred=[N]` to `mem_save` |
| Looking up past work / history | `mem_search "keywords"` · `mem_recent` · `mem_timeline` |
Path cost is round-trips, not milliseconds: the PreToolUse hook above already recalls (0 calls) — prefer it. For an explicit query, if these `mem_*` tools are deferred behind ToolSearch this session, the Bash CLI (exact path in the detail doc) is one call vs two (ToolSearch + call).
Full tool + CLI tables, citation/decay rules, and save discipline → `.claude/plugin_claude_mem_lite.md`
<!-- claude-mem-lite:end -->
---
## AGENTIC EXECUTION WORKFLOW (LEAN SUPERPOWERS)
### 1. Brainstorm & Initial Spec
- Vague tasks trigger an immediate brainstorm block. Ask clarifying questions and detail alternatives before writing any code.
- Produce a compact initial approach covering proposed code architecture and target files.
### 2. Adversarial Review ("The Hole Finder")
- **Mandatory Gate**: Before finalizing any plan or code, pivot to an adversarial developer persona whose sole job is to break the proposed solution.
- Actively stress-test the initial spec against the stack constraints. Analyze and call out:
- **Framework Gotchas**: Joomla 5/Fabrik limitations (e.g., placeholder parsing context, missing `jtbl_` references, evaluation order bugs).
- **Database Bottlenecks**: Missing indices, multi-table joins on unindexed columns (like custom county repeat tables), PII leakage risks, or large queries that might trigger truncation limits.
- **Edge Cases**: Empty states, unauthenticated sessions, unexpected user group IDs (e.g., County Admin vs. Club Manager permissions), or deployment drift.
- **Alternatives**: Propose a cleaner, more stable, or lower-maintenance approach if the initial spec is overly complex.
- Present these findings clearly as `[Gotchas & Edge Cases Identified]` and adjust the spec accordingly.
### 3. Linear Planning
- Break the finalized, hardened spec into independent, 2-to-5-minute task increments.
- Maintain this roadmap in a local file at `.claude/plan.md`.
- Track tasks strictly: `[ ] Task description | Modified files | Verification criteria`.
### 4. Execution & TDD
- Process tasks line-by-line. Focus entirely on the current micro-step without feature creep.
- **Strict Testing Rule**: Write or update tests alongside code changes. Run and verify all test states inside the Local Docker Test Environment (`CLAUDE-docker-testenv.md`).
### 5. Code Review & Debug Routine
- Evaluate every file change against the local plan before moving to the next item.
- If a bug or crash occurs during execution, halt and apply this 4-step sequence:
1. Identify exact failing symptoms and collect relevant runtime logs.
2. Formulate a single, verifiable hypothesis.
3. Write a regression test or target a specific script to prove the bug exists.
4. Apply the fix and re-run your Docker validation suite to confirm resolution.
### 6. Finishing & Cleanup
- Verify the entire test suite passes on your working branch.
- Provide a concise summary of final modifications.
- Offer to prepare the files for deployment using your custom deployment tools (`.claude/scripts/deploy-file.sh`).