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_viewactually 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/mainis the deploy reference for bothAlaskanFishermanFrontendandworkflow. Localmainmay 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.htmlhadcapture_pageview: false, so PostHog stopped emitting native$pageview.shared/src/hooks/usePageView.tsstill calledafDl.push('page_view'), andshared/src/utils/dl.tsmirrored that custom event into PostHog.- PostHog built-in DAU/WAU widgets expect
$pageview/screen events, so the widgets dropped even though custompage_viewtraffic 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_viewinwindow.dataLayerfor GTM/GA4 parity; - stop mirroring only
page_viewinto 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. fetchis the only state-changing command allowed, and only because it’s non-destructive.- Do not modify
.git/configor 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.