feat(longitudinal): preserve observation clocks and membership shares - #235
Conversation
Keep validity, recorded, received, and ingested times plus explicit membership weights so an offline Seoul-clinic EMA cannot collapse into one timestamp or one primary group. Enrollment, persistence, HTTP, Gyeot, and TEPP stay outside this slice. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Keep the observation-time slice labeled as Active PR evidence, not evaluated-main implementation, now that the landing PR number exists. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headf4b23e6dce605760286423fe4f3237c6a8bfa512. -
Head SHA:
f4b23e6dce605760286423fe4f3237c6a8bfa512 -
Workflow run: 32042781001
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (3 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (3 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (4 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (4 files)"]
R2 --> V2["docs review"]
Evidence --> S3["Test: longitudinal_observation_time_contract.rs"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test: longitudinal_observation_time_contract.rs"]
R3 --> V3["targeted test run"]
Branch coverage missed the find() arms that accept a later iOS copy and a later Android ping for the same clinic enrollment. Add a Seoul EMA fixture that proves those rows stay separate source identities. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Runtime CI failed format check on the Seoul EMA iOS/Android same-enrollment fixture. Apply rustfmt only; contract behavior is unchanged. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Branch coverage left the find() enrollment mismatch arm unproven. A second Seoul-clinic enrollment may reuse the vendor observation id without colliding with the first enrollment's source identity. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
seonghobae
left a comment
There was a problem hiding this comment.
Independent last-push review of exact head b1a73788.
Required checks on this head are SUCCESS: Runtime CI (format/clippy/tests/rustdoc), production line and branch coverage, coverage-evidence, noema-review, Semgrep, Trivy, OSV, Scorecard, SBOM, and package provenance. The stale OpenCode REQUEST_CHANGES on f4b23e6 was coverage-evidence failure on a prior SHA and does not apply to this head.
Reviewed the Seoul-clinic four-clock / dual-membership ingest:
- source identity is
(enrollment_ref, source_system_ref, source_observation_ref)with exact replay idempotent and conflicting clocks fail-closed; - membership shares must be non-empty, unique, positive, and sum to 10,000;
- source-clock skew is flagged, not rewritten; platform ingest cannot precede receipt or the last accepted ingest time;
- padded/numeric aliases and impossible UTC offsets fail closed;
- TRACEABILITY keeps this as Active PR, not evaluated-main Implemented.
The latest fixture proves a second enrollment may reuse a vendor observation id without colliding. Ready to land. Enrollment persistence, HTTP, Gyeot, and TEPP remain out of scope.
|
OpenCode required check is now SUCCESS on exact head Merge remains blocked by a stale OpenCode: please replace the stale REQUEST_CHANGES with a current-head verdict so this check-clean slice can land. |
|
OpenCode: please replace the stale REQUEST_CHANGES on prior SHA Required checks on |
Rebased onto current main after #235. Persist-backed session HTTP stays on the sealed start path; this rebase only keeps both sides of stale changelog/traceability/module-list overlap and does not change persist or session behavior.
Protected main moved from aac99d0 to 46142cd after #235. Record item-delivery, snapshot, narrative, credential, authorization, and outbox-lease persist as shipped, and treat observation clocks and membership shares as protected-main truth. Remaining persist and operator-health HTTP slices stay Active PR. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Rebased onto current main after #235. Persist-backed session HTTP stays on the sealed start path; this rebase only keeps both sides of stale changelog/traceability/module-list overlap and does not change persist or session behavior.
* feat(api): start and reload sessions over persist-backed HTTP Rebased onto current main after #235. Persist-backed session HTTP stays on the sealed start path; this rebase only keeps both sides of stale changelog/traceability/module-list overlap and does not change persist or session behavior. * test(api): cover fragmented session body and unpublished in-memory start Linux llvm-cov left the Content-Length wait-continue path and the start-from-already-unpublished in-memory catalog replay arm unexecuted. Prove the listener waits for the declared body, and that a buyer who already started can retry after the in-memory catalog is suspended. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): cover UTF-8 session framing and persist-backed HTTP port Exercise invalid header bytes, GET reload, numeric start identity, and the PostgreSQL session HTTP port from the library so production line and branch coverage can close the remaining persist-backed start/reload paths. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): drop participant-ref check before corrupt load The assessment_session table rejects a numeric participant_ref at insert. Drop that check first so load can prove it still fails closed when a repaired-badly store contains an illegal stored identity. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): cover library session load replay and GET framing Execute command replay, fail-closed corrupt history, and persist-backed GET/UTF-8 framing in the library crate so Linux llvm-cov instantiations reach the production line and branch gates. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): execute persist From and invalid UTF-8 bodies Cover the Linux llvm-cov From<PersistenceError> instantiation and the decode_request_bytes map_err closure that remain after library load replay tests, without changing session HTTP behavior. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): cover remaining session persist instantiation lines Execute library and integration-crate start/persist error arms that LLVM JSON counts per instantiation so production line coverage can reach 100% without changing product behavior or coverage policy. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> * test(api): split persist query-error or-patterns for line coverage Linux llvm-cov JSON counted the `|` or-pattern source lines in From<InstrumentReleaseQueryError> as uncovered (1850/1854) even though the last arm executed. Give each query-error variant its own match arm and execute those mappings from the integration crate, including the Database start path, without changing persist or session start semantics. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Why
A Seoul-clinic participant can complete an evening EMA while offline. #226 enrolls that person and re-checks consent, but it explicitly leaves observation clocks out of scope. Without this slice, ingest can still collapse four clocks into one receipt time and flatten ward-plus-shift membership into a single primary group. That is the atomistic fallacy the product is required to prevent.
What
src/longitudinal_observation.rsfor normalized observation identity, four clocks, civil timezone/offset, and explicit membership shares of 10,000.recorded_atafterreceived_at) without rewriting the phone clock.Out of scope
Prefer this over folding onto #226
Use this branch for observation-time and membership-share ingest. Prefer #226 for enrollment collection gating. Do not merge those slices as one PR.
Standard basis
International Organization for Standardization. (2019). ISO 8601-1:2019 Date and time—Representations for information interchange—Part 1: Basic rules (with Amendment 1:2022). https://www.iso.org/standard/70907.html
World Wide Web Consortium. (2013). PROV-DM: The PROV data model (W3C Recommendation, 30 April 2013). https://www.w3.org/TR/prov-dm/
Robinson, W. S. (1950). Ecological correlations and the behavior of individuals. American Sociological Review, 15(3), 351–357. https://doi.org/10.2307/2087176
Curran, P. J., & Bauer, D. J. (2011). The disaggregation of within-person and between-person effects in longitudinal models of change. Annual Review of Psychology, 62, 583–619. https://doi.org/10.1146/annurev.psych.093008.100356
Hamaker, E. L., & Wichers, M. (2017). No time like the present: Discovering the hidden dynamics in intensive longitudinal data. Current Directions in Psychological Science, 26(1), 10–15. https://doi.org/10.1177/0963721416666518
Browne, W. J., Goldstein, H., & Rasbash, J. (2001). Multiple membership multiple classification (MMMC) models. Statistical Modelling, 1(2), 103–124. https://doi.org/10.1177/1471082X0100100202
Verification
tests/longitudinal_observation_time_contract.rsfailed to compile before the module existedcargo test --test longitudinal_observation_time_contract --test documentation_architecture_contractcargo clippy --all-targets -- -D warningsOperator next action
Review the offline Seoul-clinic four-clock and dual-membership contracts. Do not self-approve. Do not merge #226 as a substitute for this ingest slice.