# Claude operating notes for this project

This is a WordPress plugin (current display: **Ppok AI Toolkit**, working slug: `ppok-ai-toolkit`) that registers **WordPress Abilities** so AI clients can call them through [`WordPress/mcp-adapter`](https://github.com/WordPress/mcp-adapter), optionally fronted by [`Automattic/mcp-wordpress-remote`](https://github.com/Automattic/mcp-wordpress-remote).

## Start every session by reading

[`.context/project.json`](.context/project.json) — the single source of project context. Architecture decision, identifier naming policy, licensing split, SFTP constraints, rename history, v1 ability roster, and `todo_next` all live there. Read it before proposing changes.

## Operating principles (short form — full text in project.json)

- **Always idiomatic.** Prefer WP core APIs (Abilities API, Settings API, REST API), WPPB layout, and WPCS conventions over bespoke abstractions. Only diverge when the upstream pattern is missing a feature, and leave a one-line comment explaining why.
- **Single source of context.** Project context lives in `.context/project.json`, tracked by git. Do **not** write to `~/.claude/projects/.../memory/` — it would just drift.
- **Asymmetric gating.** Reads are universal (limitless factory) — only the per-call capability check gates them, no admin toggle, no audit log. Writes are layered-gated (L1–L5: capability, schema, block allowlist, plugin-options scope, audit log) and default OFF until the admin opts each one in. The boundary is `meta.ppok.write` on the ability descriptor. See [.context/project.json](.context/project.json) → `architecture.exposure_policy`.

## Hard constraints

- **Don't rename the plugin folder or any slug-shaped identifier** (`ppok-ai-toolkit`, `PPOK_AI_TOOLKIT_*`, text domain, REST namespace, composer name, option keys, contributor handle) until the user confirms the SFTP sync is paused. The folder name **is** the live plugin slug; renaming orphans activation state and option data. Display strings and PHP namespaces **are** safe to rename.
- **Licensing is split per-file.** Anything that touches WordPress symbols is GPL-2.0-or-later. Files under `includes/lib/` are proprietary and must contain zero WordPress dependencies. Every PHP/JS/CSS file carries an `@license` header. See [`LICENSE.md`](LICENSE.md).
- **Don't commit secrets or deploy configs.** `SFTP.json` (if it exists locally), `vendor/`, and `.context/` exclusions configured in your SFTP tool — keep them that way.
- **Don't push `vendor/` via SFTP.** The remote has a static bootstrap (12 files, ~76KB) pushed once; the local `vendor/` is fat with dev deps for testing. Editing existing PHP/CSS/JS files just uploads-on-save — no composer dance. **Only when you add or remove a class file** must the remote classmap be regenerated: `composer dump-autoload --no-dev` → temporarily un-ignore `vendor/` in `../.vscode/sftp.json` → right-click `vendor/composer/autoload_classmap.php` → SFTP: Upload File → re-ignore → `composer dump-autoload` to restore. Full procedure + rationale in `.context/project.json` → `sftp.vendor_policy_2026_05_23`.

## When you learn something durable

Update the right section of `.context/project.json`:

| Kind of fact | Section |
| --- | --- |
| Architectural decision | `architecture` |
| New convention / rule | `principles` |
| Identifier change | `plugin` + `naming_split` |
| New dependency / soft-dep | `architecture.soft_dependencies` |
| Next work item | `todo_next` |
| Brand / display rename | `naming_split.rename_history` + relevant fields |

Don't create sibling `.md` docs unless the user asks. Keep context consolidated.

## When in doubt

Ask. The user has been decisive on naming, scope, and licensing — surface options and let them pick rather than guessing.
