Skip to content

feat(audit): consolidate FDE audit knowledge into context-mill skills#193

Merged
ordehi merged 3 commits into
mainfrom
feat/fde-audit-knowledge-consolidation
Jun 19, 2026
Merged

feat(audit): consolidate FDE audit knowledge into context-mill skills#193
ordehi merged 3 commits into
mainfrom
feat/fde-audit-knowledge-consolidation

Conversation

@ordehi

@ordehi ordehi commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Consolidates eight production-validated identity / flag failure patterns and the marketing-attribution audit dimension (a documented gap in our coverage) into the context-mill audit suite. Also formalizes the FDE investigation methodology as a cross-cutting reference.

Background, cross-reference, and per-gap recommendations:
vault/posthog/fde/skills/dev/ph/consolidation-plan.md (FDE team only).

What's in this PR

New skill: audit-attributionwizard audit attribution

5 fix-side checks (UTM survival on landing, UTM survival through OAuth, first-touch $set_once discipline, custom click-id capture, attribution on conversion events) + 3 config-side checks (cross_subdomain_cookie, cookieless_mode × attribution, consent integration). Step 1 self-seeds the ledger (see "Heads-up" below). Includes engagement-provenance.md documenting which customer engagement each check traces back to and at what scale.

shared_docs pins to data/utm-segmentation.md, libraries/js/config.md, privacy/data-collection.md, getting-started/identify-users.md. Patterns with no canonical doc are inlined — see "Companion docs PRs" below.

Patches to existing skills

  • audit/references/2-init.md — new init-not-duplicated check (dual-init $set_once race that's caused ~165k blocked merges/day at one multi-SDK customer).
  • audit-identify/references/2-identify-fix.md — new identify-sequential-calls check (auth-provider-UID → internal-UID pattern, ~30k blocked merges/day at the same customer).
  • audit-identify/references/3-identify-lifecycle.md — tightened identify-alias-usage polarity to error on backend-aliases-browser-UUID (~80k blocked merges/day). The existing rule's "legitimate server-side alias" allowance covered exactly the failure pattern.
  • audit-identify/references/5-server-sdk.md (new step) — three checks: server-process-person-profile, server-sdk-flush-on-exit, server-set-without-identify. Old 5-report.md renamed to 6-report.md. anonymous-vs-identified-events.md added to shared_docs.
  • audit-feature-flags/references/2-feature-flags-fix.md — new ff-bootstrap-distinct-id-mismatch and ff-identified-only-pre-auth-targeting checks.

Investigation methodology

  • New posthog-best-practices/references/investigation-standards.md — the FDE provenance + verification + adversarial-review standards as a cross-cutting reference.
  • Every audit's report-step now renders an ### Assumptions and blind spots subsection per area.
  • audit/references/5-report.md notebook-upload placeholder count bumped 3 → 5 per area.

Why now

This work folds knowledge that has been living in customer-specific deliverables (and FDE vault docs) into the audit suite where it's discoverable and runnable by anyone. After this lands, a Convex-style audit is wizard audit && wizard audit identify && wizard audit attribution && wizard audit events && wizard audit feature-flags — five reports with MCP-backed data-side cross-checks the static prompt couldn't do — instead of a 400-line prompt that has to be tuned per customer.

Wizard side: nothing required

Earlier I planned a companion wizard PR for program scaffolding and seed updates. That's not needed — the CLI overhaul (wizard #617 / context-mill #178, merged 2026-06-08) made command registration purely runtime. dispatchFamily resolves audit attribution against cliEntries in skill-menu.json on every wizard invocation, then runs it through the generic agentSkillConfig. As soon as a context-mill release with this PR is cut, wizard audit attribution works on the next wizard invocation. No wizard release required.

Heads-up: latent issue in existing narrow audit leaves (out of scope here)

While verifying that audit-attribution would seed correctly, I found that the existing narrow audit leaves — audit-identify, audit-events, audit-feature-flags, audit-autocapture, audit-session-replay — say in their description.md "The audit ledger is seeded by the wizard" but the wizard's agentSkillConfig (which all of them route through after the CLI overhaul) does not seed. The top-level audit and events-audit both have wizard-side seedAuditLedger() calls in their index.ts; the narrow leaves don't, and their skill markdown doesn't call audit_seed_checks either. So either they're producing empty reports today or the agent is improvising when audit_resolve_checks returns "unknown check id".

The fix is the same pattern this PR uses for audit-attribution: add an audit_seed_checks call to step 1 of each affected skill. Out of scope for this PR; happy to do as a follow-up.

audit-attribution itself is fine — see commit 4d037e1.

Companion PR(s): posthog.com docs

Inlined rule prose in this PR for patterns with no canonical doc. Planned parallel docs work to land the durable explanations:

Pattern Target
UTM survival through OAuth redirects (N10) New pagecontents/docs/data/utm-through-auth-redirects.mdx or section in utm-segmentation.mdx. Zero existing coverage; highest leverage.
Backend SDK flush in serverless / edge / workers (N6) Consolidated page — guidance currently scattered across 5+ snippet files; cross-link from each SDK index.
Dual posthog.init() race (N1) Callout in product-analytics/identity-resolution.mdx
Sequential identify calls (N2) Anti-pattern section in identity-resolution.mdx
Backend posthog.alias() (N3) Expand alias guidance in identity-resolution.mdx
\$set-without-\$identify (N4) Anti-patterns section in product-analytics/person-properties.mdx
bootstrap.distinctID mismatch (N7) Warning callout in feature-flags/bootstrapping.mdx
identified_only + flag targeting (N8) New section in feature-flags/best-practices.mdx
cookieless_mode × attribution (N9) Tradeoffs callout in product-analytics/privacy.mdx

When each docs PR merges, the corresponding inline prose in the skill markdown collapses to a thin rule wrapper that defers to the doc via shared_docs:.

Role-change ack

audit-attribution ships as role: command. CONTRIBUTING.md criterion 5 asks for wizard-maintainer review on command-surface additions. Flagging for ack on this PR; if the team prefers role: skill first, happy to downgrade and promote later.

Test plan

  • npm test — 92/92 passing
  • npm run build — clean; audit-attribution.zip (38.5 KB) emitted; audit-identify.zip carries the new 5-server-sdk.md + bundled anonymous-vs-identified-events.md
  • dist/skills/skill-menu.json lists audit-attribution under cliEntries with role: command, parentCommand: audit, command: attribution
  • All bundled docs verified present in zips (utm-segmentation.md, config.md, data-collection.md, identify-users.md, anonymous-vs-identified-events.md)
  • audit-attribution self-seeds its ledger in step 1 (parity with events-audit)
  • /wizard-ci basic-integration — see PR comment; smoke test for manifest integrity
  • Local dev-server smoke (pnpm dev + wizard local-mcp) — recommended before release-cut to confirm the agent reads the new step files end-to-end against a real codebase

Adds the marketing-attribution audit dimension (a documented gap), folds
eight production-validated identity / flag failure patterns into the
existing audit skills, and formalizes the FDE investigation methodology
as a cross-cutting reference.

New skill: audit-attribution
- wizard audit attribution (role: command, parent: audit)
- 5 fix-side checks: utm-survives-landing, survives-auth-redirect,
  first-touch-set-once, custom-click-ids, on-conversion-events
- 3 config-side checks: cross-subdomain-cookie, cookieless-mode-impact,
  consent-integration
- Pins shared_docs to utm-segmentation, libraries/js/config,
  privacy/data-collection, getting-started/identify-users
- Bundles engagement-provenance.md mapping each check to its source
  customer engagement and observed scale

audit-identify
- New step 5 (server-SDK) with server-process-person-profile,
  server-sdk-flush-on-exit, server-set-without-identify
- New identify-sequential-calls check (Task E in step 2)
- Tightened identify-alias-usage polarity: error on backend-aliases-
  browser-uuid even when alias is on the server side
- Old 5-report.md renamed to 6-report.md; report area expanded to include
  Server SDK; shared_docs picks up anonymous-vs-identified-events.md

audit
- New init-not-duplicated check in step 2 (dual-init set_once race)

audit-feature-flags
- New ff-bootstrap-distinct-id-mismatch check (bootstrap overriding identity)
- New ff-identified-only-pre-auth-targeting check (silent flag default on
  anonymous users when person_profiles is identified_only)

Investigation methodology
- New posthog-best-practices/references/investigation-standards.md
- Every audit report step now renders an Assumptions and blind spots
  subsection per area (placeholder count in the audit notebook-upload
  skeleton bumped 3 to 5 per area)

Companion work (not in this PR):
- Wizard repo: seed updates so new check ids appear in the audit ledger TUI
- posthog.com docs PRs: callouts for net-new patterns

Tests: 92 passing. Build emits audit-attribution.zip and registers
wizard audit attribution under cliEntries.
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci basic-integration
  • /wizard-ci error-tracking-upload-source-maps
  • /wizard-ci misc
  • /wizard-ci revenue

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci error-tracking-upload-source-maps/android
  • /wizard-ci error-tracking-upload-source-maps/cicd-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-nested-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-gitlab-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-ssh-vps-node-raw
  • /wizard-ci error-tracking-upload-source-maps/flutter
  • /wizard-ci error-tracking-upload-source-maps/ios
  • /wizard-ci error-tracking-upload-source-maps/next
  • /wizard-ci error-tracking-upload-source-maps/next-no-posthog
  • /wizard-ci error-tracking-upload-source-maps/node-raw
  • /wizard-ci error-tracking-upload-source-maps/node-rollup
  • /wizard-ci error-tracking-upload-source-maps/node-rollup-typescript-plugin
  • /wizard-ci error-tracking-upload-source-maps/node-webpack
  • /wizard-ci error-tracking-upload-source-maps/nuxt-3-6
  • /wizard-ci error-tracking-upload-source-maps/nuxt-4-3
  • /wizard-ci error-tracking-upload-source-maps/react-native
  • /wizard-ci error-tracking-upload-source-maps/react-vite
  • /wizard-ci error-tracking-upload-source-maps/rust
  • /wizard-ci misc/quack-quack
  • /wizard-ci revenue/stripe

Results will be posted here when complete.

@ordehi

ordehi commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

/wizard-ci basic-integration

Smoke test for manifest integrity. This PR doesn't touch the integration skills, but it adds a new skill (audit-attribution), restructures audit-identify step numbering (5 → 6 for the report step), and bumps the audit notebook-upload placeholder count from 3 → 5 per area. Running basic-integration confirms the manifest is still consumable and the integration setup flow isn't affected.

Note for reviewers: the new audit logic itself (wizard audit attribution, the new audit-identify server-SDK step, the new checks across audit / audit-feature-flags) isn't exercised by any workbench scope yet. Validating those needs a wizard-side PR with example apps that intentionally include the anti-patterns (sequential identify, backend alias, dual init, UTM-lost-through-OAuth, etc.). Out of scope for this PR.

@wizard-ci-bot

wizard-ci-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown

🧙 Wizard CI Results

Trigger ID: 9ec0aed
Workflow: View run

App Confidence PR YARA
basic-integration/android/Jetchat 3/5 #1984 (logs)
basic-integration/angular/angular-saas N/A Failed (logs)
basic-integration/astro/astro-hybrid-marketing 4/5 #1982 (logs)
basic-integration/astro/astro-ssr-docs 4/5 #1992 (logs)
basic-integration/astro/astro-static-marketing 4/5 #1987 (logs)
basic-integration/astro/astro-view-transitions-marketing 4/5 #1988 (logs)
basic-integration/django/django3-saas 4/5 #1986 (logs)
basic-integration/fastapi/fastapi3-ai-saas 4/5 #1989 (logs)
basic-integration/flask/flask3-social-media 4/5 #1983 (logs)
basic-integration/javascript-node/express-todo 4/5 #1990 (logs)
basic-integration/javascript-node/fastify-blog 4/5 #1985 (logs)
basic-integration/javascript-node/hono-links 4/5 #1991 (logs)
basic-integration/javascript-node/koa-notes 4/5 #1994 (logs)
basic-integration/javascript-node/native-http-contacts N/A Failed (logs)
basic-integration/javascript-web/saas-dashboard 5/5 #1997 (logs)
basic-integration/laravel/laravel12-saas 4/5 #1993 (logs)
basic-integration/next-js/15-app-router-saas 4/5 #1995 (logs)
basic-integration/next-js/15-app-router-todo 4/5 #1996 (logs)
basic-integration/next-js/15-pages-router-saas 4/5 #1998 (logs)
basic-integration/next-js/15-pages-router-todo N/A Failed (logs)
basic-integration/nuxt/movies-nuxt-3-6 N/A Failed (logs)
basic-integration/nuxt/movies-nuxt-4 N/A Failed (logs)
basic-integration/python/meeting-summarizer 4/5 #2000 (logs)
basic-integration/rails/fizzy 4/5 #1999 (logs)
basic-integration/react-native/expo-react-native-hacker-news 1/5 #2001 (logs)
basic-integration/react-native/react-native-saas 4/5 #2002 (logs)
basic-integration/react-router/react-router-v7-project N/A Failed (logs)
basic-integration/react-router/rrv7-starter 4/5 #2003 (logs)
basic-integration/react-router/saas-template 4/5 #2006 (logs)
basic-integration/react-router/shopper 4/5 #2005 (logs)
basic-integration/sveltekit/CMSaasStarter N/A #2009 (logs)
basic-integration/swift/hackers-ios 5/5 #2007 (logs)
basic-integration/tanstack-router/tanstack-router-code-based-saas N/A Failed (logs)
basic-integration/tanstack-router/tanstack-router-file-based-saas 4/5 #2008 (logs)
basic-integration/tanstack-start/tanstack-start-saas 4/5 #2010 (logs)
basic-integration/vue/movies 4/5 #2011 (logs)

Configuration

Setting Value
Wizard ref main
Context Mill ref feat/fde-audit-knowledge-consolidation
PostHog ref master

Search for trigger ID 9ec0aed in wizard-workbench PRs.

@ordehi ordehi requested a review from a team June 19, 2026 18:36
The runtime resolution path (wizard audit attribution -> dispatchFamily ->
agentSkillConfig) does not pre-seed the audit ledger; audit_resolve_checks
would error 'unknown check id' on every check otherwise. Follow the
events-audit pattern: skill calls audit_seed_checks directly in step 1
with the full 8-check + write-report payload.

Note: the existing narrow audit leaves (audit-identify, audit-events,
audit-feature-flags, audit-autocapture, audit-session-replay) appear to
have the same latent issue — their description.md says 'seeded by the
wizard' but the wizard's agentSkillConfig does not seed. Out of scope
for this PR; flagged for a follow-up.

@gewenyu99 gewenyu99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, there are some places where ``` are malformed because the prompt: points to ``` with nested ```.

Otherwise good


Emit one `mcp__wizard-tools__audit_resolve_checks` call with a single update for id `attribution-cookieless-mode-impact`, including `file` (path:line of the cookieless_mode setting, or the init if unset) and `details` as compact JSON:

```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this breaks the ``` wrap here. You may need to do the hack where you use ``````

@gewenyu99

Copy link
Copy Markdown
Collaborator

Next time you can do /wizard-ci sample or just /wizard-ci basic-integration/next-js. It gets quite expensive to do the full set of CI now :P

Subagent prompts in audit skills wrap their text in a triple-backtick fence
but contain a triple-backtick JSON example inside. Per CommonMark, the inner
fence closes the outer block, breaking rendering. Bump the outer fence to
four backticks so the inner three-backtick JSON blocks nest cleanly.

Affects 24 prompt blocks across 7 reference files in audit-attribution,
audit-feature-flags, and audit-identify.
@ordehi ordehi merged commit ad72e79 into main Jun 19, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants