Add essay: PostHog Code and the production signal#11
Conversation
Analyzes PostHog Code's enricher through the proactive agent lens. The enricher bridges code and production data (feature flags, event volumes, experiments) via tree-sitter static analysis and live API queries. Entirely reactive today but the enricher pattern is the most interesting primitive for proactive dev agents we've seen. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR adds PostHog Code documentation with new visualization components. A card illustration component ( ChangesPostHog Code documentation
🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Taller viewBox (360) gives code lines breathing room. Status dots (green/yellow/red) next to each annotation. Enricher pill with curved arrows from source boxes. Separator lines between code entries. Clearer visual flow from inputs → enricher → output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| <rect x="20" y="38" width="280" height="100" rx="8" fill={C.paper} stroke={C.ink} strokeWidth="1.5" /> | ||
| <text x="32" y="56" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('checkout')</text> | ||
| <text x="32" y="72" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 23% rollout · stale · exp +4%</text> | ||
| <text x="32" y="92" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>posthog.capture('purchase')</text> | ||
| <text x="32" y="108" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 1,240 events/30d · verified</text> | ||
| <text x="32" y="128" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('old-banner')</text> | ||
| <text x="32" y="144" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>// → 0% rollout · no evals 60d</text> |
There was a problem hiding this comment.
🟡 PHEnricherFigure: last annotation text overflows the containing rect
The "source file box" rect in PHEnricherFigure spans from y=38 to y=138 (y="38" + height="100"), but the last text element at components/mdx/figures.tsx:2361 has y="144", placing its baseline 6px below the box's bottom edge. Since the rect has fill={C.paper}, this last annotation ("// → 0% rollout · no evals 60d") will render visually outside the white box, breaking the intended "annotated code file" appearance.
| <rect x="20" y="38" width="280" height="100" rx="8" fill={C.paper} stroke={C.ink} strokeWidth="1.5" /> | |
| <text x="32" y="56" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('checkout')</text> | |
| <text x="32" y="72" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 23% rollout · stale · exp +4%</text> | |
| <text x="32" y="92" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>posthog.capture('purchase')</text> | |
| <text x="32" y="108" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 1,240 events/30d · verified</text> | |
| <text x="32" y="128" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('old-banner')</text> | |
| <text x="32" y="144" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>// → 0% rollout · no evals 60d</text> | |
| <rect x="20" y="38" width="280" height="114" rx="8" fill={C.paper} stroke={C.ink} strokeWidth="1.5" /> | |
| <text x="32" y="56" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('checkout')</text> | |
| <text x="32" y="72" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 23% rollout · stale · exp +4%</text> | |
| <text x="32" y="92" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>posthog.capture('purchase')</text> | |
| <text x="32" y="108" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>// → 1,240 events/30d · verified</text> | |
| <text x="32" y="128" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>isFeatureEnabled('old-banner')</text> | |
| <text x="32" y="144" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>// → 0% rollout · no evals 60d</text> |
Was this helpful? React with 👍 or 👎 to provide feedback.
|
|
||
| All of this information exists inside the enricher's analysis pipeline. The gap is that the pipeline only runs when a human starts a session and the agent happens to read the relevant file. The enricher is a listener that only operates during active coding sessions. | ||
|
|
||
| Making it always-on would close the gap. A background process that periodically scans for stale flags across connected repos and opens cleanup PRs. A watcher that correlates error rate spikes with recent merges and alerts the PR author in Slack. A weekly digest of dead instrumentation that nobody is tracking anymore. The data is already being fetched and analyzed within the enricher's pipeline. It just needs a trigger mechanism that doesn't require a human typing a prompt to start the process. |
There was a problem hiding this comment.
🔴 Two tricolon lists in essay violates CLAUDE.md "more than once per essay" rule
CLAUDE.md states: "Avoid tricolon lists ('Not X. Not Y. Not Z.') more than once per essay. Parallel structures where three items start with the same word are an LLM tell. One instance can be rhetorical; two is a pattern." This essay contains two tricolons: line 43 ("There are no webhooks…No cron jobs…No file watchers") and line 55 ("A background process…A watcher…A weekly digest"). One of these should be restructured.
Prompt for agents
The essay has two tricolon lists (three parallel items starting with the same word), which CLAUDE.md limits to one per essay. The first tricolon at line 43 ('No webhooks...No cron jobs...No file watchers') is more rhetorically effective, so keep that one. The second tricolon at line 55 ('A background process...A watcher...A weekly digest') should be restructured. Consider combining the three items into a flowing sentence, e.g. describing the background process and watcher inline rather than as three parallel 'A [noun]' sentences. The goal is to break the visible parallel structure while preserving the same information.
Was this helpful? React with 👍 or 👎 to provide feedback.
| dropcap: true | ||
| --- | ||
|
|
||
| [PostHog](https://posthog.com) launched [Code](https://posthog.com/code) this spring, and the interesting thing about it isn't the coding agent itself. It's what the coding agent can see. |
There was a problem hiding this comment.
🔴 Repeated "isn't X. It's Y." inversion is an LLM tell flagged in CLAUDE.md
CLAUDE.md explicitly flags "'This is not X. It is Y.' inversions" as one of the biggest LLM-sounding sentence structure tells and instructs: "If a sentence sounds like it could appear in any AI-generated essay on any topic, rewrite it." The essay uses this exact pattern twice: line 9 ("the interesting thing about it isn't the coding agent itself. It's what the coding agent can see.") and line 65 ("PostHog Code isn't trying to be a proactive agent. It's a coding tool"). Having two instances creates a recognizable AI writing pattern. At least one should be restructured.
Prompt for agents
The essay uses the 'isn't X. It's Y.' inversion twice — once at line 9 (opening paragraph) and once at line 65 (closing section opener). CLAUDE.md calls this structure out as an LLM tell. Rewrite at least one to break the pattern. For the opening at line 9, consider leading with the positive claim directly (e.g. 'the interesting thing is what the coding agent can see') rather than the negation-then-reveal structure. Alternatively, restructure line 65 to merge the two halves into a single sentence without the contrast pivot.
Was this helpful? React with 👍 or 👎 to provide feedback.
- Remove "isn't X. It's Y." inversion from opening line and closing section - Restructure second tricolon list to break parallel "A [noun]" pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Files changed
content/posts/posthog-code.mdx— new essaycomponents/mdx/figures.tsx— PHEnricherFigure (code + production context diagram) and PHSignalGapFigure (signals exist but no trigger connects them to agent)components/mdx/mdx-components.tsx— register new figurescomponents/card-illustrations.tsx— PostHogCodeArt card illustration + slug mappingTest plan
tsc --noEmit)🤖 Generated with Claude Code