Skip to main content

26Q3 CDP Adhoc

Bucket initiative for small, unrelated product/customer-facing adhoc requests and bugfixes handled by the CDP team in 26Q3 — billing/API edge cases, CRM↔CDP data-sync fixes, and UI polish. Each item is a self-contained user story with its own PRD under prds/ — or, where the ask arrives from another squad as an engineering intake rather than a PM-authored product story, an RFC under rfcs/ (A6 is the first); they do not share a single product theme beyond being adhoc work that rolls up to Jira epic TF-3477 — an Epic that already existed (created 2026-07-03) before this repo-side bucket was stood up on 2026-07-14; it is reused as-is per the one-initiative-one-Epic rule rather than minting a second Epic.

This is a sibling, distinct bucket from CDP 26Q3 Engineering Initiatives (TF-3500): that one is engineering-owned infra/EOL/tech-debt work with its own RFCs; this one is product/customer-facing adhoc bugfixes with PRDs. Full doctrine + real-world grounding: .claude/reference/adhoc-interrupt-doctrine.md.

Backfilled, not newly discovered. All four stories below existed as Jira Tasks directly under Epic TF-3477 before this tracker existed (surfaced across sprint-resync passes 1-6, 2026-07-09 through 2026-07-14, as an undocumented off-plan-load finding). This README/tracker documents that existing work retroactively; nothing here changes what already happened on the board.

Story layer minted 2026-07-14 — Epic parenting correct, split-link direction currently WRONG, pending fix. Each row now has a real Jira Story under Epic TF-3477 (TF-3513–3516, parent = TF-3477 confirmed via getJiraIssue). But the "Work item split" links between each Story and its Task(s) are backwards: as created, each Story reads "split from" its Task, and each Task reads "split to" its Story — the reverse of the intended relationship (Task should read "split from" Story; Story should read "split to" Task). Root cause: the createIssueLink tool's outwardIssue/inwardIssue parameters are inverted from the naive reading, and this repo's own CLAUDE.md documented the wrong mapping — now corrected there (and in the jira-alignment-check/sprint-jira-sync skills), see CLAUDE.md's Jira alignment section. The 5 links minted this pass (TF-3513↔TF-3478, TF-3514↔TF-3483, TF-3514↔TF-3484, TF-3515↔TF-3486, TF-3516↔TF-3505) need to be deleted and recreated with the corrected parameter order — no delete-link tool was available in this session, so this is left as a follow-up. engineering-q3-2026's TF-3499 ↔ TF-3504 link (created under the same old, wrong doc) is suspected to have the identical inversion and is unverified — check it before treating it as a correct template for anything else.

Per the repo's Jira alignment convention, jira_epic lives here on the initiative README (not on the individual PRDs) so the manual per-AC sync is never accidentally triggered. Each PRD references its own Jira key(s) in its body.

Scope Changes

  • Backend — Contact Service billing-API rate limiting, CRM↔CDP field-property matching.
  • Frontend — Contact Service billing-API retry handling, Customer Properties modal styling, Edit Customer address payload shape.

(Anticipated surfaces — refined as real stories land; each story's PRD carries the subset it changes.)

Stories — per-story tracker (canonical)

This table is the canonical per-story home for the bucket. Each row is one self-contained user story, priced, classed, pulled and completed independently — the bucket is one container initiative (one Portfolio row, one Epic), but nothing here shares a fate. The bucket is classed, not ranked: it takes no ## Priority rank on the roadmap (a heterogeneous bucket can't be ordered by one integer, and an urgent adhoc can outrank a ranked initiative) — instead each story carries a Class of Service and the roadmap renders the bucket in its parallel ## Adhoc / Interrupt lane. It is append-only — the bucket grows by adding rows, never by restructuring the roadmap (see How the bucket grows). Full doctrine: .claude/reference/adhoc-interrupt-doctrine.md.

  • Story — stable identity A<n>, assigned in creation order and never reused/renumbered.
  • Class — per-story Class of Service: 🔴 Expedite (customer-/revenue-/security-facing — may preempt ranked work, WIP-limited + logged in ## Expedite log) · 📅 Fixed-Date (hard external date) · 🟡 Standard (normal pull-in fill) · ⚪ Intangible (cosmetic / cleanup, slack only).
  • Status — live completion: backlogin-progressin-reviewdone. The roadmap forecast row's % done is the rollup done ÷ total of this column.
  • BE · FE · QA · Mobile — canonical per-story staffing, one column per discipline; = that discipline isn't in the story's Scope.
  • Effort is deliberately unsized (captures-never-estimates).
StoryClassStatusAddedScopeBEFEQAMobileJira StorySummary (→ PRD)
A1⚪ Intangiblebacklog2026-07-03FrontendZhelia AlifaHendryTF-3513 (Task: TF-3478)Fix padding on Create/Edit Customer Properties modal (Step 1 32px → 32px 142px, matches Figma) → prd
A2🔴 Expeditedone2026-07-06Backend, FrontendGhoziJoviHendryTF-3514 (Tasks: TF-3483, TF-3484)Fix duplicate billing deduction/refund: remove naive FE retry-on-5xx (TF-3483) + add BE rate limiter (TF-3484) on Contact Service billing APIs — P0 incident, one root cause split FE/BE → prd
A3🟡 Standarddone2026-07-06BackendJulio JefferHendryTF-3515 (Task: TF-3486)Normalize CDP field name (snake_case, trailing-underscore trim) before CRM↔CDP field-property matching, fixing false-negative duplicate-field creation → prd
A4🟡 Standardin-review2026-07-10FrontendJoviHendryTF-3516 (Task: TF-3505)Send empty-string (not stringified "null") address subfields on Edit Customer when the initial address is null → prd
A5🟡 Standardin-review2026-07-22FrontendZhelia AlifaHendryTF-3608 (Task: TF-3479)Show remaining custom-field quota on the layout menu (design confirmed, PR merged — see PRD) → prd
A6🔴 Expedite (classified 2026-07-21 per sprint-planning direction — justification pending, no urgency evidence documented; see RFC)backlog2026-07-21BackendGhoziHendryTF-3609Chat's Sticky Agents feature needs CDP support for set/remove assignment actions — intake placeholder, raised at Sprint 2 planning with no further detail yet; Scope is provisional (Backend-only assumed) and, like the classification, still to be confirmed with the Chat/Omnichannel squad. Upstream: Chat Epic QC-22880 + Design PXL-9354 (August 2026 target, UX done) — see RFC. Re-homed here 2026-07-27 from engineering-q3-2026 (was its A10) → rfc

Reconciliation notes (2026-07-26 pass-03):

  • A5 remains in-review, matching TF-3479's observed board state. The outstanding Zhelia owner-confirmation is independent of completion status and does not move the row back to backlog.
  • TF-3568 (Toast shown on bottom) is a board-Done FE bug assigned to Jovi but has no merged-code trace in the registered repositories. It receives no completion credit in this bucket until a merge is cited or Jira is corrected. It also has no canonical A<n> tracker row; the DRI must classify it and run the bucket-growth checklist before it can affect the rollup.

Flags on the table above (not encoded in the cells, so they don't corrupt the linter's parse):

  • A1's FE owner is Zhelia Alifa (CDP's PM/DRI, also this Epic's reporter) rather than a roster-listed FE engineer. Possibly a self-filed quick fix or a placeholder assignment — confirm the real implementor before this story is pulled off backlog.
  • A5's FE owner is Zhelia Alifa (matching the Jira Task's current assignee) — same caveat as A1: she's CDP's PM/DRI, not a roster-listed FE engineer. Confirm the real implementor before this story is pulled off backlog.
  • A2 is done on the board for both halves, but only TF-3483 (FE) is code-corroborated — merged in qontak-customer-fe PR #453. TF-3484 (BE) has no merged-code trace in any of the 6 CDP repos as of the 2026-07-14 code-evidence.mjs check — a code-evidence-gap not yet routed anywhere else. Flagged for DRI confirmation (see the PRD's Verification section) rather than silently trusted; this bucket carries no man-days, so the gap doesn't misstate progress, but the BE mitigation for a P0 billing incident being unconfirmed in code is worth a real look.

Progress rollup: 2 of 6 done (33%) as of 2026-07-27 — the count of Status: done rows over total rows. This is the single number mirrored to the roadmap ## Portfolio progress & forecast row; it grows/shrinks as rows are added and Statuses move, with no roadmap edit required beyond refreshing that one derived cell. A4 and A5 are in-review; A6 is backlog (re-homed 2026-07-27, unscoped).

Owner rollup (for the mirrors): BE — Ghozi (A2, A6), Julio Jeffer (A3); FE — Jovi (A2, A4), Zhelia Alifa (A1, A5 — flagged; see below); QA — Hendry (all six, Lane B).

Expedite log

Append-only record of the bucket's 🔴 Expedite classifications. Classifying a story Expedite is free; the act of pulling one in flight (in-progress/in-review) — where preemption actually happens — must have a row here (linter BUCKET_EXPEDITE_UNJUSTIFIED). No expedite_wip_limit is set yet (uncapped, check skipped) — see the frontmatter note.

StoryDateAuthorized byPreemptsReason
A22026-07-06Zhelia Alifa (inferred — Epic reporter; no explicit authorization recorded in Jira)— (backfilled, pulled before this tracker existed)Customer-/revenue-facing: a P0 incident causing duplicate billing deduction/refund on Contact Service calls. Classed 🔴 Expedite reflecting the real urgency (Highest-P0 in Jira) of work that was already pulled and completed (2026-07-09/07-10) before this bucket was documented — this is a backfill record, not a fresh preemption event. PM/TPM should confirm the authorization and whether any ranked CDP initiative's queue was actually displaced that week (no status/ note exists for one, suggesting it was likely worked as gap-fill rather than a true preemption — unconfirmed).

Pull rule (deterministic — how an adhoc gets scheduled)

A bucket takes no ## Priority rank — it holds stories of incompatible urgency (a 🔴 Expedite billing incident beside a ⚪ Intangible padding fix), so no single integer can order them. Handling is a per-story pull rule, run off data already captured above (Class / Scope / owner) × capacity.md load × the sprint queue's blocked flags: a story is pulled when the owner's ranked (P1…Pn) queue is blocked or between items — unless it is 🔴 Expedite, which may interrupt ranked work (once expedite_wip_limit is set + logged above). 🟡 Standard / ⚪ Intangible never run ahead of ranked work; 📅 Fixed-Date interrupts only as its date nears. Among eligible stories the pull order is Class → closeability (can it reach done this window with current staffing) → domain affinity. Generic contract: .claude/reference/adhoc-interrupt-doctrine.md.

How the bucket grows (adding a new adhoc)

The bucket absorbs new adhoc requests mid-quarter without touching the roadmap ## Priority ranks. To add one:

  1. Author the PRD under prds/ (lightweight is fine — a single self-contained user story with a Section-8 story table), or an RFC under rfcs/ if the item is an engineering intake from another squad rather than a PM-authored product story.
  2. Append a tracker row above with the next free Story id (A7, A8, …), its Class, per the doctrine, Status: backlog, today's Added date, Scope, discipline owners, Jira key, and summary linking the PRD.
  3. Mint the Jira Story under Epic TF-3477 (one Story per item, never per-AC — use jira-alignment-check), and mirror its key into the row — same pattern as A1-A4 (TF-3513–3516).
  4. Mirror staffing into the roadmap Implementors/QA (union), capacity.md Allocation (adhoc-q3-2026 (DISC) TBD — no man-days), and, if worked this sprint, the sprint queue. If it's 🔴 Expedite and pulled in flight, set/respect expedite_wip_limit, add an ## Expedite log row, and, if it displaces ranked work, a note in that initiative's dated delivery/status/.
  5. Refresh the rollups — the tracker's Progress line (done ÷ total), the roadmap forecast % done cell, and the roadmap ## Adhoc / Interrupt lane class buckets. The bucket's lane row, Portfolio row and Epic do not change — that stability under growth is the point.

What you never do: give a new item its own roadmap ## Priority rank, or split the bucket into multiple Epics.

QA Lane

Lane B (keeps a human QA gate) — advisory, as of 2026-07-14.

  • Basis: money-critical. A2 fixes a P0 duplicate billing deduction/refund incident — a textbook Lane-B trigger (a silent failure reaches paying customers' invoices directly). Every other CDP initiative is Lane B as team policy regardless.
  • Owner: Zhelia Alifa (PM). Scope: each item's PRD Section-8 ACs; QA runs per-story as each is pulled.
  • Set as the conservative default without a full qa-lane-advisor pass. A1 (cosmetic padding fix) is the one genuinely low-risk item here and could warrant a lighter gate — re-confirm with qa-lane-advisor if the bucket grows enough to justify per-story QA-lane splitting.