establishing-code-ownership
Skill727 starsChanged yesterdayMITView on GitHub
Determine which PostHog team owns a file, directory, or code path, or enumerate all code a team owns (via distributed `owners.yaml`, `products/*/product.yaml`, and `.github/CODEOWNERS`). Use when assigning a reviewer, attributing a bug or slow query to a team, routing work, scoping a team-wide audit, or answering "who owns X" / "what does team Y own".
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 9
Don't re-parse the ownership files by hand.
- Very specific: line 24
No hogli/flox available? The dependency-light fallback needs only pyyaml: git ls-files posthog/hogql | PYTHONPATH=packages/owners-yaml …
- Very specific: line 56
If neither the resolver nor product.yaml resolves it, consult the feature-ownership handbook — coarse-grained (broad areas, not files) and …
- Distinctive: line 57
If even that fails and the Slack MCP is available, search Slack — least authoritative (opinions, stale threads), so verify against the repo …
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Establishing code ownership
Ownership is resolved by one tool — hogli owners:* — over distributed owners.yaml files.
Don't re-parse the ownership files by hand; the resolver owns the semantics and is what CI enforces.
Fast path: hogli owners:*
Dev machines have flox/hogli, so shell straight to the resolver.
hogli owners:who posthog/hogql/printer.py # who owns this path (+ the file that decided it)
hogli owners:resolve --json posthog/api/survey.py products/surveys/backend/api.py # batch, JSON keyed by path
hogli owners:unowned # every tracked file with no owner (append a prefix to scope: `owners:unowned products/`)owners:who prints the resolved owners, the status, the Slack channel, and source — the owners.yaml/product.yaml file that decided the answer.
The channel comes from the root teams: registry entry for the primary owner, else a derived #<slug>; a path whose primary owner is an @handle has no channel.
owners:resolve takes paths as arguments or newline-delimited on stdin, so you can pipe a file list: git ls-files posthog/hogql | hogli owners:resolve --json.
No hogli/flox available? The dependency-light fallback needs only pyyaml: git ls-files posthog/hogql | PYTHONPATH=packages/owners-yaml python -m owners_yaml (stdin paths → the same JSON).
Resolution algorithm (what the resolver does)
For a path, it walks from the repo root down to the path collecting ownership files, then merges them nearest-file-wins:
owners.yaml— the canonical, distributed source. Each directory can carry one. Fields (owners,status,inherit, per-pathrules) fall through to the nearest ancestor unless overridden.inherit: falsecuts the walk (Gerrit'sset noparent) — nothing above it contributes. Within a file, every matching rule applies in order, and each replaces only the fields it sets.owners: nullmeans unowned by design (exempt from the coverage check), distinct from a directory with no file at all (genuinely unowned).additions:names the owners of additions below a directory rather than the owners of the files in it (the consumer decides what counts as an addition); it never changesowners, and it adds up across the walk so a nested file cannot drop an ancestor's entry.sensitive: truemarks paths where a small change matters (a CI baseline, an exemption list), so the reviewer assigner requests their owners for every change, whatever its size; it is nearest-wins likestatus, aproduct.yamlcan set it too, and it never makes a review required.products/<name>/product.yaml— an accepted alias. The rootowners.yamlenables this withalias_files: [product.yaml]. When a product dir has noowners.yaml, itsproduct.yamlowners:list is read as the ownership forproducts/<name>/**, and itssensitive:flag applies to that tree too (every otherproduct.yamlfield is ignored). A dir with both files is a lint error;owners.yamlwins..github/CODEOWNERS— blocking approvals, never part of the walk. It keeps GitHub-native semantics, stays hand-maintained (mostly infra, e.g.team-security), and is enforced by GitHub itself. The resolver does not read it — when you need to know whether a blocking approval is additionally required, consult the file directly. It never changes the resolvedowners, and nothing here writes to it. A tool that can only read CODEOWNERS gets a generated projection of the map instead, fromhogli owners:codeowners(see packages/owners-yaml/README.md); that projection covers test files and is never.github/CODEOWNERS.
Owners are a mixed list of team slugs (team-devex, conversations, logs — the GitHub team handle minus @PostHog/) and @handles for individuals; the first entry is the primary owner.
team → code (what does this team own?)
There's no single "team → files" command; resolve the tree and filter by slug:
git ls-files | hogli owners:resolve --json | jq -r 'to_entries[] | select(.value.owners | index("team-surveys")) | .key'Also grep products/*/product.yaml for the slug — each hit is all of that products/<name>/**; one team often owns several, so don't stop at the first.
Owned paths span backend and frontend/src/...; cover both, or say up front you're doing one side.
Generated files
A generated artifact often resolves to a broad parent owner or nobody.
Trace it to the input it's generated from and report that team as the logical owner (e.g. services/mcp/src/tools/generated/<x>.ts comes from products/<name>/mcp/tools.yaml).
Distinguish the logical owner (the team owning the source — the answer to report) from the literal resolver result on the generated path, and flag the gap so the operator can decide whether to pin it with a rules: entry.
Last resort: feature-ownership handbook, then Slack
If neither the resolver nor product.yaml resolves it, consult the feature-ownership handbook — coarse-grained (broad areas, not files) and hand-maintained, so prefer the repo files and flag any handbook-sourced answer as possibly stale.
If even that fails and the Slack MCP is available, search Slack — least authoritative (opinions, stale threads), so verify against the repo files and flag the answer as Slack-sourced.
Slug vs handle
- Handle (
CODEOWNERS):@PostHog/<slug>, e.g.@PostHog/team-replay. - Slug (
owners.yaml/product.yaml): handle minus@PostHog/, e.g.team-replay. - Not uniform: some carry
team-(team-self-driving), some don't (conversations,logs). If a name doesn't resolve, try both forms.
Other versions1 project uses a version of this.
Word for word · 1
- PostHog/posthog★ 40k100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository124 other files it gives its agents.
- AGENTS.mdAGENTS.md
- common/AGENTS.mdAGENTS.md
- hog/AGENTS.mdAGENTS.md
- proto/AGENTS.mdAGENTS.md
- rust/AGENTS.mdAGENTS.md
- .cursor/rules/django-python.mdcCursor rule
- .cursor/rules/react-typescript.mdcCursor rule
- .cursor/rules/rust.mdcCursor rule
- adding-activity-loggingSkill
- adding-api-scopesSkill
- adding-inbound-webhooksSkill
- adding-inbox-sourcesSkill
- adding-ingestion-warningsSkill
- adding-mcp-store-serversSkill
- adding-personhog-rpcSkill
- adding-product-alertingSkill
- adding-project-secret-api-key-authSkill
- adding-today-highlightsSkill
- adopting-generated-api-typesSkill
- analyzing-experiment-precompute-canarySkill
- analyzing-experiment-query-performanceSkill
- analyzing-insights-across-teamsSkill
- announcing-behavior-changesSkill
- auditing-llm-gateway-paritySkill
- auditing-warehouse-source-coverageSkill
- authenticating-to-clickhouseSkill
- authoring-ci-workflowsSkill
- building-product-empty-statesSkill
- building-the-toolbarSkill
- clickhouse-migrationsSkill
- debugging-ci-failuresSkill
- debugging-local-replaySkill
- debugging-local-task-agent-runsSkill
- debugging-mcp-analyticsSkill
- debugging-signals-pipelineSkill
- debugging-table-access-deniedSkill
- depot-ciSkill
- depot-container-buildsSkill
- depot-github-runnersSkill
- developing-subscriptionsSkill
- django-migrationsSkill
- django-startup-timeSkill
- documenting-warehouse-sourcesSkill
- editing-agents-mdSkill
- extending-hobby-smoke-testsSkill
- extending-personhog-test-harnessSkill
- finding-llm-gateway-migration-candidatesSkill
- fixing-flaky-testsSkill
- formatting-slack-messagesSkill
- gating-production-deploysSkill
- gating-sensitive-actionsSkill
- generating-clickhouse-query-performance-reportsSkill
- hogliSkill
- implementing-mcp-toolsSkill
- implementing-mcp-ui-appsSkill
- implementing-warehouse-sourcesSkill
- improving-drf-endpointsSkill
- improving-mcp-toolsSkill
- ingestion-pipeline-doctor-nodejsSkill
- instrumenting-first-party-metricsSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

