---
name: debug-management-ui
description: Diagnoses management interface failures by reading ui-config.php to inspect LINGUISE_OOBE_DONE, LINGUISE_LOGIN_SECRET, and DB constant state, then cross-references the findings against the four silent failure modes documented in AGENTS.md (blank page, login failure, 403 on POST, stuck OOBE). Read-only — never modifies any file.
---

# Debug Management UI

Diagnoses failures in the Script-PHP management interface (triggered by `?linguise_language=zz-zz`) by reading `ui-config.php` to inspect the OOBE and authentication state constants, then cross-referencing the findings against the four documented failure modes in AGENTS.md and `memory-bank/managementFlow.md`.

## Procedure

### Step 1 — Read ui-config.php and inspect all constants (read-only)

Read `ui-config.php` from the project root. This file is generated by `OobeManager` and contains `define()` statements for the management system state.

Extract and report on each constant:

1. **LINGUISE_OOBE_DONE**:
   - If the constant is not defined or the file does not exist: report `ui-config.php: NOT FOUND or LINGUISE_OOBE_DONE not defined`
   - If `true`: report `OOBE Status: Complete (LINGUISE_OOBE_DONE = true)`
   - If `false`: report `OOBE Status: Incomplete (LINGUISE_OOBE_DONE = false) — setup wizard is active`

2. **LINGUISE_LOGIN_SECRET**:
   - If defined and the value is a non-empty string (expect a 64-character hex string from `random_bytes(32)`): report `Login Secret: Present (non-empty)` — **never display the actual secret value**
   - If defined but empty (`''`): report `Login Secret: EMPTY — login will always fail`
   - If not defined: report `Login Secret: NOT DEFINED — management authentication is broken`

3. **LINGUISE_OOBE_DB_TYPE**:
   - If `sqlite`: report `Database Type: SQLite`
   - If `mysql`: report `Database Type: MySQL`
   - If not defined: report `Database Type: Not configured`

4. **MySQL-specific constants** (only when `LINGUISE_OOBE_DB_TYPE = mysql`):
   - **LINGUISE_OOBE_DB_HOST**: Report as `Present` (non-empty) or `EMPTY / Not defined`
   - **LINGUISE_OOBE_DB_NAME**: Report as `Present` (non-empty) or `EMPTY / Not defined`
   - **LINGUISE_OOBE_DB_USER**: Report as `Present` (non-empty) or `EMPTY / Not defined`
   - **LINGUISE_OOBE_DB_PASSWORD**: Report only whether it is non-empty (do not display the value)
   - **LINGUISE_OOBE_DB_PREFIX**: Report the value (prefixes are not secrets)

### Step 2 — Read memory-bank/managementFlow.md for flow reference (read-only)

Read `memory-bank/managementFlow.md` to understand the expected lifecycle:

- The `ui-config.php` lifecycle diagram (how constants are set during OOBE)
- The OOBE wizard flow (Mode A: without token, Mode B: with token)
- The post-OOBE admin panel flow (login, session establishment, CSRF)

Reference these flows when diagnosing which stage has failed.

### Step 3 — Read AGENTS.md for failure mode reference (read-only)

Read the "Debugging the management interface" section from `AGENTS.md` (lines 181-185). The four documented silent failure modes are:

1. **Blank page**: `ui-config.php` absent or malformed, or `LINGUISE_OOBE_DONE` not `true`
2. **Login failure**: `LINGUISE_LOGIN_SECRET` incorrect or mismatched with session
3. **403 on POST**: CSRF token mismatch between client cookies and server session
4. **Stuck OOBE**: DB credentials in `ui-config.php` are invalid (MySQL: host/name/user are empty or unreachable; SQLite: data directory not writable)

### Step 4 — Map constant state to failure mode

Cross-reference the collected constant state from Step 1 against the four failure modes:

| Failure Mode | Constant State Signature | Diagnostic |
|---|---|---|
| **Blank page** | `ui-config.php` does NOT exist, OR `LINGUISE_OOBE_DONE` is not defined / not `true` | The management dispatch in `linguise.php` cannot proceed past the OOBE check. The page will render nothing or a PHP error. |
| **Login failure** | `LINGUISE_OOBE_DONE = true` AND `LINGUISE_LOGIN_SECRET` is EMPTY or NOT DEFINED | Without a valid login secret, session authentication in `OobeManager::run()` will always fail. |
| **403 on POST** | `LINGUISE_OOBE_DONE = true` AND `LINGUISE_LOGIN_SECRET` is present AND all DB constants are valid | This is a runtime CSRF issue (not a constant-state issue). The CSRF token in the client's cookies does not match the server's session. Recommend clearing browser cookies and reloading. |
| **Stuck OOBE** | `LINGUISE_OOBE_DONE = false` AND MySQL constants (`DB_HOST`, `DB_NAME`, `DB_USER`) are empty, OR the data directory for SQLite is not writable | The OOBE wizard's `storeDatabaseConnection()` failed because the DB credentials are invalid or the data directory is not writable. The wizard remains active until the connection test succeeds. |

### Step 5 — Output the diagnostic report

Format the output as a structured report:

```
## Management UI Debug Report

### ui-config.php Status
- File: {EXISTS / NOT FOUND}
- OOBE Status: {Complete / Incomplete}
- Login Secret: {Present / EMPTY / NOT DEFINED}
- Database Type: {SQLite / MySQL / Not configured}

### Database Configuration (MySQL only)
- DB Host: {Present / EMPTY}
- DB Name: {Present / EMPTY}
- DB User: {Present / EMPTY}
- DB Password: {Present / EMPTY}
- DB Prefix: {value}

### Failure Mode Analysis
**Most likely failure mode: {FAILURE MODE NAME}**

Evidence:
- {Finding 1 from constant state}
- {Finding 2 from constant state}

### Resolution Steps (from AGENTS.md)
{Referenced step(s) from the "Debugging the management interface" section}

### Additional Context (from managementFlow.md)
{Brief summary of the expected lifecycle stage where the failure occurs}
```

Reference the specific step(s) from the AGENTS.md "Debugging the management interface" section:

- If **Blank page** → cite Step 1: "If the page shows nothing: check `ui-config.php` exists and `LINGUISE_OOBE_DONE = true`"
- If **Login failure** → cite Step 2: "If login fails: verify `LINGUISE_LOGIN_SECRET` in `ui-config.php` matches the session"
- If **403 on POST** → cite Step 3: "If 403 on POST: CSRF token mismatch — clear browser cookies and reload"
- If **Stuck OOBE** → cite Step 4: "If OOBE is stuck: delete `ui-config.php` to restart the wizard (⚠ loses DB config)"

### Step 6 — Validation

After running, verify:
1. **No file was modified** — this skill is strictly read-only
2. `ui-config.php` was read and all relevant constants were extracted
3. No secret values (password, login secret) were displayed in the output
4. `memory-bank/managementFlow.md` was read for flow reference
5. `AGENTS.md` was read for the four failure mode descriptions
6. The output maps the constant state to exactly one failure mode (or lists multiple with likelihood ordering)

### Edge Cases

- **`ui-config.php` not found**: Report `ui-config.php: NOT FOUND. This is consistent with a blank page failure mode or a fresh installation. Run the OOBE wizard by visiting ?linguise_language=zz-zz.`
- **`ui-config.php` is malformed or has PHP syntax errors**: If the file cannot be parsed, report `ERROR: ui-config.php exists but could not be parsed. The file may be corrupted. Delete it to restart the OOBE wizard.`
- **Multiple constants missing**: If both `LINGUISE_LOGIN_SECRET` is empty AND DB constants are empty, list both login failure and stuck OOBE as possible failure modes, ordered by likelihood.
- **`memory-bank/managementFlow.md` not found**: Still perform the constant-state diagnostic, but note: `WARNING: memory-bank/managementFlow.md not found — OOBE lifecycle cross-reference unavailable.`
- **`AGENTS.md` not found**: Still perform the diagnostic, but note: `WARNING: AGENTS.md not found — failure mode descriptions and resolution steps unavailable.`
- **All constants look correct**: If `LINGUISE_OOBE_DONE = true`, login secret is present, and DB constants are valid, but the user still reports issues, note: `All constant-state checks passed. The issue is likely runtime (CSRF token mismatch, session expiry, or a browser caching issue). Refer to AGENTS.md Step 3: clear browser cookies and reload.`