# ACF field policy keys

Audience: AI coding agents first.

## Status

ACTIVE — correcting verified persistence and server-side rejection regressions in implementation commit `f46f83bddd865f054d24015dae463c180175cd64`.

## Outcome

Make every discovered configurable ACF field independently configurable by stable ACF field key, including PHP/local-JSON fields without positive numeric ACF post IDs. Preserve layout-only tab, accordion, and message fields as read-only.

## Source request

Owner request, 2026-08-11: implement stable field-key canonical identity across discovery, validation, lookup, persistence, inheritance, nested fields, runtime application, API, and admin UI. Edit only named files. Commit exact named files with message `Enable policies for local ACF fields`.

## Acceptance

- No-ID discovered field accepts a distinct per-field override.
- Override returns through API, changes effective/runtime policy, leaves sibling/global policy unchanged.
- Nested keys remain isolated.
- Unknown, malformed, structural/layout-only keys reject server-side without weakening authorization/nonce validation.
- Database-backed fields retain safe compatibility and remove obsolete no-ID keyed overrides after synchronization.
- A no-ID field can explicitly select `inherit`, suppressing embedded PHP/local-JSON metadata while retaining global and sibling isolation.
- Controller rejects syntactically valid unknown keys with 404 and tab, accordion, and message keys with 403 without changing ACF metadata or field-policy options.
- Focused PHP tests, relevant admin test/lint/build, PHPCS baseline, PHPStan, and `git diff --check` pass or owner-owned external noise is recorded.
- Commit contains only named task files.

## Preserved WIP / ref

Worktree: `/home/user/Projects/Press.zone/wordpress/wp-content/.worktrees/acf-field-policy-keys`.

Do not alter files outside owner-approved list. Existing worktree state is preserved.

## Constraints

- Stable ACF field keys are canonical identity.
- No schema/migration unless repository evidence proves unavoidable.
- Backend enforces configurability; UI state is never authorization.
- Layout-only `tab`, `accordion`, `message` fields remain read-only.
- Reject malformed/unknown/structural identifiers.

## Execution steps

1. Trace controller request validation, persistence, policy inheritance, nested discovery, runtime integration, and current UI behavior.
2. Define field-key validation and compatibility lookup in policy/integration/controller.
3. Update UI identity and behavior.
4. Add behavior tests for no-ID, nesting, invalid/layout-only, inheritance/runtime, and compatibility.
5. Run acceptance gates, inspect warnings, commit named files.

## Current receipt

Amended implementation commit carries resolver precedence, explicit no-ID `inherit`, stale-option reconciliation, and controller rejection contracts. Observed: focused PHP contracts passed; focused admin Vitest test, admin lint, and admin build passed; PHPCS baseline, PHPStan, and `git diff --check` passed. Pre-commit passed applicable staged PHP checks; notices were owner-owned tooling scope limits (root lacks `package.json` and `composer.lock`, Trivy unavailable, standalone tests outside configured PHP tool paths), with focused admin/PHP gates run explicitly. Final action: amend this receipt and index status into the same commit, then verify final SHA and clean worktree.

Historical receipt follows.

Focused PHPCS baseline initially reported four surplus diagnostics in `ACFIntegration.php`: one newly introduced `fieldUpdateActive` guard assignment plus three `fieldKey` API-parameter occurrences consumed after the baseline budget. Added narrow existing-API PHPCS ignores at only new call/guard sites; restored a shifted pre-existing guard-site diagnostic to baseline accounting. Direct unused-parameter PHPCS inspection reported only pre-existing callback-stub parameters; no new test warning intersected changed lines, so no callback signature changed.

Observed gates:

- `php tests/unit/Translation/ACFFieldPolicyStandaloneTest.php && php tests/unit/Translation/ACFFieldsControllerStandaloneTest.php && php tests/unit/Translation/ACFIntegrationModesStandaloneTest.php` — passed: all three contracts.
- `local-gate --key ipz-acf-policy-ui-test -- npm --prefix admin test -- tests/acf-field-policy.test.js` — passed: 1 file, 1 test.
- `local-gate --key ipz-acf-policy-admin-lint -- npm --prefix admin run lint:js` — passed.
- `local-gate --key ipz-acf-policy-admin-build -- npm --prefix admin run build` — passed: webpack compiled successfully.
- `php tools/phpcs-baseline.php check includes/Compatibility/ACFIntegration.php includes/Compatibility/ACFFieldPolicy.php` — passed.
- `./vendor/bin/phpstan analyse --configuration=phpstan.neon.dist --no-progress -- includes/Compatibility/ACFIntegration.php includes/Compatibility/ACFFieldPolicy.php` — passed: no errors.
- `git diff --cached --check && git diff --check` — passed before final staging; re-run after staging before commit.
- `composer phpcs` reports existing repository-wide style debt beginning in `includes/Glossary/GlossaryManager.php`, outside named task files; focused staged baseline gate is clean.
- Final named-file commit created; pre-commit baselined PHPCS and PHPStan passed.
- Pre-commit reported only owner-owned non-applicable tooling notices: root has no `package.json`/`composer.lock`, Trivy is unavailable, and three standalone test files are outside configured PHP tool scopes; focused admin/PHP tests and admin lint/build were run explicitly.

## Next executable action

None after final amend and clean-worktree verification.
