# File specifications

What each file must hold, who reads it, and how it goes wrong. Paths are fixed: other skills read these exact names. The templates in `assets/` hold the field lists; this file says why each field is there and which skill depends on it.

## Header on every file

Each Markdown file starts with YAML front matter, including `README.md`, `tracking-plan/README.md` and `decisions.md`:

```yaml
---
file: metrics.md
owner_role: revenue-operations-lead
approver_role: head-of-growth
status: approved            # draft | approved | under-review
version: 3                  # integer, bumped on any change in meaning
effective_from: 2026-10-01
last_reviewed: 2026-10-17
review_by: 2027-01-17
review_cadence: quarterly   # see maintenance.md
change_triggers: [pricing change, new lifecycle stage, new product line]
open_items: 2               # count of unresolved questions listed at the top of the file
---
```

- `status: draft` means other skills may read it but must say the source is unapproved. A new file starts as `draft`, including `decisions.md`, until the creation entry names the approver.
- `review_by` in the past means stale. Rules for stale files, including the stricter rule for actions, are in `references/maintenance.md`.
- Roles rather than personal names keep the file valid when people move. A name may be added beside the role.
- Every file has an `## Open items` section at the top, even if empty, so the count in the header can be checked.

## README.md (the index)

- Purpose: the one file an agent reads first. It says what each file governs, when to read it, who owns it and when it is next reviewed.
- Must hold: one bullet per file with governs, read when, owner role, status and review_by; the precedence rule; the optional files present and which skill wrote each; context kept elsewhere and linked (see `references/existing-context.md`); the exclusion rule; how to propose a change.
- Size: under 80 lines. It is loaded often, so detail belongs in the files it points to.
- Read by: every skill, and the agent's project instruction file points here.

## stack.md

- Purpose: what runs where, who owns it, and how an agent can look at it.
- Must hold, per tool and environment: job in one line, status (active, migrating, retiring, with dates), operating owner and change approver, who can publish, account ownership (owned by company or agency, company-held admin roles, linked under which manager account or business portfolio, access last reviewed), public identifiers, data in and out, agent access route (export path or MCP server with its read-only mode), where credentials are stored (by name), renewal date where it drives decisions, `last_verified` date, method and baseline snapshot.
- Tool-specific fields other skills read by name:
  - Ad platforms: manager account, campaign classes (brand, non-brand, competitor, Performance Max), Google Ads Editor version and who posts imports.
  - Tag management: which site each container serves, server container host, retired container and destination IDs.
  - ESP or messaging platform: workspaces, REST cluster or region, SDK platforms and versions, every system that writes to it.
  - CRM: hubs or products and editions, other CRMs, connectors.
  - Analytics: GA4 standard or 360, property and stream IDs, BigQuery export project, dataset and location.
- Also: domains and apps that send data, environments, a data-flow list (`source -> destination: method, frequency`), consent tooling, and copies of context held in vendor AI features.
- Read by:
  - tracking-break-map: senders, containers, server endpoint and host, export, warehouse, BI, owners, environments.
  - purchase-reconciliation: GA4 property and stream IDs, BigQuery export project, dataset and location, every purchase sender.
  - ga4-unassigned-not-set-diagnosis: GA4 property and streams, web and server containers, CMP and consent mode, every domain the journey crosses, payment providers, Measurement Protocol senders.
  - consent-debugging: CMP, containers, hardcoded tags, server container, tag gateway.
  - gtm-container-audit: container IDs and which site each serves, GA4, Google Ads and Floodlight IDs, pixels, server container host, CMP, owners, retired IDs.
  - google-ads-editor-import-builder and negative-keyword-workflow: customer ID, manager account, campaign classes, Editor version, who posts.
  - utm-convention-and-registry and campaign-naming-convention: ad platforms and account IDs, ESP, affiliate network, shortener or redirect service, spend connectors, CRM, warehouse, GA4 standard or 360.
  - braze-implementation-qa: workspaces, REST cluster, SDK platforms and versions, every system that writes to Braze, owners.
  - hubspot-implementation-plan: hubs and editions, other CRMs, billing, product database, warehouse, connectors, owners, environments.
  - agent-write-safety: systems, environments, account and container names, owners.
  - tracking-plan-builder, analytics-tool-selector, attribution-model-selector, mobile-attribution-fundamentals: emitters, SDKs and versions, MMP, ad networks, subscription platform, destinations, owners.
- Fails when: a tool is listed from memory and was removed months ago; two senders to one destination are recorded as one; IDs have no environment, so staging data is queried as production; an agency owns the account and nobody recorded it.

## naming-rules.md

- Purpose: the rules for event names, property names, UTM values, in-platform campaign names, tag manager names and CRM property internal names, plus what to do with a value that fits no rule.
- Must hold: format rules (case, separators, tense, length limits checked live), approved vocabularies or a link to the registry, the identifier versus display label distinction, old-to-new mappings with cutover dates, and an unrecognised-value rule ("flag for review; do not create a new value").
- Observed compliance, from one 90-day export: the share of distinct values that match, and the share weighted by sessions or clicks. A few malformed values can carry most traffic, so report both. If the weighted share is below the threshold the owner sets (default 80 percent), record the rule as "documented, not followed" and open an item for the owner.
- Read by: event-naming-convention, tracking-plan-builder, utm-convention-and-registry, campaign-naming-convention, attribution-model-selector, ga4-unassigned-not-set-diagnosis (approved source and medium pairs), google-ads-editor-import-builder, gtm-container-audit (tag and trigger naming), hubspot-implementation-plan (property internal names).
- Fails when: the agent "cleans" a value by inventing a category; a display label is used as a join key and breaks when marketing renames a campaign.

## metrics.md

- Purpose: the business contract for each metric that drives a decision.
- Must hold, per metric: `metric_id` with a version suffix (`cac_new_paid_v1`; the base name never changes, the suffix changes only with meaning), display name, status, its own `last_reviewed` and `review_by`, decision and what it must not be used for, entity and grain, numerator and denominator, date field and time zone, window with boundary rules, maturity and complete-data cutoff, exclusions, unknown and missing input handling, zero-denominator result, aggregation rule, `segments_overlap`, time additivity, supported dimensions with their scope, `not_equivalent_to`, authoritative implementation (dbt metric, semantic view, LookML measure or SQL file path), business owner, technical owner, a worked example with the expected answer, and acceptance fixtures.
- Aggregation: disjoint segments sum numerators and denominators, then divide. Overlapping segments (multi-touch channels, overlapping audiences) are recomputed from the deduplicated eligible population. Never average segment rates.
- Dimension scope: fixed at a milestone (plan at signup) or current value. For channel and source dimensions, name the exact scope: GA4 traffic-source dimensions come in first-user, session and event scopes, and the same channel label answers a different question in each. Or name the attribution rule.
- File-level blocks: "Ad platform conversion actions" (each action, primary or secondary, and which feed bidding) and "Targets" (target CPA, ROAS or other goals, with an effective period, versioned separately from the definitions because targets change more often).
- Start with three to five metrics. The number of metrics is not the measure of progress.
- Where a semantic layer exists (dbt Semantic Layer, Snowflake semantic views, LookML), `metrics.md` holds the business agreement and points to the implementation. It does not become a second, competing calculation.
- Read by: tracking-plan-builder (links journeys to metric IDs), purchase-reconciliation (order and revenue definitions, thresholds), tracking-break-map (the metric under complaint), analytics-tool-selector, attribution-model-selector (outcome definition), mobile-attribution-fundamentals (install, activation, payer, CAC and payback), negative-keyword-workflow (conversion actions in the Conversions column, target CPA or ROAS), hubspot-implementation-plan (lifecycle and pipeline definitions), campaign-naming-convention (which reports group spend, and by what).
- Fails when: unknowns are dropped and the rate improves as data quality falls; rates are averaged across segments instead of recomputed from numerator and denominator; overlapping segments are summed; daily snapshots are summed into a period total; SQL and prose disagree and nobody is named to resolve it.

## data-dictionary.md

- Purpose: where evidence comes from and how records relate. Not a column dump.
- Must hold: entities with business keys and mappings per system (expected cardinality, for example one current CRM company per account); timestamps and what each means, with time zone; shared properties and attributes defined once (type, allowed values, `null_means`, written by, which writer wins on conflict, used by); join hazards with the approved model or aggregation; known lags and limitations; misleading field names with what they really record; deprecated fields still populated.
- Read by: tracking-plan-builder and event-naming-convention (shared property definitions), utm-convention-and-registry (cost tables and the CRM fields that store UTMs), campaign-naming-convention (campaign dimension columns), braze-implementation-qa (which system owns each custom attribute), hubspot-implementation-plan (existing field definitions and owners), any skill writing SQL.
- Fails when: an agent picks a valid but wrong date field; a three-table join multiplies revenue; a field named for product activity records CRM activity; two systems write the same attribute and nobody knows which wins.

## tracking-plan/

- This skill creates only `tracking-plan/README.md` and `tracking-plan/CHANGELOG.md` with a heading. Journey files and event contracts are written by tracking-plan-builder.
- README must hold: where the authoritative plan lives (this folder, Segment Protocols, Mixpanel Lexicon, Amplitude Data, RudderStack, Avo or a sheet) and the date of the last export if it lives elsewhere; the index of journeys and contracts with status; conversion events with their intended hostnames and regions and must-not-fire conditions; which enforcement tool validates events; events observed but not in the plan.
- Read by: tracking-plan-builder, purchase-reconciliation (purchase contract), consent-debugging (consent category per event), tracking-break-map (source of truth and expected ratio), gtm-container-audit (conversion scope and must-not-fire conditions), braze-implementation-qa (Canvas trigger and exit event contracts), analytics-tool-selector, mobile-attribution-fundamentals.
- Fails when: two plans claim to be current (a sheet and Protocols) and differ.

## decisions.md

- Purpose: the dated record of why the data looks the way it does, and who may approve what.
- Sections:
  - Approval policy: per change class, the approver role, maximum objects, maximum spend change, freeze windows and approval expiry. agent-write-safety reads this before any write.
  - Decisions, newest first: ID, date, status (proposed, accepted, superseded by ID), title, context, decision, alternatives, consequences including any series break, owner, approver, effective date, affected files, metrics and tools.
  - Release log, newest first: date, system, change, version, who released. GTM versions, CMP changes, checkout or signup changes, server integrations, SDK upgrades, context file versions.
  - Data incidents, newest first: date range, affected tools and metrics, cause, treatment (annotated, restated, excluded), link to an incident record if one exists.
- Append-only. A decision is superseded by a new entry, never edited in place, except to set its status.
- Read by almost every skill: approval policy and change classes (agent-write-safety), consent model (consent-debugging, purchase-reconciliation, gtm-container-audit, braze-implementation-qa, hubspot-implementation-plan), custom channel groups, unwanted referrals and cross-domain list (ga4-unassigned-not-set-diagnosis: put the full current list in the entry that changes it), attribution model and window changes (attribution-model-selector), UTM and naming cutovers and mappings (utm-convention-and-registry, campaign-naming-convention), naming exceptions (event-naming-convention), earlier tool decisions (analytics-tool-selector), posted Editor imports (google-ads-editor-import-builder), competitor, served-region and existing-customer decisions (negative-keyword-workflow), messaging policy such as frequency caps and control groups (braze-implementation-qa), identity and account boundary decisions (hubspot-implementation-plan, mobile-attribution-fundamentals), ATT decisions (mobile-attribution-fundamentals).
- Fails when: a reporting time zone change, a consent mode switch or a channel group edit has no date, so a trend break is read as performance.

## Optional files

- Written by other skills, listed in the index when present:
  - `utm-registry.csv` and `platform-campaign-map.csv`: utm-convention-and-registry.
  - `naming-rules.yaml`, `naming-vocab.csv` and `campaign-registry.csv`: campaign-naming-convention.
  - `change-log/<YYYY-MM-DD>-<slug>.md`: agent-write-safety, one log per applied batch.
  - A measurement map: mobile-attribution-fundamentals.
  - Incident records: ga4-unassigned-not-set-diagnosis saves them where the user chooses and proposes a dated summary for `decisions.md`. `incidents/<date>-<slug>.md` is a suggested location, not a fixed path.
- Written by this skill:
  - `inventory/<YYYY-MM-DD>.yaml`: the inventory worksheet from each run, definitions and public identifiers only. It is the provenance evidence for `stack.md` and the baseline for the next drift check.
  - `context-tests.yaml` from `assets/context-test-set.yaml`.
  - On request: `customer-fit.md`, `playbooks.md`, `brand-and-claims.md` from `assets/optional-files-template.md`.
