Inspiration

Coding agents have made adding code cheaper than ever, and nothing has made removing it cheaper. Every feature an agent ships is carried for good: built, scanned, patched, deployed and paid for in carbon. Pendo's 2019 report found 80% of features rarely or never used across 615 customers' products (vendor data). Unused features still ship in every image, and nobody owns the decision to remove them. Shelf Life makes the end of a feature's life as deliberate as its birth.

What it does

Shelf Life runs the whole life of the features in a real application: Uptime Kuma 2.5.6 (MIT), imported into GitLab (Path B, Supervised) and deployed on Google Cloud Run.

  1. Birth. The Registrar flow (trigger: MR created) commits a birth certificate for every new feature: owner, purpose, a testable hypothesis and a sunset date. CI refuses features without one. 148 are registered.
  2. Evidence. Every night CI takes a census of the live app (counts only), prices each feature in image megabytes and known vulnerabilities, and asks GitLab Orbit what removing it would touch. A second physician, Jev, gives typed verdicts with probabilities, with Gemini as the fallback.
  3. A sealed, blind death certificate. A person files a census and sets the policy. The Coroner (Claude, through GitLab Duo) decides without any tool that could reach the second opinion, and its verdict is sealed on the census before a deterministic step opens that opinion. The Reconciler marks a certificate signable only when both agree.
  4. Signature. One person approves in the session. The Undertaker opens a Hospice: MR.
  5. Hospice. Agents never merge. The deterministic sexton CI jobs merge after a green pipeline and switch the feature off with GitLab feature flags. In the app a retired feature shows a tombstone with Ask for it back; over HTTP it answers with RFC 9745 Deprecation and RFC 8594 Sunset headers.
  6. Burial. After quiet days the sexton buries it: the next image leaves it out, and a GitLab Release publishes its obituary.
  7. Resurrection. Lazarus brings any feature back on request, with a new sunset, and records which evidence missed that person.

The Necropolis (GitLab Pages) tells each feature's life story and publishes every agent session in full, because GitLab shows session pages only to project members.

Real run, real objects

  • Two censuses were refused by the agents themselves: too little evidence, then a second physician that was only 93% sure.
  • The third retired three units: Hospice !20 (merged by the sexton), Burial !22 two quiet days later, an obituary release, and an image about 100 MB and 94 known vulnerabilities lighter. Resurrection request #8 brought one back through Lazarus's !25, 10 minutes from request to running.
  • A fourth census, sealed: the public transcript proves the verdict was posted at 15:23:54 and the second opinion opened at 15:23:55, and the sealed note is byte-identical (SHA-256) to what the agent posted.
  • Live on Google Cloud: a GitLab runner calls the live service and gets Deprecation and Sunset headers from server: Google Frontend (pipeline).
  • All nine DevSecOps stages, each with a real run: STAGES.md.

Path B: what we added

Everything below is new work in the submission period, on top of Uptime Kuma 2.5.6:

  • the lifecycle registry and its CI check; the Registrar and Coroner/Undertaker/Lazarus flows and a chat agent in the AI Catalog;
  • the nightly census, evidence, Orbit burial plans and second physician; the sexton CI jobs (merge, flags, watch, bury) and obituary releases;
  • in the app: a Shelf Life page, tombstones in the monitor editor, Deprecation/Sunset headers, feature-flag off switches, and a new GitLab Incident notification provider;
  • the Necropolis on GitLab Pages, a GLQL wiki dashboard, the SCI carbon ledger, and the Google Cloud deployment (OpenTofu, Cloud Run, Cloud SQL, Workload Identity Federation).

Sustainability (environmental opt-in)

Shelf Life measures itself with the Green Software Foundation's SCI (ISO/IEC 21031:2024), R = 1,000 monitor checks. The ledger runs in CI, nets out the agents' own footprint and Shelf Life's own CI, reports low/central/high ranges, and is reproduced to the last digit by the GSF Impact Framework (shelf-life/sci).

Quantified gain (current ledger, central values):

  • SCI per 1,000 checks: 3.21 → 2.59 g (−19%) in steady state; 3.76 → 2.76 g (−27%) while rebuilding six times a day.
  • Net of the agents and of Shelf Life's own CI: +3.59 g CO₂e a day (range −0.3 to +14.4; we publish the negative end).
  • The agents' measured spend so far: 77 g (95 Duo LLM calls in 39 sessions, 324 Jev calls), repaid in 21.5 days.
  • The lean image is 1,730 → 544 MB with 1,745 → 375 known vulnerabilities. For scale: Uptime Kuma's image has been pulled 196 million times, and every pull of a lean image moves about 0.4 GB less (compressed).

Model optimization

  • Every flow starts with a one-word gate on Duo's small model; 35 of 42 sessions stopped there for unrelated work items and MRs.
  • Evidence fetching and posting the seal are deterministic steps, not LLM calls; the Coroner sees a pre-ranked shortlist, not all 148 features.
  • The second physician answers 9 units per call (25 units in 3 calls), and unchanged evidence is never re-asked: last verdicts are carried forward.

Pipeline optimization

  • The first ledger showed Shelf Life cost more than it saved, so we retired our own waste: an hourly schedule (about 21 g a day) is gone; one nightly pipeline remains and never rebuilds, rescans or moves the image.
  • Component measurements run only when the image recipe changes; registry-only lifecycle MRs skip the container test suite; jobs are interruptible and layers are cached in the registry.

Energy-efficient architecture

  • Retired the Cloud SQL Auth Proxy sidecar (5.41 g a day, −20% of the footprint).
  • Burial removes unused system components from the image itself, so they are never built, scanned, stored or pulled again.
  • Runs in europe-north1 (29.84 g/kWh, location-based; renewable purchases not subtracted). Right-sizing memory to 512 MiB (126 MiB measured) is computed but not applied.

How we built it

  • Agents and flows: GitLab Duo Agent Platform custom flows from the AI Catalog, with agents, deterministic steps, a human-input gate and routers; triggers on MR created and work item created; a chat agent.
  • GitLab: Orbit (knowledge graph) queries; CI/CD across nine stages; SAST, Secret Detection, Dependency and Container Scanning; Container Registry, feature flags (Unleash API), environments, Releases, Pages, wiki GLQL, incidents and CODEOWNERS.
  • Infrastructure: OpenTofu with GitLab-managed state, and Workload Identity Federation into Google Cloud (Cloud Run, Cloud SQL, Artifact Registry, Secret Manager), so no keys are stored.

Challenges we ran into

  • The first nightly pipeline never ran: a changes: rule is always true on schedules.
  • A Docker Hub outage blocked a registry-only MR, so lifecycle MRs now skip upstream's container tests, and the sexton refuses any such MR that touches another file.
  • The first burial revived a buried monitor type by switching its flag off; it was fixed the same day.
  • Jev hit its free usage limit, so verdicts now survive outages and a fallback physician takes over; Google retired the Gemini model mid-hackathon, so the job now picks the newest Flash model.

Accomplishments that we're proud of

  • The system said no twice before it retired anything.
  • Independence is structural, not a prompt instruction: the Coroner has no tool that could reach the second opinion, and the seal is provable from a public transcript.
  • Every number in the submission comes from a GitLab object or a CI job, including the ones that don't flatter us.

What we learned

Two independent physicians plus one human signature is slow on purpose. Making independence structural (no tool, a sealed verdict) rather than a prompt instruction is what makes the "no" trustworthy. And measuring our own carbon honestly changed what we built.

What's next for Shelf Life

  • Longer observation windows (14 days or more) and censuses across many deployments.
  • Removing monitor types' npm dependencies at burial, guided by the Orbit burial plan.
  • Packaging the flows and sexton so any GitLab project can adopt them (docs/ADOPT.md).

Built With

  • claude
  • cloud-sql
  • gemini
  • gitlab
  • gitlab-ci
  • gitlab-duo-agent-platform
  • gitlab-feature-flags
  • gitlab-orbit
  • gitlab-pages
  • google-cloud-run
  • green-software-foundation-impact-framework
  • jev
  • node.js
  • opentofu
  • uptime-kuma
  • vue
Share this project:

Updates

Submission history