Output Summary

Sprint 4 Week 1 (May 7 to 13) numbers:

MetricCount
MRs authored & merged12
MRs reviewed (substantive)2
Direct main commits10
Domains covered4 (mr-bot service, infra/CI, security/deps, RBAC)
Branches with SIRA ticket prefix12 of 12
Force-pushes to main0
Merges with conflicts at squash time0

The week was dominated by sira-mr-bot (eight MRs) but also covered a security response (SIRA-365, pin all deps after the TanStack Snyk incident), a quality-gate addition (SIRA-353, React Doctor), an RBAC expansion (SIRA-364), and ten direct-main commits for infra/dev tooling.

The Twelve MRs

!275  SIRA-354 feat(mr-bot): replace CI-status card with MR-content card
!276  SIRA-355 fix(mr-bot): edge-case hardening
!286  SIRA-356 fix(mr-bot,infra): deploy without sudo and route via sira-api nginx
!288  SIRA-356 fix(ci): make mr-bot:deploy self-sufficient and inject env vars
!292  SIRA-361 feat(mr-bot): put author ping inside the embed Author field
!293  SIRA-362 feat(mr-bot): drop merge follow-up ping + recover from deleted cards
!294       fix(mr-bot): restore floating @ping above the embed
!295  SIRA-353 feat(web): add React Doctor scan in CI quality stage
!296       feat(mr-bot): enforce plain-paragraph summary format
!299  SIRA-365 chore(deps): pin all deps + add 24h install cooldown
!300  SIRA-364 feat(api): RBAC expansion & hardening (BE + docs)
!303  SIRA-366 chore(web): improve React Doctor score

Every branch follows <user>/<type>/<SIRA-XX>-<topic> or, for non-ticket cleanup work, <user>/<topic>. Every merge was squash-merge. The complete list is verifiable at the filtered GitLab view.

GitLab merge request list filtered to author Daffa Abhipraya, deployed between 2026-05-07 and 2026-05-14, showing all 12 merged MRs from SIRA-366 down to SIRA-354 with green Merged badges and zero-conflict checklists

Direct Main Commits: Scoped to Infra and Tooling

The project AGENTS.md gives the product owner permission to push directly to main, but only for “non-feature, non-prod-codebase changes.” Ten such commits this week:

5a2bd625 docs: refresh AGENTS.md across root, apps/api, apps/web
cca07ae1 refactor(infra): rename superset-* to wt-* across SIRA
e2b63141 chore(infra): remove conductor + superset GUI configs (wt is canonical)
a4f0c61e fix(ci): pin supabase CLI version to prevent postgres image tag drift
99aab08b feat(scripts): name superset containers after worktree
8d865ef6 feat(scripts): align superset port allocation with wt slot offsets
e6a67589 chore: lower pre-push process priority
458e1324 chore: cap pre-push test workers
66e6d4d5 chore(tooling): drop supabase/sonarqube MCP and allow main pushes
1da5d418 chore(wt): add .wt/config.toml for universal worktree CLI

None touch product code. All are documentation, dev-tooling, infra config, or CI fixes. The CI fix in a4f0c61e (pin supabase CLI to mitigate a postgres image tag drift bug) is the most consequential; it unblocked every subsequent integration-test job. Putting it through an MR would have delayed the fix by a CI cycle for zero review value, so direct-to-main was the right call.

The rule I follow: if a teammate could plausibly object to the change AND it touches code that runs in production, it goes through an MR even if I’m the PO. If it only touches dev-tooling or fixes a CI bug that’s actively blocking the team, direct main is faster and equally safe (the next CI run is the verification).

The Discord Ping Placement Saga: Four Iterations, Discipline Held

The mr-bot’s Discord card has an @author ping. Where does the ping go? This single design question went through four iterations across MRs !275, !292, !293, !294, and !296. The pre-squash commits tell the story:

  1. !275 original: ping in the message content field, floating above the embed. (Standard Discord pattern; the @ rendering and notification both work.)
  2. !292 SIRA-361: move ping inside the embed Author field. Rationale: tidier visual layout.
  3. !293 SIRA-362: realized embedded pings don’t notify the user. The notification is what the team actually needs; visual tidiness is secondary. Revert: 75b187ca revert(mr-bot): put author ping back in content above embed.
  4. !294: floating ping wasn’t quite right either; rendering placement broke when the message was edited. Restore the floating ping with an explicit @-string format that survives edits.
  5. !296: separately, enforce the Gemini summary as a single plain paragraph; the bot was occasionally returning Markdown lists that broke the embed.

Four iterations on what looks like a small detail. The discipline part: every iteration went through a proper MR with a clear title (feat, fix, or revert), CI passed before merge, and the revert was a real revert commit (not a force-push that erased history). The two reverts (75b187ca, 37ebf290) are still in the pre-squash history if anyone wants to audit how we got to the current ping placement.

The lesson is not “I made a wrong decision and walked it back.” Reverting four times because the constraints became clearer one bug at a time is normal product work. The lesson is every walk-back went through the same merge pipeline as the original; nothing was hidden by a force-push, nothing skipped CI, nothing got merged with [WIP] in the title.

Branch Hygiene

All 12 branches were named with the SIRA ticket prefix where applicable:

  • abhip/feat/SIRA-364-rbac-expansion-hardening
  • abhip/feat/SIRA-365-pin-deps-cooldown
  • abhip/react-doctor (no ticket, exploratory work that later got SIRA-353)
  • abhip/mr-notif-cleanup (the mr-bot rebuild, with SIRA-354 in commit messages)

None of the branches outlived their MR. should_remove_source_branch=true was set on every merge, so the branches were auto-deleted on squash. No stale abhip/* branches in the remote at end of week.

CI Discipline

Every one of the 12 MRs went through the full CI pipeline (ci → quality → migrate → build). The quality stage includes SonarQube (with the 85% new-code coverage threshold), security:sast, react-doctor, schema-test, and BDD. Of those:

  • Zero MRs merged with red SonarQube (the 85% gate blocked one early attempt; I fixed the coverage gap and re-pushed).
  • The mr-bot MRs all passed the mutation:python job (the mr-bot service has its own pytest config and was wired into the mutation suite from day one).
  • Two MRs (!288, !286) had to retry their deploy job because of a containerd ingest race on Nashta. Both retried clean on the second attempt.

No MR was merged with merge_when_pipeline_succeeds=true while the pipeline was actively red. Everything that merged had a green pipeline at the time of the squash.

What I Learned

Two patterns from the week worth keeping:

Direct main is a privilege scoped to infrastructure, not a workflow shortcut. Ten direct commits felt like a lot until I went back and checked what each touched. None of them are product behavior; all are dev tooling or CI fixes. The discipline isn’t “never push to main”; it’s “every push to main has to pass the test ‘would a teammate object?’ applied honestly.”

Walk-backs are normal, but they have to be transparent. The Discord ping went through four iterations because the constraints (Discord’s notification semantics, embed render behavior, edit-survivability) only became clear as users hit them. The work isn’t about getting it right the first time; it’s about every iteration being visible in the git history. Two real revert(mr-bot): commits are better than one rewritten history that pretends I knew the answer all along.

Evidence