> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.qonversion.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 2026 10 23 doc1 validation

# DOC1 — Apple Ads documentation sync

Branch: `sam/dev-2080-docs-sync`. The delivery commit SHA is supplied in the executor's final report; this file is part of that commit.

Source snapshots verified from fetched origin/main:

* dash-mono `05417021b31c906874451a0ac39559b7e98dd810`
* api-gateway `11b625e7cddb388cd6f6eb92b225bd3e9da6b8c9`
* Documentation base `6c25bd6`.

## Files and purpose

* `api-reference/rest-api-v4.yaml` — Unified refusal schemas with required type/code/message, JSON 413 with either idempotency path, and public disconnect compatibility.
* `reference/v4/apple-ads.mdx` — Aligned error codes/envelope and 413; explained public disconnect state and OAuth/legacy recovery.
* `docs/apple-ads-attribution.mdx` — Updated three display labels while keeping stored values intact.
* `docs/apple-search-ads.mdx` — Separated explicit Disconnected from Apple-side Expired or revoked; corrected Connect with Apple action.
* `docs/apple-ads-troubleshooting.mdx` — Aligned disconnect, Enable/Pause outcome copy, and stale-permission recovery.
* `docs/apple-ads-budget-usage.mdx` — Gave Far below the budget its dedicated bids/targeting/delivery advice.
* `docs/apple-ads-manage-campaigns.mdx` — Documented campaign switch vs child-row menu, keyword-only Set bid, Enable/Pause labels, and OAuth/legacy recovery; kept old heading anchors.
* `docs/apple-ads-data-freshness.mdx` — Clarified import preview dates cover added rows and spend is grouped by currency.
* `docs/mcp-apple-ads.mdx` — Corrected OAuth vs legacy stale-permission recovery.
* `skill.md` — Mirrored the corrected permission recovery instructions.
* `.docs-quality/claims/apple-ads.json` — Updated 23 claims (3 new), with 45 evidence windows baselined for changed/new statements.
* `.docs-quality/evals/apple-ads.json` — Updated four existing questions and added eight questions for the changed behavior.
* `.docs-quality/evals/apple-ads.holdout.json` — Independent coordinator clarified one existing expired/revoked expectation; other entries untouched.
* `.docs-quality/tests/apple-ads-sync.test.mjs` — Added eight public contract regression tests with no new dependencies.
* `.github/workflows/docs-quality.yml` — Runs the new regression suite in the claims CI job.
* `.claude/state/TASK_JOURNAL.md` — Recorded scope, pinned sources, verification, and blocked eval prerequisite.
* `.docs-quality/results/apple-ads/history.jsonl` — Recorded failed dev preflight and full holdout execution.
* `.docs-quality/results/apple-ads/2026-10-22T23-35-04-local-dev-doc1-backend-preflight.json` — Preserved the dev backend authentication error.
* `.docs-quality/results/apple-ads/2026-10-22T23-40-47-local-holdout-doc1-holdout.json` — Preserved all 40 holdout authentication errors.
* `.docs-quality/results/apple-ads/2026-10-23-doc1-validation.md` — This reviewable validation report.

## Claims touched

* `apple-ads.attribution.media-source-labels-asa-report`
* `apple-ads.attribution.media-source-labels-generic`
* `apple-ads.connection.connect-button-labels`
* `apple-ads.connection.disconnect-result-state`
* `apple-ads.connection.status-reconnect-required-expired`
* `apple-ads.freshness.budget-usage-far-below-version`
* `apple-ads.freshness.budget-usage-what-to-check`
* `apple-ads.freshness.import-review-first`
* `apple-ads.manage.after-change-confirmed-note`
* `apple-ads.manage.after-change-failed`
* `apple-ads.manage.after-change-pending`
* `apple-ads.manage.apple-permission-check-stale`
* `apple-ads.manage.bid-keywords-only`
* `apple-ads.manage.pause-resume-all-levels`
* `apple-ads.manage.rate-limit-daily-increases`
* `apple-ads.manage.ui-not-delivering-word`
* `apple-ads.manage.ui-status-switch`
* `apple-ads.mcp-api.write-permission-data-stale`
* `apple-ads.mcp-api.write-validation-422`
* `apple-ads.manage.through-mcp-every-live-bid-or`
* `apple-ads.connection.public-disconnect-compatibility`
* `apple-ads.mcp-api.write-error-envelope`
* `apple-ads.mcp-api.write-body-too-large-json`

## Fails before / passes after

The exact new suite was copied into a temporary extraction of the eight relevant `origin/main` source files using `git archive`; the shared checkout and implementation worktree were not reverted. Command on each tree:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
node --test .docs-quality/tests/*.test.mjs
```

Before (origin/main):

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# tests 8
# pass 0
# fail 8
```

After:

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# tests 8
# pass 8
# fail 0
```

The tests cover the V4 envelope required fields, JSON 413 on both idempotency paths, stored-source/display-label mapping, explicit-disconnect/public compatibility, far-below advice, menu controls, OAuth/legacy stale-permission recovery, and added-row import dates/currencies.

## Full offline suite and lint

All commands exit 0:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
node --test .docs-quality/tests/*.test.mjs
node .docs-quality/bin/self-test.mjs
node .docs-quality/bin/check-claims.mjs docs --base origin/main
node scripts/ci/check-root-files.mjs --self-test
node scripts/ci/check-root-files.mjs
node scripts/ci/validate-docs.mjs --self-test
node scripts/ci/validate-docs.mjs
node scripts/ci/lint-content.mjs
node scripts/ci/check-images.mjs --base origin/main
npx --yes mint@4.2.935 validate --telemetry false
npx --yes @redocly/cli@latest lint api-reference/rest-api-v4.yaml
npx --yes --package=@apidevtools/swagger-cli swagger-cli validate api-reference/rest-api-v4.yaml
git diff --check
```

Relevant result tails:

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
new suite: 8/8 passed
gate self-test: 27/27 passed
claims: 540 claims; coverage 468/474 (99%); 0 errors, 0 warnings
root self-test: 13/13 passed
root guard: errors: 0, warnings: 0
link validator self-test: 6/6 passed
errors: 0, warnings: 14
content lint: errors: 0, warnings: 0
image check: errors: 0, warnings: 0
Mintlify: success build validation passed
Redocly: API description is valid; 54 warnings (same 54 on origin/main)
swagger-cli: api-reference/rest-api-v4.yaml is valid
YAML/malformed-response check: 899 response objects; no malformed response objects
baseline: baselined 45 evidence windows in apple-ads
```

The link validator's warnings are its unchanged grandfathered baseline. Redocly was also run on the original spec to establish no warning growth. Python's openapi-spec-validator could not be installed using a venv because this VM lacks ensurepip/pip; the spec was instead checked by Redocly, swagger-cli OpenAPI validation, and PyYAML with the CI malformed-response-object check. No host packages were installed.

## Eval execution and limitation

The requested holdout command was run:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
node .docs-quality/bin/eval.mjs --feature apple-ads --corpus local --bank holdout --concurrency 8 --label doc1-holdout
```

Result: **40 questions, 40 infrastructure errors; zero graded answers**. Backend:

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
claude cli: Failed to authenticate: OAuth session expired and could not be refreshed
```

The one-question dev preflight had the same authentication error. No `ANTHROPIC_API_KEY` is present on the VM. The runner records zero-valued metrics when all calls error; those are not meaningful quality scores and the VM run did not pass. The dev repeat-3 run and model-based ledger/page audits remain unverified until the external VM Claude CLI session is renewed or a configured Anthropic API key is supplied. No reauthentication was attempted.

### Later Mac holdout (separate run)

The later `doc1-holdout-mac` run used the same holdout bank: **40 graded answers, 0 errors, pass\_rate 0.975 (39/40), fact\_recall 1**. The single failed question was `h.mcp-api.bid-currency-422`. Its recorded `docs_sha` is `7c07e96`; it was **not run against the final reviewed head**. This is distinct from the VM's `doc1-holdout` authentication failures and does not replace that infrastructure record.

Evidence: `2026-10-22T23-51-52-local-holdout-doc1-holdout-mac.json` and its entry in `history.jsonl`. No eval was rerun on the VM for DOC1b because its credential remains expired. A fresh run against the final reviewed head remains outstanding.

## Risks, release and compatibility

* Documentation-only change: no flag changes, migrations, runtime writes, deployments, PRs, or production queries.
* Existing pages, slugs, stored media-source values and public connection enums stay compatible; old renamed-heading anchors are explicitly retained.
* v6 is recorded in internal evidence; published budget advice retains the lifecycle/budget-history qualifications already on the page.
* Next-release reload-persistent confirmed changes (30 minutes) and corresponding bulk behavior were deliberately excluded. The docs-feature workflow permits pre-release assertions only if they stay true without the new code.
* The brief's broad specific-code preservation claim is not true for the gateway's 5xx path: it still replaces upstream 5xx with `storage_error` (or its own `network_error` on timeout). The docs preserve this behavior and promise explicit-code retention only for 4xx. The backend normalizer preserves `kill_switch`, but it is not end-to-end over REST.
* No live API or production verification was performed, per task scope. Text-only changes use CI/build checks rather than dashboard screenshots.

## Reviewer questions

1. Is the gateway's generic 5xx behavior intentional, or should preserving `kill_switch` end-to-end be a separate runtime fix?
2. Who can renew the VM eval credential or run evaluation on the Mac so the holdout and dev repeat-3 evaluation can be verified against the final reviewed head before merge?

## DOC1b — review follow-up verification (2026-10-23)

Pulled `sam/dev-2080-docs-sync` to `f055d5e` in its existing worktree. Rechecked fetched `origin/main` at dash-mono `05417021b31c906874451a0ac39559b7e98dd810` and api-gateway `7dfd82a2e6f4cbf02f39139d5216c06461cfa07f` without modifying either checkout.

### Source findings and focused changes

* Campaign status actions: `AppleAdsWriteRequest::normalizeStatus` uses `ENABLED`/`ACTIVE` and `PAUSED`; `WriteAwareCells.tsx` labels the action Enable/Pause. Overview/report prose, matching claims and eval facts now use enable. Existing claim IDs, old heading anchors, the `RESUME` API alias, reconnect wording and verbatim UI copy remain compatible.
* `error.class`: `AppleAdsWriteError::project` normalizes only `type`, `code` and `message`, retaining class metadata. `AppleAdsGatewayWriteErrorTest::testWriteOutcomesAddV4FieldsAndPreserveExistingData` explicitly checks arrays, objects, numbers, booleans and null are preserved. Gateway `appleAdsWriteV4Error` likewise retains `json.RawMessage` class values unchanged, using a string only for fallback-code selection. A `type: string` constraint would misrepresent the public body. The optional class schema remains unconstrained and now documents its normal string form and handling of non-string values.
* 422: `AppleAdsWriteService::validationError` provides `error.fields`; its later refusal path forwards the supplied error body without adding fields. The REST and MCP rows and matching claim now express the same conditional fields contract as the OpenAPI response description.
* Mac evaluation: the separate historical run and its reviewed-head limitation are recorded above and in the journal; saved evaluation artifacts were not edited. No eval was run for DOC1b.

### Regression evidence

Added four cases to `.docs-quality/tests/apple-ads-sync.test.mjs`: consistent enable terminology across pages/ledger/banks; separate Mac provenance and metrics in report/journal; optional unconstrained class metadata; and conditional 422 fields in REST/MCP documentation.

The new cases were run against the pulled `f055d5e` content before making the fixes, then against the fixed files:

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
node --test .docs-quality/tests/*.test.mjs
before: tests 12; pass 8; fail 4 (all four new cases)
after:  tests 12; pass 12; fail 0
```

### Full follow-up checks

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
node --test .docs-quality/tests/*.test.mjs
  tests 12; pass 12; fail 0
node .docs-quality/bin/self-test.mjs
  27/27 passed
node .docs-quality/bin/check-claims.mjs docs --base origin/main
  540 claims; coverage 468/474 (99%); 0 errors, 0 warnings
node scripts/ci/lint-content.mjs
  errors: 0, warnings: 0
node scripts/ci/validate-docs.mjs
  errors: 0, warnings: 14 (existing grandfathered baseline)
node scripts/ci/check-root-files.mjs
  errors: 0, warnings: 0
npx --yes mint@4.2.935 validate --telemetry false
  success build validation passed
npx --yes @redocly/cli@latest lint api-reference/rest-api-v4.yaml
  Your API description is valid. You have 54 warnings (existing baseline).
npx --yes --package=@apidevtools/swagger-cli swagger-cli validate api-reference/rest-api-v4.yaml
  api-reference/rest-api-v4.yaml is valid
PyYAML / CI malformed-response check
  899 response objects; no malformed response objects; error.class optional and unconstrained
git diff --check
  clean
```

CodeRabbit CLI review was attempted once with `coderabbit review --light --agent --uncommitted`; it stopped with `environment_unsupported` because agent login requires a localhost browser callback. No reauthentication was attempted; the focused diff was reviewed locally. Python `openapi-spec-validator` remains unavailable; swagger-cli and Redocly supplied OpenAPI validation.

Documentation only: no flags, migrations or deploy order; revert the docs commit to roll back. No production queries, runtime writes, PR changes or other-repository edits. Evaluation on the final reviewed head remains outstanding, and the Mac run's single failed question remains historical evidence rather than a claimed pass. The class constraint suggestion is intentionally declined based on the pass-through behavior above. Reviewer follow-up: arrange final-head evaluation when credentials are available; no further implementation question for these four threads.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.