Commit Graph
5 Commits
Author SHA1 Message Date
weishu 96d81a3f12 merge: B-M2b Android session/machine stores + session list
# Conflicts:
#	android/app/build.gradle.kts
2026-08-17 15:48:09 +08:00
weishu f702cbf844 feat(android): session/machine stores + session list (B-M2b)
:core:protocol — summary-side patch path ported from the web reference:
- wire/SummaryPatching.kt: patchSessionSummary port with the summary path's
  >= versioned gates (replicated web divergence vs the detail path's strict >,
  documented), derived-field recompute (pendingRequestsCount/Kinds/Requests
  capped 5, todoProgress), render-irrelevance filter (activeAt-only keep-alive
  suppression), toSessionSummary/toSessionSummaryMetadata projection, and the
  deprecated canApplyVersionedSummaryPatch legacy gate.
- wire/SessionSorting.kt: exact sortSessionSummaries comparator
  (globalPinned > pinned > active > pendingRequestsCount among active >
  updatedAt desc; Long-safe, stable).
- SessionMetadata grows the per-flavor agent session id fields the
  agentSessionId projection needs.

:core:data store/ — StateFlow stores with per-hub JSON snapshots:
- JsonSnapshotStore: debounced (500 ms) atomic tmp+fsync+rename snapshots,
  synchronous cold-start load, corrupt files degrade to null.
- SessionStore: sorted summary list + per-id detail cache (strict-> detail
  patching via SessionPatching), full-session upsert preserving hub-computed
  scheduled fields, REST fallback for unparseable payloads, coalesced refresh
  (16 ms batch like the web), optimistic pin/archive.
- MachineStore: full/patch/null machine-updated decision tree per sse.md.
- LastSeenStore: per-session last-seen watermarks + once-per-scope baseline
  seeding + unread derivation (sessionLastSeen.ts/sessionAttention.ts port).
- StoreSyncTargets: SyncEventRouter fan-in — global-scope message-stream
  events refresh the list, gap handshakes full-resync.

:app feature/sessions/ — standalone screen + plain-constructor ViewModel:
- SessionListScreen: pinned section, status dot with thinking pulse, flavor/
  machine/worktree meta line, pending badge, todo chip, unread dot, machine
  filter chips, PullToRefreshBox, offline banner, empty states, long-press
  pin/archive sheet; taps emit onOpenSession only (no navigation).
- SessionListViewModel: store combine -> UiState, owns the global SSE
  subscription while started (subscribe after collector registration),
  entry refresh, error SharedFlow for snackbars.

Tests: SummaryPatching/SessionSorting JVM tests (cases mined from
useSSE.test.ts), store tests (stale/equal/newer patches, full replace,
keep-alive identity, snapshot round-trips, optimistic rollback), ViewModel
combine + handshake tests with fake stores. All of :core:protocol:test,
:core:data:test, :app:testDebugUnitTest, :app:assembleDebug green.
2026-08-17 15:47:05 +08:00
weishu 3cf2a669c3 feat(android): pairing flow, deep link, DI graphs, navigation skeleton (B-M1d) 2026-08-17 15:39:29 +08:00
weishu d39197b97d feat(android): markdown/code/diff rendering foundation (B-M2d1)
:core:protocol (pure JVM, all web-transform ports fixture-style tested):
- markdown/MarkdownTransforms.kt: repairTables (remark-repair-tables port),
  disableIndentedCode (enabledBlockTypes minus IndentedCodeBlock == micromark
  disable codeIndented) + canonical parser factory (GFM tables, strikethrough
  requireTwoTildes, autolink), stripCjkAutolinkArtifacts, detectFilePathLinks/
  matchWholeFilePath/rewriteExplicitLinkTarget (remark-file-path-links port)
- markdown/HrefPolicy.kt: Allowed|ConfirmFirst|Blocked scheme policy with
  double-percent-decode + control-char-strip bypass hardening (web parity);
  scheme-less/SPA/protocol-relative fail closed on native
- git/UnifiedDiffParser.kt: full unified diff -> DiffFile/DiffHunk/DiffLine
  (rename/copy/new/deleted/binary/mode/similarity, quoted paths, bare codex
  diffs, tolerant of truncated hunks + wrong LLM counts)
- 56 new JVM tests (repair matrix, parser config, CJK, path detection incl.
  negatives, href matrix, 11 diff scenarios cross-checked vs web semantics)

:app Compose UI:
- ui/markdown/Markdown.kt: transforms -> commonmark AST walk; paragraphs/
  headings/lists (ordered/bullet/task via stripped text markers)/blockquote/
  tables (intrinsic-width grid in horizontal scroll)/thematic break/html
  monospace fallback; unknown fences (mermaid/math) degrade to CodeBlock;
  LinkAnnotation links via LocalMarkdownLinkHandler (onFilePath/onUrl+policy)
- ui/markdown/CodeBlock.kt: header chip + copy, horizontal scroll, highlights
  1.0.0 syntax coloring off-main via produceState with 200-entry LRU keyed by
  (hash, len, lang, dark), 400-line cap then plain
- ui/components/DiffView.kt: hunk headers, +/- tinted rows, dual line-number
  gutters, compact/expand
- ui/theme: HapiExtendedColors (code/diff/table/quote tokens mirroring web
  index.css light/dark/OLED) + pure-black OLED scheme, provided by HapiTheme
- MarkdownPreviewParameterProvider + kitchen-sink @Previews (compile-checked)

deps (Maven Central verified): org.commonmark:commonmark 0.24.0 + gfm-tables/
gfm-strikethrough/autolink exts, dev.snipme:highlights 1.0.0 (jvm variant)

Verified: :core:protocol:test 141 green, :app:assembleDebug green
2026-08-17 15:14:01 +08:00
weishu 83bd25aa3b feat(android): scaffold Compose app + core modules + CI (B-M0) 2026-08-17 11:22:35 +08:00