Skill: Deploy History

Tools for answering “what shipped, when, and is it live?” using the local git history of the AlaskanFishermanFrontend and workflow repos. Read-only — never modifies source code.

When to use

  • Hypotheses that depend on whether or when an instrumentation or page change shipped
  • Sanity-checking a custom semantic event before reasoning about its data (“is page_view actually emitted from code, and since when?”)
  • Reconciling spec (semantic.md) against implementation
  • Identifying recent changes that might have caused a metric shift
  • Producing the deploy timeline for a run’s findings.md

Conventions (from knowledge/product.md)

  • origin/main is the deploy reference for both AlaskanFishermanFrontend and workflow. Local main may drift; never trust it without fetching.
  • Merge date on origin/main = deploy date (CDN cache TTLs add a few minutes; Cloudflare Worker config changes are separate from a code deploy and not covered by these queries).
  • PR not yet merged ≠ live.

Non-destructive refresh — always run first

git -C <repo-path> fetch origin --no-tags --prune

fetch only updates remote-tracking refs (origin/main, etc.). It does not touch the working tree, the index, any local branch, or any stash. Safe to run regardless of what’s checked out or what uncommitted changes exist.

<repo-path> is one of:

  • /Users/andrej/projects/freelance/alaskan/AlaskanFishermanFrontend
  • /Users/andrej/projects/freelance/alaskan/workflow

Canonical queries

All queries below operate on origin/main so the result reflects what’s live, regardless of local branch state.

When did a file first ship?

git -C <repo> log origin/main --diff-filter=A --format='%h %ai %s' -- <path>

Returns the commit that first added <path> to main. Use for “when did this component / event emitter / handler first reach production?”.

When did a string (event name, function name, URL) first appear or last change?

git -C <repo> log origin/main -p -S '<string>' --format='%h %ai %s' --pickaxe-all

-S '<string>' finds commits that change the count of occurrences of <string> (added or removed). Use for “when did 'page_view' start being emitted?” or “did pushAddPaymentInfoFromSummary ever pass orderId?”.

What was deployed in a date range?

git -C <repo> log origin/main --since='<start>' --until='<end>' --oneline --first-parent

--first-parent keeps the timeline along main, hiding noisy intra-PR commits. Use for “what landed on the frontend between 2026-05-04 and 2026-05-09?”.

Inspect a specific commit’s scope

git -C <repo> show <sha> --stat
git -C <repo> show <sha> -- <path>

The first gives the file list and line counts; the second shows the actual diff for one file. Cite the SHA when reporting findings.

Line-level provenance

git -C <repo> blame -w -L <start>,<end> origin/main -- <path>

-w ignores whitespace-only changes (avoids “the formatter touched this” noise). Use to identify the PR/commit responsible for a specific line that’s behaving unexpectedly.

Build a current emission map (route → event)

Used by the conversion-orchestrator’s pre-flight to produce a per-run binding from funnel events to the routes that currently emit them. Do not cache the result in the KB — re-derive each run so drift cannot creep in. The output belongs in the run’s inputs.json under emission_map, not in semantic.md or product.md.

# 1. extract the (route → component) list from the SPA router
git -C <repo> show origin/main:version1/src/router.tsx

# 2. for each funnel event string, find emission callsites
git -C <repo> grep -nE "['\"]<event_name>['\"]" origin/main -- shared/src version1/src

# 3. for each callsite's hook / util, find the page components that import it
git -C <repo> grep -nE "<hook_or_fn_name>" origin/main -- version1/src/pages

# 4. join step 3's component name back to a route from step 1

# 5. trace the navigation graph from the lander. Grep the lander component and its child
#    components (e.g. version1/src/components/landing/) for navigate(, useNavigate, <Link to=,
#    to= props. Any destination route that itself emits a funnel event makes that event a
#    valid stage signal — the originating route does not have to emit it.
git -C <repo> grep -nE "navigate\(|useNavigate|<Link to=|to=" origin/main -- \
    version1/src/pages/LandingPage.tsx version1/src/components/landing/

Cross-check the resulting map against knowledge/semantic.md’s “Stage-to-role intent” table. An event firing from a route that does not fill its stage’s role is a C2 instrumentation mismatch — surface as a candidate finding before any volume-based hypothesis on that event. C2 is per-event, not per-stage: one Selection event being C2 does not invalidate sibling events that are correctly wired through the navigation graph.

Worked example — Selection stage with two events on the 2026-05-13 run, one C2, one not:

# Event A: view_item_list

# step 2: where is view_item_list emitted?
git -C AlaskanFishermanFrontend grep -nE "['\"]view_item_list['\"]" origin/main -- shared/src version1/src
# → shared/src/utils/funnelEvents.ts:47   afDl.push('view_item_list', ...)

# step 3: who imports the emitter wrapper?
git -C AlaskanFishermanFrontend grep -nE "useViewItemList" origin/main -- version1/src/pages
# → version1/src/pages/shop/ProductSelectionPage.tsx:25 useViewItemList(visibleProducts)

# step 4: what route mounts ProductSelectionPage?
git -C AlaskanFishermanFrontend grep -nE "ProductSelectionPage|choose-your-fish" origin/main -- version1/src/router.tsx
# → /shop (index)    mounts ProductSelectionPage
# → /choose-your-fish mounts LandingPage    ← the ad lander, has no useViewItemList

# Verdict for view_item_list: C2. Wired to /shop; paid Meta lands on /choose-your-fish.
# The event will read near-zero for paid traffic by design, not by behaviour.

# Event B: select_item — same stage, different verdict

# step 2: where is select_item emitted?
git -C AlaskanFishermanFrontend grep -nE "['\"]select_item['\"]" origin/main -- shared/src version1/src
# → shared/src/utils/funnelEvents.ts:86   afDl.push('select_item', ...)

# step 3: who calls pushSelectItem / uses useProductPageAnalytics?
git -C AlaskanFishermanFrontend grep -nE "pushSelectItem|useProductPageAnalytics" origin/main -- version1/src
# → version1/src/hooks/useProductPageAnalytics.ts:79  pushSelectItem(product, ...)
# → version1/src/pages/ProductPage.tsx               uses useProductPageAnalytics
# → version1/src/pages/shop/ProductSelectionPage.tsx pushSelectItem on card click

# step 4: which route mounts ProductPage?
# → /product/:variant in router.tsx

# step 5: does the lander navigate to /product/:variant?
git -C AlaskanFishermanFrontend grep -nE "navigate\(['\"]/product" origin/main -- version1/src/components/landing/
# → SourceTruhSecton.tsx:13  navigate(`/product/${product}`)  on card click in #vybrat-box

# Verdict for select_item: NOT C2. Paid Meta lands on /choose-your-fish; the lander has
# product cards that navigate to /product/:variant; ProductPage mounts useProductPageAnalytics
# which fires select_item. The Selection-stage role is filled via the navigation graph, even
# though the lander itself does not emit the event. select_item is a valid behavioural signal
# for paid traffic at the Selection stage.

The failure mode this catches: stopping at step 4 with the first broken event found, and then dismissing the whole stage as C2. Per-event verdicts + navigation trace separates a real route-to-route drop from an event-wiring bug.

Check if a PR has actually been merged

git -C <repo> log origin/main --grep='Merge pull request #<N>' --oneline

If empty, the PR isn’t on main yet — treat any change it claims to make as not live.

Worked example — the 2026-05-04 PostHog pageview change

Question: “Why did PostHog DAU drop after May 4/5?”

cd /Users/andrej/projects/freelance/alaskan/AlaskanFishermanFrontend
git fetch origin --no-tags --prune
git log origin/main --diff-filter=A --format='%h %ai %s' -- shared/src/utils/dl.ts
# → 0a66087 2026-04-30 21:50 +0200  feat: dataLayer envelope and PostHog super-properties for new web

git log origin/main -p -S "'page_view'" --format='%h %ai %s' --pickaxe-all -- shared/src/
# → first commit adding the literal: 0a66087 (2026-04-30, on a branch)
# → first merge to main carrying it: cd49a72 (2026-05-04 20:43 — feat/de-gtm-and-posthog-parity)

git log origin/main --since='2026-04-30' --until='2026-05-08' --oneline --first-parent
# → cd49a72 PR #1 (2026-05-04 20:43)
# → b7eee49 PR #3 (2026-05-06 08:21)
# → 2bad0a5 PR #4 (2026-05-07 14:21)

Conclusion: the custom page_view event was deployed at 2026-05-04 20:43 CET. Any analysis window starting before 2026-05-05 has a partially-zero denominator on this event. Documented in knowledge/semantic.md instrumentation gaps.

Follow-up diagnosis on 2026-05-11:

  • version1/index.html / version2/index.html had capture_pageview: false, so PostHog stopped emitting native $pageview.
  • shared/src/hooks/usePageView.ts still called afDl.push('page_view'), and shared/src/utils/dl.ts mirrored that custom event into PostHog.
  • PostHog built-in DAU/WAU widgets expect $pageview/screen events, so the widgets dropped even though custom page_view traffic continued.

Affected interval: 2026-05-05 through 2026-05-11 before the fix merge. During this interval, custom page_view is the reliable onsite funnel-entry event, while PostHog built-in DAU / WAU widgets based on $pageview undercount.

Fix branch: AlaskanFishermanFrontend fix/posthog-native-pageviews.

Intended fix:

  • set PostHog capture_pageview: 'history_change' for SPA-native $pageview;
  • keep page_view in window.dataLayer for GTM/GA4 parity;
  • stop mirroring only page_view into PostHog;
  • continue mirroring ecommerce/business events into PostHog.

Output discipline

When reporting deploy-history findings:

  • Cite the SHA + commit timestamp + PR number (not just “May 4”). Future readers want the audit trail.
  • State the repo + branch (AlaskanFishermanFrontend origin/main).
  • Distinguish “merged to main” from “exists on a branch” — only the former is live.
  • If the answer is “not yet merged”, say so explicitly and surface the PR number / branch name so the orchestrator can flag it as a pending change.

Hard rules

  • Read-only. Never run git commit, git push, git reset, git checkout, git restore, git stash, git rebase, git merge, or any working-tree-modifying command. The agentic system observes these repos; engineering changes them.
  • fetch is the only state-changing command allowed, and only because it’s non-destructive.
  • Do not modify .git/config or set credentials. Don’t touch hooks.
  • If a question seems to require modifying source, it’s the wrong question for this skill — surface as a Data gap and suggest the orchestrator file a separate engineering ticket.

This site uses Just the Docs, a documentation theme for Jekyll.