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 identityA<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:backlog→in-progress→in-review→done. The roadmap forecast row's% doneis the rollupdone ÷ totalof this column.BE·FE·QA·Mobile— canonical per-story staffing, one column per discipline;—= that discipline isn't in the story'sScope.- Effort is deliberately unsized (captures-never-estimates).
| Story | Class | Status | Added | Scope | BE | FE | QA | Mobile | Jira Story | Summary (→ PRD) |
|---|---|---|---|---|---|---|---|---|---|---|
| A1 | ⚪ Intangible | backlog | 2026-07-03 | Frontend | — | Zhelia Alifa | Hendry | — | TF-3513 (Task: TF-3478) | Fix padding on Create/Edit Customer Properties modal (Step 1 32px → 32px 142px, matches Figma) → prd |
| A2 | 🔴 Expedite | done | 2026-07-06 | Backend, Frontend | Ghozi | Jovi | Hendry | — | TF-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 | 🟡 Standard | done | 2026-07-06 | Backend | Julio Jeffer | — | Hendry | — | TF-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 | 🟡 Standard | in-review | 2026-07-10 | Frontend | — | Jovi | Hendry | — | TF-3516 (Task: TF-3505) | Send empty-string (not stringified "null") address subfields on Edit Customer when the initial address is null → prd |
| A5 | 🟡 Standard | in-review | 2026-07-22 | Frontend | — | Zhelia Alifa | Hendry | — | TF-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) | backlog | 2026-07-21 | Backend | Ghozi | — | Hendry | — | TF-3609 | Chat'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 canonicalA<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
doneon the board for both halves, but only TF-3483 (FE) is code-corroborated — merged inqontak-customer-fePR #453. TF-3484 (BE) has no merged-code trace in any of the 6 CDP repos as of the 2026-07-14code-evidence.mjscheck — acode-evidence-gapnot 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.
| Story | Date | Authorized by | Preempts | Reason |
|---|---|---|---|---|
| A2 | 2026-07-06 | Zhelia 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:
- Author the PRD under
prds/(lightweight is fine — a single self-contained user story with a Section-8 story table), or an RFC underrfcs/if the item is an engineering intake from another squad rather than a PM-authored product story. - Append a tracker row above with the next free
Storyid (A7,A8, …), itsClass, per the doctrine,Status: backlog, today'sAddeddate,Scope, discipline owners, Jira key, and summary linking the PRD. - 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). - Mirror staffing into the roadmap
Implementors/QA(union),capacity.mdAllocation(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/respectexpedite_wip_limit, add an## Expedite logrow, and, if it displaces ranked work, a note in that initiative's dateddelivery/status/. - Refresh the rollups — the tracker's Progress line (
done ÷ total), the roadmap forecast% donecell, and the roadmap## Adhoc / Interrupt laneclass 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-advisorpass. A1 (cosmetic padding fix) is the one genuinely low-risk item here and could warrant a lighter gate — re-confirm withqa-lane-advisorif the bucket grows enough to justify per-story QA-lane splitting.