Inspiration

Software that elderly people depend on breaks in small, dangerous ways: a button too small for a shaking hand, one English word on a Punjabi screen, a page too slow for a ₹6,000 phone on 3G. Humans miss these in review because they are not the user.

So we asked: what if the users themselves were in the gates? And what if everything after the code (planning, review, security, release, monitoring, learning) ran hands-off on the GitLab Duo Agent Platform?

What it does

GrandOps ships a small medicine-reminder app for elderly patients and caregivers in India (English, हिन्दी, ਪੰਜਾਬੀ). The app is deliberately simple; the delivery loop around it is the product.

  • Nine custom Duo flows cover the lifecycle:
    • Triage plans the issue and sets a risk tier.
    • Builder is a supervisor with developer, tester and persona-fixer sub-agents. It opens the merge request.
    • Elder-care Reviewer reviews it, and a second independent reviewer joins on tier 2.
    • Sentinel covers security, Herald writes EN/HI/PA release notes, Scribe records lessons in AGENTS.md, Green Steward works on carbon, and Chaos and Healer handle resilience.
  • Five synthetic grandparents gate every merge and every deploy. Each is a Playwright suite, run again against the live site:
    • Kamla (tremor): every target at least 48 px, spaced at least 8 px apart
    • Harbans (low vision): text at least 18 px, contrast at least 7:1
    • Rano (Punjabi only): zero English on any screen
    • Mohan (screen reader): axe-core clean, full keyboard path
    • Bittu (₹6,000 phone on 3G): page visible within 3 s, JavaScript under 170 KB
  • Deterministic safety. Scripts decide, agents explain. The merge gate, canary SLO watch, rollback, chaos guard, PII scan and carbon gate are plain code with no LLM.

What happened in the real runs

  1. A caregiver's request was opened as an issue. Triage labelled it tier::2 and wrote acceptance criteria and a test plan for each persona.
  2. Builder opened the merge request on its own: code, translations in all three languages, unit and e2e tests.
  3. The Elder-care Reviewer and the second tier-2 reviewer both posted APPROVE. Sentinel reviewed the security findings, and Herald wrote release notes in three languages.
  4. Green Steward proposed a greener pipeline, and the reviewer blocked it, because it narrowed container scanning. Agents check agents.
  5. The pipeline deployed to Google Cloud Run (asia-south1), and the personas passed on the live site.
  6. The first production canary breached its p95 SLO, so the pipeline rolled it back automatically.

How we built it

  • App: Next.js (App Router) + TypeScript strict, next-intl, Firestore. "Dose taken" works without client JS. Atkinson Hyperlegible type. Each tablet is drawn in its real colour.
  • Dose logic: pure functions that store UTC and display IST, with 100% branch coverage and fast-check property tests.
  • CI/CD: GitLab CI with SAST, Secret Detection, Dependency and Container Scanning, an SBOM, JUnit reports, and a per-pipeline carbon report.
  • Agents: Duo Flow Registry v1 YAML, with least-privilege toolsets per flow and AGENTS.md as house rules. Verdicts are visible [autopilot:review … verdict=APPROVE] lines that the deterministic merge gate parses.
  • Cloud: Terraform/OpenTofu for Cloud Run (staging + prod), Artifact Registry, Firestore, Secret Manager, and keyless Workload Identity Federation from GitLab CI. Production gets a canary, an SLO watch, then promote or rollback.
  • Carbon: every pipeline computes its Software Carbon Intensity with the Green Software Foundation formula SCI = ((E × I) + M) / R (energy × grid intensity, plus embodied emissions, per unit of work).

Challenges

  • Cloud Run reserves URL paths ending in "z", so /healthz never reached the app. We moved the external checks to /health.
  • Geography distorted the gates. CI runners in the US are about 250 ms from Mumbai, which made Bittu and the canary fail for reasons real users in India never see. We now measure the runner's network round trip on Cloud Run's reserved /healthz (which never reaches the app) and subtract it: app time = probe time − network baseline. The budgets themselves never changed.
  • GitLab rejects HTML comments in flow prompts, so hidden verdict markers became visible ones.
  • Live data broke rules that local tests passed: a 25 px "MR" link, and an English issue title on a Punjabi page. The live persona run caught both before anything reached production.

What we learned

  • Agents are good at explaining and fixing; rules should decide.
  • Putting real users into the gates, as personas, changes what "done" means.
  • The most convincing evidence was the loop catching itself: a reviewer blocking another agent, and a canary rolling back production on its own.

Built With

  • axe-core
  • docker
  • fast-check
  • firestore
  • gitlab
  • gitlab-ci
  • gitlab-duo-agent-platform
  • gitlab-security-scanning
  • google-cloud-artifact-registry
  • google-cloud-run
  • google-secret-manager
  • green-software-sci
  • next-intl
  • next.js
  • node.js
  • opentofu
  • playwright
  • pnpm
  • react
  • syft
  • terraform
  • typescript
  • vitest
  • workload-identity-federation
Share this project:

Updates

Submission history