Does AI write code faster? It does, and that is the boring part of the answer.
After building three production systems end to end with AI agents this year, a Malaysian HRMS, a maritime crew SaaS, and this portfolio's own delivery pipeline, the more interesting change is structural. AI does not just speed up one step of the lifecycle. It rearranges which step is the bottleneck, and it changes what "review" and "maintenance" mean.
Plan: the spec becomes the bottleneck
For CrewSync, a multi-tenant maritime crew management SaaS, the first artifact was not code. It was an Obsidian vault: one note per module, architecture and tech stack decided before a single line was written.
That written contract is what let agent sessions build against a real spec instead of improvising scope. The MVP foundation landed the next day: 196 files, roughly 24,000 lines, covering multi-tenant isolation, certificate expiry alerts, safe-manning checks, a Filament admin panel and a React self-service portal.
When an agent can generate a working module in minutes, the planning document stops being a formality you write to satisfy process. It becomes the actual bottleneck. The highest-leverage hour in the project is the one spent before any code exists.
Build: agents type, review gates every merge
hrmydeck, a Malaysian HRMS now in production pilot, is built end to end through agent sessions: implementation, fixes, deployment config and docs, on Laravel 12 with Filament and Postgres, a React employee web app and a React Native mobile app.
The commit trail carries AI co-author trailers on the majority of commits, so this is not a claim about vibes. It is checkable against the repo history.
What did not change: every merge still passes through human review. The agent proposes, runs the build and type checks, and a person decides what ships. "Built with AI agents" describes who typed the code, not who is accountable for it.
Review: AI finds real bugs, and sometimes the wrong fix
Before the pilot release, a gap-finder audit compared every API code path against its admin-panel equivalent.
It found money-touching bugs. The API's payroll calculation was silently missing claims reimbursement and unpaid-leave deductions that the admin panel applied, so two code paths computed different salaries for the same employee. It also caught API-created employees never receiving their welcome invite, and claim endpoints that were implemented but never meant to be exposed.
The audit also proposed a fix for a claim-approval deadlock, no approval possible when no approver was configured, by falling back to any manager-role user. Technically sound, organisationally wrong. Human review caught it and reverted it the same day:
revert: remove MANAGER role fallback in claim approval
CEO/COO approvers must be explicitly configured via CLAIM_APPROVER_*
env vars. The MANAGER fallback is not the intended approval chain.
The audit was worth running for the payroll bug alone. The revert is the actual point. Agents optimise for "no deadlock." Humans know which deadlocks are load-bearing. Review stops being "check the syntax" and becomes "check the judgment."
Test and harden: a sweep before every release
Separately from the behavioural audit, a pre-release authorization sweep went through the claims, payroll and leave-calendar paths specifically for scoping and access-control gaps.
Managers could mark other teams' claims as paid. Every employee could see the entire company's leave calendar regardless of role. Claim approver IDs were hardcoded rather than configurable. All fixed before the pilot went live.
Splitting this from code review matters. A functional audit asks "does this behave correctly." A hardening sweep asks "who is allowed to do this." Agents are good at running both exhaustively across every route, which is exactly the kind of sweep a human reviewer normally has to ration time against.
Deploy: green does not mean live
This portfolio's own auto-deploy pipeline froze silently, twice. Green builds, published images, and production simply stayed on the old version. No failing step anywhere pointed at it.
The fix was not a retry. It was making the pipeline prove itself: bake the commit SHA into the served HTML, then add a CI job that polls production until it reports that exact SHA.
verify-deploy:
needs: build
steps:
- run: |
for i in $(seq 1 20); do
live=$(curl -sf https://ariefrse.my/ \
| grep -o 'build-commit" content="[^"]*"')
[ "$live" = "$GITHUB_SHA" ] && exit 0
sleep 30
done
exit 1 # production never picked up this commit
On its first run the job failed, correctly. Watchtower had frozen again, and what used to be days of silently stale production became a red X within ten minutes of the push.
Any pipeline that can go quiet needs a step that asks the live system a question only a real deploy can answer correctly.
Maintain: regressions become context, not just fixes
A duplicate-ID seeder bug broke CI silently. No obvious cause, just red builds. The code fix was one line.
The durable fix was recording the failure where the next agent session would
actually read it, in the repo's own CLAUDE.md:
## Known CI Footguns: Never Re-introduce
1. Seeder dedup: always ->unique() on pluck('employeeId') in
MockDataSeeder: duplicate IDs will break seeding silently
2. Leave calendar scoping: non-approver roles (EMPLOYEE, FINANCE)
must only see their own leaves; global scoping breaks this
3. Staging Docker BuildKit cache is flaky, pre-existing, unrelated
to code changes
Agents forget between sessions. The repo does not. Maintenance stops being purely "fix the bug" and becomes "make the bug unrepeatable," which is context engineering rather than code review.
Phase by phase
| Phase | Before | With AI agents |
|---|---|---|
| Plan | Light spec, details resolved while coding | Spec is the build contract. Vague specs surface immediately as bad output |
| Build | Bottlenecked on typing and boilerplate | Bottlenecked on review bandwidth |
| Review | Check style and correctness | Check judgment: did the fix violate an unstated business rule |
| Test and harden | Time-rationed manual sweeps | Exhaustive route-by-route sweeps before every release |
| Deploy | Green build treated as proof of a live deploy | Pipeline verifies the live system, not its own exit code |
| Maintain | Tribal knowledge in one engineer's memory | Regressions written into agent context so they cannot recur silently |