Skip to content

fix(app-shared): parse date-only strings as calendar days - #8181

Merged
iscekic merged 7 commits into
mainfrom
drain/local-calendar-dates
Oct 27, 2026
Merged

iscekic merged 7 commits into
mainfrom
drain/local-calendar-dates

Conversation

@iscekic

@iscekic iscekic commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — the Security Agent audit report ran inside the Android dev client against the local stack on this machine at this head and shows the backend's date-only period end as its calendar day, with the emulator clock west of UTC and again east of it. The shared parser itself was exercised by the package suite, which resolves a YYYY-MM-DD value to that calendar day's local midnight in America/Los_Angeles, Asia/Tokyo, and UTC.

Change

  • packages/app-shared/src/utils.ts resolves a YYYY-MM-DD value to local midnight of that calendar day, so default local formatting shows that day. A date that does not exist in its month stays an invalid Date, so callers that check for one keep their fallback; four-digit years below 100 keep their year; a missing value stays an invalid Date.
  • apps/mobile/src/components/security-agent/audit-report-screen.tsx formats the report's date-only displayEnd with the existing formatCalendarDate helper, so the header and the empty state show the report's calendar day, while generated and event clocks keep formatUtcTimestamp.
  • packages/app-shared/src/utils.test.ts covers America/Los_Angeles, Asia/Tokyo, and UTC, a day that does not exist in its month, a four-digit year below 100, a missing value, and timestamp instants.
  • The audit-report mounted suites mock the formatter the header now calls.

Verification

Supporting checks at head 007c37b:

  • packages/app-shared, vitest run: 25 files, 530 tests passed; src/utils.test.ts: 8 tests passed.
  • packages/app-shared, tsgo --noEmit: clean.
  • apps/mobile, vitest run --project mobile-mounted src/components/security-agent/: 25 files, 299 tests passed.
  • apps/mobile, tsgo --noEmit: clean.
  • oxlint on the changed mobile files and oxfmt --check on every changed file: clean.

Android dev client against the local stack

Dev client com.kilocode.kiloapp on the emulator, Metro serving this checkout, Next.js on localhost:3000 over adb reverse, signed in to the local dev stack. The backend answers securityAgent.getAuditReport with a date-only period end:

"period": { "start": "2026-07-30T00:00:00.000Z", "endExclusive": "2026-10-28T00:00:00.000Z",
            "displayEnd": "2026-10-27", "timeZone": "UTC" }

With the emulator clock west of UTC, where the local calendar date was still the previous day, the accessibility dump of the report header reads:

text="7/30/2026 – 10/27/2026 · UTC"

With the emulator clock east of UTC, where the local calendar date was already the next day, the same dump reads:

text="7/30/2026 – 10/27/2026 · UTC"
text="Generated 10/27/2026, 12:03 PM UTC"

The date-only period end renders the report's calendar day in both device zones; the generated clock keeps its instant. The screenshot below is the eastern-zone capture of that screen.

Parser behavior in the package suite

The same parser is exercised under three time zone settings in packages/app-shared/src/utils.test.ts, at the head that CI runs:

America/Los_Angeles  2026-09-26 -> local hour 0, renders 9/26/2026
Asia/Tokyo           2026-09-26 -> local hour 0, renders 9/26/2026
UTC                  2026-09-26 -> local hour 0
2026-02-30 and 2026-13-01 -> Invalid Date
2026-03-16 15:21:40.957+00 -> the same instant in Los Angeles and Tokyo

Limitation: no product screen feeds a date-only backend value through the shared parser and then formats it in the device zone, so the parser's zone behavior is proven by the package suite rather than through a screen. The audit report carries the only date-only field on a mobile screen, and the device run above exercises that screen.

Production prerequisites

None.

Proxy answers

The owner's proxy gave these answers in the owner's place.

  1. Question: Parser semantics: For a date-only input like 2026-09-26, what should the shared parseTimestamp return?
    Answer: Local-midnight calendar Date
    Confidence: 0.75 · Precedent: Fix the root cause and the class of the issue: "fix class of issue preventing progress" (7f3470e0ba6f). The work item also asks for a local-midnight Date.
  2. Question: Invalid dates: When a date-only string names a day that does not exist (e.g. 2026-02-30), what should parseTimestamp do?
    Answer: Preserve Invalid Date (Recommended)
    Confidence: 0.80 · Precedent: Fix the root cause on every affected surface (session 7f3470e0ba6f: "fix class of issue preventing progress"). Keeping Invalid Date leaves existing caller fallbacks working and avoids silently showing the wrong day.

@iscekic iscekic added drain Work item from the findings drain janitor:trust Janitor finding: trust boundary hardening labels Oct 19, 2026
Comment thread packages/app-shared/src/utils.ts Resolved
Comment thread packages/app-shared/src/utils.test.ts Resolved
@kilo-code-bot

kilo-code-bot Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit adds the formatCalendarDate mock to the audit-report evidence suite, matching the formatter the screen now calls, and the net PR diff keeps the parser and both mobile test mocks consistent. No memory-leak risk: the change adds no listeners, timers, subscriptions, or retained caches.

Assumptions: [INFERENCE] none. The main merge in d687836a6 contributes no PR-scoped changes; review focused on the net PR diff against 0d5416bd8.

Files Reviewed (6 files)
  • packages/app-shared/src/utils.ts
  • packages/app-shared/src/utils.test.ts
  • apps/mobile/src/components/security-agent/audit-report-screen.tsx
  • apps/mobile/src/components/security-agent/audit-report-screen.mounted.test.tsx
  • apps/mobile/src/components/security-agent/audit-report-screen-evidence.mounted.test.tsx
  • apps/mobile/src/components/security-agent/audit-report-screen-timestamps.mounted.test.tsx
Previous Review Summaries (2 snapshots, latest commit d8978a0)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit d8978a0)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit resolves both prior findings: parseTimestamp now preserves four-digit years below 100 via setFullYear, and the timezone tests assert the resulting UTC instant, so they would fail if the zone stub stopped applying. The new Date(0)/setFullYear/setHours sequence still yields local midnight, and the month/day guard still rejects non-existent days such as 2026-02-30 and 2026-13-01. No memory-leak risk introduced: the change adds no listeners, timers, subscriptions, or retained caches.

Files Reviewed (2 files in this increment)
  • packages/app-shared/src/utils.ts
  • packages/app-shared/src/utils.test.ts

Previous review (commit 07f807f)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The date-only parsing change is sound for the mobile surfaces that consume it, but the parser loses leading-zero years and the new timezone tests cannot prove that the zone stub actually applies.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/app-shared/src/utils.ts 18 new Date(year, ...) maps years 0-99 to 1900-1999, so 0099-01-01 no longer parses as year 0099; the month/day guard does not catch it.
packages/app-shared/src/utils.test.ts 22 The "west/east of UTC" tests read back through local getters, so they pass even if vi.stubEnv('TZ', ...) has no effect; assert the resulting instant or offset instead.
Files Reviewed (4 files)
  • packages/app-shared/src/utils.ts - 1 issue
  • packages/app-shared/src/utils.test.ts - 1 issue
  • apps/mobile/src/components/security-agent/audit-report-screen.tsx - 0 issues
  • apps/mobile/src/components/security-agent/audit-report-screen.mounted.test.tsx - 0 issues

No memory-leak risk introduced: the change adds no listeners, timers, subscriptions, or retained caches.

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 63.7K · Output: 9.9K · Cached: 590K

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic enabled auto-merge October 19, 2026 23:25
@iscekic iscekic added the merge:human Substantive functional risk requires human review. label Oct 19, 2026
@iscekic
iscekic disabled auto-merge October 20, 2026 19:13
@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change and removed merge:blocked labels Oct 21, 2026
@iscekic iscekic removed merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. labels Oct 22, 2026
@iscekic

iscekic commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android emulator capture of the Security Agent audit report. The period and generated lines render the report's calendar days with its UTC marker. Test data only.

Audit report header

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. intent:ok Janitor change confirmed as a real bug fix, not intended behavior labels Oct 22, 2026
…dates

# Conflicts:
#	apps/mobile/src/components/security-agent/audit-report-screen.tsx
@iscekic iscekic removed merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:blocked:insufficient-e2e Verification does not cover the change labels Oct 23, 2026
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android emulator run against local services displayed the audit report period and generated time with the UTC marker. The screen used a single owned fake-account fixture.

Audit report period and UTC marker

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Oct 23, 2026
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android emulator run against the local dev stack. The Security Agent audit report renders its period with the UTC marker while the emulator clock is set outside UTC: the device reads Sat Oct 24 (+14), and the period end still renders 10/23/2026, the report's own calendar day. The generated stamp renders 10/23/2026, 10:39 PM UTC from the same run.

Assertion from the accessibility dump captured with the screenshot:

Audit report
E2E Calendar
7/26/2026 – 10/23/2026 · UTC
Generated 10/23/2026, 10:39 PM UTC
1 Findings  1 Events  0 Critical  1 High
Prototype pollution in left-pad

Single owned fake-account fixture, local Postgres and local Next.js; no production services in the path.

Audit report period rendered with the UTC marker

Audit report period rendered with the UTC marker

@iscekic

iscekic commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android dev client from this branch against the local stack, signed in to a local test account, on the Security Agent audit report with one seeded finding and one event for that account.

Two captures of the same view with the emulator clock set through two zones, taken after a relaunch in each. The visible lines were asserted from a uiautomator dump taken in the same command as each capture; this environment has no OCR pass, so the dump is the assertion and the images show the same viewport.

Commands used, abbreviated: adb shell service call alarm 3 s16 <zone>, adb shell am force-stop, adb exec-out uiautomator dump /dev/tty, adb exec-out screencap -p.

Audit report period line, first device zone

Audit report period line, second device zone

@iscekic iscekic removed the merge:blocked:insufficient-e2e Verification does not cover the change label Oct 24, 2026
@iscekic
iscekic enabled auto-merge October 24, 2026 14:57

@eshurakov eshurakov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shallow review: no critical issues found.

…dates

# Conflicts:
#	packages/app-shared/src/utils.test.ts
#	packages/app-shared/src/utils.ts
@iscekic
iscekic disabled auto-merge October 27, 2026 11:07
@iscekic iscekic removed the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Oct 27, 2026
@iscekic

iscekic commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Verified on the Android dev client against the local dev stack at head 007c37b. The Security Agent audit report shows the report period and the generated time; the accessibility dump reads 7/30/2026 – 10/27/2026 · UTC.

The shared parser is covered by packages/app-shared/src/utils.test.ts under America/Los_Angeles, Asia/Tokyo, and UTC, for a day that does not exist in its month, and for a four-digit year below 100.

Audit report header showing the report period and generated time

@iscekic iscekic added the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Oct 27, 2026
@iscekic
iscekic added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit f12a9d8 Oct 27, 2026
84 checks passed
@iscekic
iscekic deleted the drain/local-calendar-dates branch October 27, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain intent:ok Janitor change confirmed as a real bug fix, not intended behavior janitor:trust Janitor finding: trust boundary hardening merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants