Round #142Score 4/5Transport: taxi

The missing deadline axis became a component across three modes

Route: /taxi-crew
Desktop preview
Mobile preview

Captured at a 375px viewport. Long pages scroll inside the frame.

The screenshots stay in Japanese. Every round is a real screen for a real Japanese industry, so an English re-render would no longer be the screen the agent actually produced.

Write-up

The missing deadline axis became a component across three modes

⁠Build log series⁠: I give an AI that has never seen Gunjo (@gunjo/ui) only the public npm package and the gunjo.jp docs, then ask it to build a real screen. ⁠This second staff-facing taxi round⁠ covered ⁠driver management, daily reports, and roll call⁠: breathalyzer checks, revenue breakdowns, hours on duty, and qualification expiry.

Result: 4/5, and the value-against-deadline axis triggered a build

The desktop-density screen passed tsc. The agent reported:

⁠This is the deepest React library for administrative work I have used.⁠ ActionQueue, AmountBreakdown, CoSign, DataTable, Meter, and StatGroup covered nearly the whole compliance console without structural hand-rolling, and cues beyond color came by default through icons, text, and screen-reader-only labels. ⁠But qualifications had nowhere to express expiry. It was the second hand-rolled area after the dispatch screen in .⁠

The core observation: ExpiryBadge reached three of three

⁠Airline crew qualifications introduced the gap in , and bus driver qualifications supplied the second case in .⁠ Here another agent hand-rolled a currencyState() classifier and badge wrapper for taxi commercial licenses, aptitude assessments, and medical exams. ⁠That was the third case across three modes.⁠ Each agent independently described the same missing behavior and API:

⁠The library does nothing for a date against a deadline.⁠ ReferenceValue only accepts numeric ranges, Meter covers numeric consumption against a limit, and Badge is just a pill. <Currency value={date} warnWithin={60} /> plus a pure currencyState(date) classifier mirrors ReferenceValue and flagValue. It is the third axis beside value against limit (Meter) and value against range (ReferenceValue): value against deadline. Every crew and compliance console has to hand-roll it.⁠

The catalog also worked honestly. It stated that no dedicated expiry component existed, so the agent did not search for one. Guidance added in and that dates do not belong in ReferenceValue, and that expiry should be assembled from ScheduleGrid and Badge (PR#384), protected three adopters from a false lead while the cases accumulated. ⁠Honest documentation became the counter that measured when to build.⁠

What I built: ExpiryBadge and classifyExpiry, the fourteenth component

<ExpiryBadge value="2026-07-20" today={today} warnWithinDays={60} />
const { state, days } = classifyExpiry("2026-07-20", { today, warnWithinDays: 60 })
// { state: "expiring", days: 22 }  // valid / expiring / expired / missing
  • Valid, expiring soon, expired, and missing appear as color-safe status chips with an icon and label, date, and days remaining or overdue.
  • The pure classifyExpiry function is the counterpart to flagValue in ReferenceValue. It is safe for server rendering and has no hooks. Supplying today is recommended for deterministic server output, with new Date() as the default.
  • I reversed the catalog guidance from "not provided" to "use ExpiryBadge for date-based expiry" and documented the Meter (capacity), ReferenceValue (range), and ExpiryBadge (deadline) set.
  • PR#394 verified all four states against a fixed date, including the date and remaining days, color-safe presentation, and no browser errors.

⁠What I built under src this round: ExpiryBadge, on its third case and as the fourteenth component. Issue #383 closed.⁠

What I took away: placing a gap on an axis turns building into confirmation

By I had already described ExpiryBadge as the missing third axis beside Meter and ReferenceValue. The third case did not require a fresh design. It confirmed and transcribed a specification that had matured:

  • The date and threshold API producing four states plus days remaining followed from the two existing components.
  • The pure classifyExpiry function mirrored flagValue.
  • The catalog's honest unsupported note counted three hand-rolled implementations.

⁠When a gap can be placed on an axis, its specification matures before the third case and the eventual build has little ambiguity.⁠ After Stringline matured over 30 rounds and StatusBoard was located by data structure, this became the third example of waiting as deliberate design work.

📊 Component scoreboard (⁠14 built⁠)

AmountBreakdown / ActionQueue / ListCard / Gantt-segments / SeatMap / LoyaltySummaryCard / RadioCard / FilterChips / PageHeader / Itinerary / TicketStub / Stringline / StatusBoard / ⁠ExpiryBadge⁠ In progress: BottomActionBar approaching three of three, StatusLevel at two of three, TransitItinerary legs at two of three, LineChip at two of three, and ThresholdGate.

📋 Mode progress

  • ✈️ Air and 🚆 rail: five staff + six passenger screens each ✅ / 🚌 Bus: two staff + three passenger screens
  • 🚕 ⁠Taxi: two staff screens (dispatch and driver management)⁠ / remaining passenger ride-hailing app

Next up: build log

  • A ⁠passenger-facing taxi app⁠ for ride requests, arrival estimates, fare estimates, the ride, and payment. It will test the mobile passenger foundation in a fourth mode and could supply another BottomActionBar case.

The run

The value-against-deadline axis settled across air, bus, and taxi. Once the gap was placed on an axis, the build became confirmation rather than invention.

This series is co-created with AI (Claude and Codex). A human designs the experiments, makes the calls, and fact-checks before publishing; the AI does the hands-on work and drafting.

Components from @gunjo/ui

The components this screen's source imports directly.

The code the agent actually wrote

Click a file to expand its source.

業界別「AI指示書パック」、先行登録を受付中です。