isolating-product-facade-contracts

Migrates PostHog products to a facade and contracts architecture with enforced import boundaries.

713|118|Updated Aug 11, 2020
One-click install
npx skills add https://github.com/PostHog/posthog-foss --skill isolating-product-facade-contracts
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: isolating-product-facade-contracts
Source: https://github.com/PostHog/posthog-foss/tree/main/.agents/skills/isolating-product-facade-contracts
Command: npx skills add https://github.com/PostHog/posthog-foss --skill isolating-product-facade-contracts

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

PostHog products that expose internals (models, logic, views) across boundaries create tight coupling, slow CI, and unsafe test skipping. This Skill guides the migration of a product to the isolated architecture used by Visual review: a pure contracts layer, a thin facade, and presentation separated behind enforced import boundaries.

Core Features & Use Cases

  • Recon and baseline: Uses hogli product:isolate:scan, product:maturity, and product:lint to classify cross-boundary references, measure core coupling, and detect which migration phase a product is in.
  • Structured migration workflow: Defines contracts in facade/contracts.py, builds a thin facade/api.py, migrates callers in one pass, and moves presentation to consume the facade with hogli product:isolate:move.
  • Boundary enforcement: Turns on tach interfaces, import-linter contracts, the backend:contract-check CI skip, and narrowed turbo.json inputs only when isolation is sound.
  • Use Case: A product like web_analytics still has core importing its models and test fixtures. Use this Skill to scan the coupling, build facade read/write functions, reroute callers, seal reverse accessors, and enable the CI skip once ignore_imports debt is drained.

Quick Start

Ask the AI to run the isolation scan for a PostHog product and plan its migration to the facade and contracts architecture following this skill.

Frequently Asked Questions about isolating-product-facade-contracts

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I migrate a PostHog product to the facade and contracts architecture?

Start with hogli product:isolate:scan to map cross-boundary references, then define frozen pydantic dataclasses in facade/contracts.py, build a thin facade/api.py, migrate callers in one pass, and move presentation to consume the facade. Finish by enabling tach interfaces and the backend:contract-check script.

How do I know which migration phase a PostHog product is in?

Run hogli product:maturity and product:isolate:scan. A fresh product has no facade directory, a mid-sweep product has contracts and api but core still imports internals, and a mid presentation-wave product still has ignore_imports TODO entries in pyproject.toml.

When can a PostHog product enable the backend:contract-check CI skip?

Only after the product is fully isolated: no ignore_imports entries remain, presentation is thin, and the tach boundary is on. hogli product:lint blocks the script while deferred entries exist because the skip is unsound until then.

Does a product need a facade if nothing imports it in-process?

Yes. Cross-cutting tests exercise a product's HTTP API in-process by URL with zero imports, which import-graph tools cannot see. The facade seals presentation so every observable behavior lives behind the boundary, making the CI skip sound.

How do I handle cross-product foreign keys during isolation?

Seal the relation with related_name="+" and remove any explicit related_query_name, then delete its line from products/model_crossing_uses_baseline.txt. Give callers that need reverse access a facade read function instead.

What coupling does the isolate scan miss?

The scan only walks backend.* imports, so it misses reverse accessors, string-based signal senders, test-infrastructure imports, product-root surfaces like dags/, HogQL system tables, and dotted-string config. Use git grep "products.<name>" and the scan's string-reference section to find them.