Skip to content

feat(longitudinal): preserve observation clocks and membership shares - #235

Merged
seonghobae merged 7 commits into
mainfrom
cursor/bc-a36fdb29-c3b9-41b0-bc17-a34bc0d2eb8f-03a1
Aug 17, 2026
Merged

feat(longitudinal): preserve observation clocks and membership shares#235
seonghobae merged 7 commits into
mainfrom
cursor/bc-a36fdb29-c3b9-41b0-bc17-a34bc0d2eb8f-03a1

Conversation

@cursor

@cursor cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

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

  • Add src/longitudinal_observation.rs for normalized observation identity, four clocks, civil timezone/offset, and explicit membership shares of 10,000.
  • Fail closed on padded or numeric aliases, zero or inverted validity, missing timezone, impossible UTC offset, empty/duplicate/zero/unbalanced membership, ingest-before-receipt, and last-write-wins source replay.
  • Flag source-clock skew (recorded_at after received_at) without rewriting the phone clock.
  • Keep platform ingest monotonic across the in-memory set.
  • Record the ISO 8601 / PROV-DM / Robinson / Curran & Bauer / Hamaker & Wichers / Browne et al. doctoring and keep TRACEABILITY as Active PR, not evaluated-main Implemented.

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

  • RED: tests/longitudinal_observation_time_contract.rs failed to compile before the module existed
  • GREEN: cargo test --test longitudinal_observation_time_contract --test documentation_architecture_contract
  • cargo clippy --all-targets -- -D warnings
  • Required exact-head checks, coverage, and independent review before merge

Operator 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.

Open in Web View Automation 

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>
@cursor
cursor Bot requested a review from seonghobae August 16, 2026 16:54
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>
@seonghobae
seonghobae marked this pull request as ready for review August 17, 2026 04:37
@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

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.

@opencode-agent opencode-agent Bot 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.

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head f4b23e6dce605760286423fe4f3237c6a8bfa512.

  • 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"]
Loading

cursoragent and others added 3 commits August 17, 2026 16:32
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 seonghobae 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.

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.

@seonghobae seonghobae 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.

Stale REQUEST_CHANGES on f4b23e6: coverage-evidence failed on that SHA. Current head b1a7378 has coverage-evidence SUCCESS, Runtime CI SUCCESS, and independent last-push approval.

@seonghobae

Copy link
Copy Markdown
Contributor

OpenCode required check is now SUCCESS on exact head b1a73788, and I submitted an independent last-push APPROVE on that SHA.

Merge remains blocked by a stale opencode-agent REQUEST_CHANGES on prior SHA f4b23e6 (coverage-evidence failure that this head no longer has). I cannot dismiss that review (integration token is forbidden) and will not use admin bypass.

OpenCode: please replace the stale REQUEST_CHANGES with a current-head verdict so this check-clean slice can land.

@seonghobae

Copy link
Copy Markdown
Contributor

OpenCode: please replace the stale REQUEST_CHANGES on prior SHA f4b23e6 (coverage-evidence failure) with a current-head verdict on b1a73788.

Required checks on b1a73788 are SUCCESS, including coverage-evidence. Independent last-push APPROVE is already present. Merge remains blocked only by that stale CHANGES_REQUESTED. I cannot dismiss the integration review and will not use admin bypass.

@seonghobae
seonghobae dismissed opencode-agent[bot]’s stale review August 17, 2026 17:40

Dismissed as stale after exact head moved from f4b23e6 to b1a7378. The blocker was coverage-evidence failure on the old head; current-head coverage-evidence, Runtime CI, security, SBOM/provenance checks are successful, and an independent last-push approval exists on b1a7378.

@seonghobae
seonghobae merged commit 46142cd into main Aug 17, 2026
33 checks passed
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
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.
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
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>
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
Rebase onto 46142cd must not keep observation-time ingest as Active PR.
Keep #242 audit evidence explicitly segregated from protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
Rebase onto 46142cd must not keep observation-time ingest as Active PR.
Keep #242 audit evidence explicitly segregated from protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 17, 2026
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.
seonghobae added a commit that referenced this pull request Aug 18, 2026
* 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>
cursor Bot pushed a commit that referenced this pull request Aug 18, 2026
Rebase onto 46142cd must not keep observation-time ingest as Active PR.
Keep #242 audit evidence explicitly segregated from protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 18, 2026
Rebase onto 46142cd must not keep observation-time ingest as Active PR.
Keep #242 audit evidence explicitly segregated from protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants