diff --git a/.ai/manifests/governance.json b/.ai/manifests/governance.json index c175fa4cd..b3be0261e 100644 --- a/.ai/manifests/governance.json +++ b/.ai/manifests/governance.json @@ -1,7 +1,7 @@ { "aiEntrypoints": [ { - "bytes": 23170, + "bytes": 24426, "file": "CLAUDE.md" }, { @@ -54,7 +54,7 @@ "looseDocs": 23, "rules": [ { - "bytes": 19573, + "bytes": 20001, "file": "rules/00-master-rules.md" }, { @@ -245,6 +245,14 @@ "bytes": 23088, "file": "rules/37-payg-credit-integrity.md" }, + { + "bytes": 6068, + "file": "rules/38-adsense-eligibility-and-low-value-content.md" + }, + { + "bytes": 3435, + "file": "rules/39-worktree-branch-completion-pr-and-release-notes.md" + }, { "bytes": 5156, "file": "rules/README.md" @@ -252,7 +260,7 @@ ], "skills": [ { - "bytes": 20103, + "bytes": 20338, "file": "skills/00-index.md" }, { @@ -431,6 +439,10 @@ "bytes": 4194, "file": "skills/find-canonical-owner.md" }, + { + "bytes": 3539, + "file": "skills/finish-worktree-branch-with-pr.md" + }, { "bytes": 4302, "file": "skills/frontend-architecture-review.md" diff --git a/.ai/manifests/hashes.json b/.ai/manifests/hashes.json index 97048fc0d..67626ec79 100644 --- a/.ai/manifests/hashes.json +++ b/.ai/manifests/hashes.json @@ -8,7 +8,7 @@ ".ai/manifests/environment-variables.json": "33602cbe", ".ai/manifests/event-graph.json": "c1cd05bc", ".ai/manifests/frontend-routes.json": "a52b7ece", - ".ai/manifests/governance.json": "f71a269b", + ".ai/manifests/governance.json": "e4492ebd", ".ai/manifests/i18n.json": "3befb756", ".ai/manifests/nginx-routes.json": "53c65be1", ".ai/manifests/packages.json": "cc928a4a", @@ -18,7 +18,7 @@ ".ai/manifests/rabbitmq-events.json": "bcaeb411", ".ai/manifests/repository.json": "047d93d0", ".ai/manifests/services.json": "9c92d2c4", - ".ai/manifests/tests.json": "4b6be224", + ".ai/manifests/tests.json": "4044f562", ".ai/manifests/workspace-dependency-graph.json": "80e5438b", ".ai/manifests/workspaces.json": "b5133e99", ".ai/packs/README.md": "2e64753b", diff --git a/.ai/manifests/tests.json b/.ai/manifests/tests.json index e99b36a04..4c1217b64 100644 --- a/.ai/manifests/tests.json +++ b/.ai/manifests/tests.json @@ -58,7 +58,7 @@ }, "claw-frontend": { "runner": "vitest", - "testFiles": 407 + "testFiles": 410 }, "claw-health-service": { "runner": "jest", @@ -102,5 +102,5 @@ } }, "generated": true, - "total": 1119 + "total": 1122 } diff --git a/CLAUDE.md b/CLAUDE.md index 6449e4625..638dae06c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -164,49 +164,51 @@ Full checklist with rationale: [`rules/05-infra-rules.md`](rules/05-infra-rules. ## Where everything lives -| You need | Go to | -| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| The blockers, in one page | [`rules/00-non-negotiable-rules.md`](rules/00-non-negotiable-rules.md) | -| Rule index | [`rules/00-master-rules.md`](rules/00-master-rules.md) · [`rules/README.md`](rules/README.md) | -| The 26 engineering mindsets | [`rules/27-engineering-mindsets.md`](rules/27-engineering-mindsets.md) | -| Knowledge, docs and skills that ship with the code | [`rules/33-knowledge-compounding-and-context-velocity.md`](rules/33-knowledge-compounding-and-context-velocity.md) · [`skills/grow-the-knowledge-layer.md`](skills/grow-the-knowledge-layer.md) | -| Gate economy and machine resources | [`rules/34-gate-economy-and-machine-resources.md`](rules/34-gate-economy-and-machine-resources.md) · [`skills/run-gates-once-and-land.md`](skills/run-gates-once-and-land.md) | -| Planning gate (Phase 0 / 0g) | [`rules/01-planning-rules.md`](rules/01-planning-rules.md) · [`rules/01-task-intake-and-planning.md`](rules/01-task-intake-and-planning.md) | -| Backend layering: controllers, services, managers, repositories | [`rules/02-backend-rules.md`](rules/02-backend-rules.md), [`rules/07`](rules/07-backend-controllers-and-transport.md)–[`rules/11`](rules/11-dtos-and-validation.md) | -| Frontend pages, hooks, components, queries | [`rules/03-frontend-rules.md`](rules/03-frontend-rules.md), [`rules/04`](rules/04-nextjs-app-router.md)–[`rules/06`](rules/06-frontend-queries-and-cache.md) | -| Declaration ownership (types/enums/constants) | [`rules/12-types-enums-constants-and-declaration-ownership.md`](rules/12-types-enums-constants-and-declaration-ownership.md) | -| Library wrappers and adapters | [`rules/13-external-library-wrappers-and-adapters.md`](rules/13-external-library-wrappers-and-adapters.md) | -| Shared packages and boundaries | [`rules/14-shared-packages.md`](rules/14-shared-packages.md) · [`context/package-boundaries.md`](context/package-boundaries.md) | -| Config and environment | [`rules/15-configuration-and-environment.md`](rules/15-configuration-and-environment.md) · [`docs/06-data/environment-variables.md`](docs/06-data/environment-variables.md) | -| Auth, permissions, IDOR | [`rules/16-authentication-and-authorization.md`](rules/16-authentication-and-authorization.md) · [`context/permission-map.md`](context/permission-map.md) | -| Events and jobs | [`rules/17-rabbitmq-events-and-jobs.md`](rules/17-rabbitmq-events-and-jobs.md) · [`context/event-flow-map.md`](context/event-flow-map.md) | -| Billing integrity and API contracts | [`rules/28-billing-integrity-and-api-contracts.md`](rules/28-billing-integrity-and-api-contracts.md) · [`docs/03-architecture/billing-threat-model.md`](docs/03-architecture/billing-threat-model.md) | -| Errors, logging, redaction | [`rules/18-error-handling-and-reliability.md`](rules/18-error-handling-and-reliability.md) · [`rules/19-logging-observability-and-redaction.md`](rules/19-logging-observability-and-redaction.md) | -| i18n | [`rules/20-i18n-and-user-facing-messages.md`](rules/20-i18n-and-user-facing-messages.md) | -| Security and secrets | [`rules/08-security-rules.md`](rules/08-security-rules.md) · [`rules/21-security-and-secrets.md`](rules/21-security-and-secrets.md) | -| Testing and coverage | [`rules/04-testing-rules.md`](rules/04-testing-rules.md) · [`rules/22-testing-and-coverage.md`](rules/22-testing-and-coverage.md) · [`context/testing-map.md`](context/testing-map.md) | -| Generated files and freshness | [`rules/24-generated-files-and-knowledge-freshness.md`](rules/24-generated-files-and-knowledge-freshness.md) · [`context/generated-file-map.md`](context/generated-file-map.md) | -| Exceptions and waivers | [`rules/25-exceptions-and-waivers.md`](rules/25-exceptions-and-waivers.md) · [`docs/exceptions/README.md`](docs/exceptions/README.md) | -| Refactor discipline | [`rules/09-refactor-rules.md`](rules/09-refactor-rules.md) · [`skills/09-refactor-toolkit.md`](skills/09-refactor-toolkit.md) | -| Exact commands (build, test, prisma, docker, release) | [`context/stack-and-toolchain.md`](context/stack-and-toolchain.md) | -| Which task → which rules/skills/reviewers | [`context/task-router.md`](context/task-router.md) | -| Where a kind of code lives | [`context/codebase-navigation.md`](context/codebase-navigation.md) | -| Who owns which table | [`context/database-ownership-map.md`](context/database-ownership-map.md) | -| Request and data flow across services | [`docs/03-architecture/end-to-end-data-flow.md`](docs/03-architecture/end-to-end-data-flow.md) | -| Routing modes and capability classes | [`docs/03-architecture/routing-engine.md`](docs/03-architecture/routing-engine.md) | -| Model catalog | [`docs/03-architecture/model-catalog-architecture.md`](docs/03-architecture/model-catalog-architecture.md) | -| Runtime progress / SSE | [`docs/03-architecture/runtime-progress.md`](docs/03-architecture/runtime-progress.md) | -| Billing, subscriptions, quotas, threat model | [`docs/03-architecture/billing-threat-model.md`](docs/03-architecture/billing-threat-model.md) | -| The money NUMBERS: plan allowances, margin, credit terms | [`docs/business/`](docs/business/README.md) | -| Nginx reference | [`docs/08-runtime-devops/nginx-reference.md`](docs/08-runtime-devops/nginx-reference.md) | -| Docker, GPU overlays, rebuild procedure | [`docs/08-runtime-devops/docker-guide.md`](docs/08-runtime-devops/docker-guide.md) · [`skills/06-docker-toolkit.md`](skills/06-docker-toolkit.md) | -| Build system (tsgo, tsc-alias, CI) | [`docs/08-runtime-devops/build-system.md`](docs/08-runtime-devops/build-system.md) | -| TLS / mkcert | [`docs/08-runtime-devops/tls-setup.md`](docs/08-runtime-devops/tls-setup.md) | -| Quality-engineering lifecycle and standards | [`docs/16-quality-engineering/`](docs/16-quality-engineering/) | -| Something is broken — runbooks | [`docs/11-runbooks/README.md`](docs/11-runbooks/README.md) | -| Architecture decisions | [`docs/13-adr/adr-index.md`](docs/13-adr/adr-index.md) | -| Per-service deep dive | `docs/04-backend/service-guide-.md` · `apps/claw-/CLAUDE.md` | -| Skill runbooks (scaffold, debug, QA, DB, events) | [`skills/00-index.md`](skills/00-index.md) | +| You need | Go to | +| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| The blockers, in one page | [`rules/00-non-negotiable-rules.md`](rules/00-non-negotiable-rules.md) | +| Rule index | [`rules/00-master-rules.md`](rules/00-master-rules.md) · [`rules/README.md`](rules/README.md) | +| The 26 engineering mindsets | [`rules/27-engineering-mindsets.md`](rules/27-engineering-mindsets.md) | +| Knowledge, docs and skills that ship with the code | [`rules/33-knowledge-compounding-and-context-velocity.md`](rules/33-knowledge-compounding-and-context-velocity.md) · [`skills/grow-the-knowledge-layer.md`](skills/grow-the-knowledge-layer.md) | +| Gate economy and machine resources | [`rules/34-gate-economy-and-machine-resources.md`](rules/34-gate-economy-and-machine-resources.md) · [`skills/run-gates-once-and-land.md`](skills/run-gates-once-and-land.md) | +| Planning gate (Phase 0 / 0g) | [`rules/01-planning-rules.md`](rules/01-planning-rules.md) · [`rules/01-task-intake-and-planning.md`](rules/01-task-intake-and-planning.md) | +| Backend layering: controllers, services, managers, repositories | [`rules/02-backend-rules.md`](rules/02-backend-rules.md), [`rules/07`](rules/07-backend-controllers-and-transport.md)–[`rules/11`](rules/11-dtos-and-validation.md) | +| Frontend pages, hooks, components, queries | [`rules/03-frontend-rules.md`](rules/03-frontend-rules.md), [`rules/04`](rules/04-nextjs-app-router.md)–[`rules/06`](rules/06-frontend-queries-and-cache.md) | +| Declaration ownership (types/enums/constants) | [`rules/12-types-enums-constants-and-declaration-ownership.md`](rules/12-types-enums-constants-and-declaration-ownership.md) | +| Library wrappers and adapters | [`rules/13-external-library-wrappers-and-adapters.md`](rules/13-external-library-wrappers-and-adapters.md) | +| Shared packages and boundaries | [`rules/14-shared-packages.md`](rules/14-shared-packages.md) · [`context/package-boundaries.md`](context/package-boundaries.md) | +| Config and environment | [`rules/15-configuration-and-environment.md`](rules/15-configuration-and-environment.md) · [`docs/06-data/environment-variables.md`](docs/06-data/environment-variables.md) | +| Auth, permissions, IDOR | [`rules/16-authentication-and-authorization.md`](rules/16-authentication-and-authorization.md) · [`context/permission-map.md`](context/permission-map.md) | +| Events and jobs | [`rules/17-rabbitmq-events-and-jobs.md`](rules/17-rabbitmq-events-and-jobs.md) · [`context/event-flow-map.md`](context/event-flow-map.md) | +| Billing integrity and API contracts | [`rules/28-billing-integrity-and-api-contracts.md`](rules/28-billing-integrity-and-api-contracts.md) · [`docs/03-architecture/billing-threat-model.md`](docs/03-architecture/billing-threat-model.md) | +| Errors, logging, redaction | [`rules/18-error-handling-and-reliability.md`](rules/18-error-handling-and-reliability.md) · [`rules/19-logging-observability-and-redaction.md`](rules/19-logging-observability-and-redaction.md) | +| i18n | [`rules/20-i18n-and-user-facing-messages.md`](rules/20-i18n-and-user-facing-messages.md) | +| Security and secrets | [`rules/08-security-rules.md`](rules/08-security-rules.md) · [`rules/21-security-and-secrets.md`](rules/21-security-and-secrets.md) | +| Testing and coverage | [`rules/04-testing-rules.md`](rules/04-testing-rules.md) · [`rules/22-testing-and-coverage.md`](rules/22-testing-and-coverage.md) · [`context/testing-map.md`](context/testing-map.md) | +| Generated files and freshness | [`rules/24-generated-files-and-knowledge-freshness.md`](rules/24-generated-files-and-knowledge-freshness.md) · [`context/generated-file-map.md`](context/generated-file-map.md) | +| Exceptions and waivers | [`rules/25-exceptions-and-waivers.md`](rules/25-exceptions-and-waivers.md) · [`docs/exceptions/README.md`](docs/exceptions/README.md) | +| Refactor discipline | [`rules/09-refactor-rules.md`](rules/09-refactor-rules.md) · [`skills/09-refactor-toolkit.md`](skills/09-refactor-toolkit.md) | +| AdSense eligibility / low-value-content policy | [`rules/38-adsense-eligibility-and-low-value-content.md`](rules/38-adsense-eligibility-and-low-value-content.md) · [`docs/03-architecture/adsense-eligibility.md`](docs/03-architecture/adsense-eligibility.md) | +| Finishing an agent-created worktree/branch (PR + release notes) | [`rules/39-worktree-branch-completion-pr-and-release-notes.md`](rules/39-worktree-branch-completion-pr-and-release-notes.md) · [`skills/finish-worktree-branch-with-pr.md`](skills/finish-worktree-branch-with-pr.md) | +| Exact commands (build, test, prisma, docker, release) | [`context/stack-and-toolchain.md`](context/stack-and-toolchain.md) | +| Which task → which rules/skills/reviewers | [`context/task-router.md`](context/task-router.md) | +| Where a kind of code lives | [`context/codebase-navigation.md`](context/codebase-navigation.md) | +| Who owns which table | [`context/database-ownership-map.md`](context/database-ownership-map.md) | +| Request and data flow across services | [`docs/03-architecture/end-to-end-data-flow.md`](docs/03-architecture/end-to-end-data-flow.md) | +| Routing modes and capability classes | [`docs/03-architecture/routing-engine.md`](docs/03-architecture/routing-engine.md) | +| Model catalog | [`docs/03-architecture/model-catalog-architecture.md`](docs/03-architecture/model-catalog-architecture.md) | +| Runtime progress / SSE | [`docs/03-architecture/runtime-progress.md`](docs/03-architecture/runtime-progress.md) | +| Billing, subscriptions, quotas, threat model | [`docs/03-architecture/billing-threat-model.md`](docs/03-architecture/billing-threat-model.md) | +| The money NUMBERS: plan allowances, margin, credit terms | [`docs/business/`](docs/business/README.md) | +| Nginx reference | [`docs/08-runtime-devops/nginx-reference.md`](docs/08-runtime-devops/nginx-reference.md) | +| Docker, GPU overlays, rebuild procedure | [`docs/08-runtime-devops/docker-guide.md`](docs/08-runtime-devops/docker-guide.md) · [`skills/06-docker-toolkit.md`](skills/06-docker-toolkit.md) | +| Build system (tsgo, tsc-alias, CI) | [`docs/08-runtime-devops/build-system.md`](docs/08-runtime-devops/build-system.md) | +| TLS / mkcert | [`docs/08-runtime-devops/tls-setup.md`](docs/08-runtime-devops/tls-setup.md) | +| Quality-engineering lifecycle and standards | [`docs/16-quality-engineering/`](docs/16-quality-engineering/) | +| Something is broken — runbooks | [`docs/11-runbooks/README.md`](docs/11-runbooks/README.md) | +| Architecture decisions | [`docs/13-adr/adr-index.md`](docs/13-adr/adr-index.md) | +| Per-service deep dive | `docs/04-backend/service-guide-.md` · `apps/claw-/CLAUDE.md` | +| Skill runbooks (scaffold, debug, QA, DB, events) | [`skills/00-index.md`](skills/00-index.md) | ## Per-workspace rules still apply diff --git a/apps/claw-frontend/CLAUDE.md b/apps/claw-frontend/CLAUDE.md index c535c277d..fb04d8c50 100644 --- a/apps/claw-frontend/CLAUDE.md +++ b/apps/claw-frontend/CLAUDE.md @@ -499,3 +499,52 @@ that 403s on every call. - Publishing mints a new immutable version and pins the model as an admin override; the help text says so, because automated sync will then never refresh it. + +## AdSense script vs verification vs ad units (2026-09-01) + +An AdSense "low value content" rejection traced back to `AdSenseHead` being +mounted in the ROOT layout (`app/layout.tsx`), with no pathname check — +`(auth)`, `(portal)`, and `(payment)` all render through the root layout, so +the ad loader script executed on login, chat, billing and settings. A +pathname-aware hook (`useAdSenseScript` / `shouldLoadAdSenseScript`) already +existed but was never wired into anything actually mounted — dead code +guarding nothing. Comments across the codebase claimed "the script only ever +lives in the marketing layout," which was aspirational, not true. + +Fixed by splitting into three independently-gated pieces (see +`docs/03-architecture/adsense-eligibility.md` and +`rules/38-adsense-eligibility-and-low-value-content.md`): + +- **Verification** (``) stays in + `AdSenseHead`, now mounted only in `(marketing)/layout.tsx`. +- **The loader script** moved to `AdSenseScriptLoader`, a client component + that re-derives pathname eligibility via the (previously-dead) + `useAdSenseScript` hook. `reviewMode` no longer bypasses eligibility — a + page the reviewer should never see monetized on must not carry the loader + either, verification or not. +- **Manual ad units** (`AdUnit`) were already correctly gated; unchanged. + +`app/__tests__/adsense-route-boundary.test.ts` asserts the route boundary +structurally (reads each layout's source, fails if AdSense is referenced +outside `(marketing)`) — a regression here fails on exactly the bug that +caused the rejection, not on a behavioral edge case a future refactor might +miss. + +**A raw `