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 (ciqualitymigratebuild). 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