feat: persist leftover interaction-map coordinates (v2.12.19) - #579
feat: persist leftover interaction-map coordinates (v2.12.19)#579seonghobae wants to merge 4 commits into
Conversation
After IRT main effects, persist complete-case ξ/ζ leftover-map coordinates and render the 2D Jeon/Gabriel map above leftover pairs (ADR 0121 / 0126). Click a post node or leftover-pair criterion to open that post. Rank-0/1 maps pad unused axes with zero. Hidden posts stay hidden. Never invent a leftover score or a theta.
|
Warning Review limit reachedNext included review available in 37 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (36)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Requesting independent review on exact head 8640199. Closest/farthest leftover pairs already live on main; this increment only persists leftover-map ξ/ζ and renders the 2D map. Hidden posts stay hidden. Never invent leftover score/theta. Never self-approve. Squash-merge only with independent APPROVE + exact-head required success. Do not wait on Checks. |
| leftover_map_persons = [ | ||
| {key: value for key, value in person.items() if key != "has_real_source_context"} | ||
| for person in leftover_map_persons | ||
| ] | ||
| leftover_map_items = list(report.get("leftover_map_items", [])) |
There was a problem hiding this comment.
📝 Info: Leftover-map criterion nodes are not ABAC filtered, but cannot leak
In read_period_reports, leftover_map_persons are ABAC/demo filtered while leftover_map_items pass through unfiltered. This is safe: items carry only criterion_code and coordinates, and a criterion node opens a post only through leftoverPairForCriterion over the already-filtered leftover_pairs. A hidden post's pair is removed, leaving its criterion non-interactive. Consistent with ADR 0121, which gates only persons.
Was this helpful? React with 👍 or 👎 to provide feedback.
| for person in report.leftover_map_persons: | ||
| await conn.execute( | ||
| """ | ||
| insert into report_leftover_map_person ( | ||
| grouping_kind, grouping_key, period_code, rubric_version, | ||
| post_id, axis_one, axis_two | ||
| ) values ($1,$2,$3,$4,$5,$6,$7) | ||
| """, | ||
| grouping_kind, | ||
| grouping_key, | ||
| period_code, | ||
| RUBRIC_VERSION, | ||
| person.post_id, | ||
| person.axis_one, | ||
| person.axis_two, | ||
| ) | ||
| for item in report.leftover_map_items: | ||
| await conn.execute( | ||
| """ | ||
| insert into report_leftover_map_item ( | ||
| grouping_kind, grouping_key, period_code, rubric_version, | ||
| criterion_code, axis_one, axis_two | ||
| ) values ($1,$2,$3,$4,$5,$6,$7) | ||
| """, | ||
| grouping_kind, | ||
| grouping_key, | ||
| period_code, | ||
| RUBRIC_VERSION, | ||
| item.criterion_code, | ||
| item.axis_one, | ||
| item.axis_two, | ||
| ) |
There was a problem hiding this comment.
📝 Info: Map-row FKs depend on in-transaction insert order
report_leftover_map_person references report_member_score and report_leftover_map_item references report_item_information. Both persist paths insert member scores and item information before the map rows in one transaction, so immediate FK checks pass. Map persons/items are always subsets of those rows (same fit post_ids; selected_items ranks every bank item), so the constraints hold across free-calibrate, FIPC, and shared-metric reports.
Was this helpful? React with 👍 or 👎 to provide feedback.
…-interaction-map-v21219 # Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # CLAUDE.md # backend/app/main.py # backend/app/report_ingestion.py # backend/tests/test_api.py # frontend/src/App.test.tsx # frontend/src/App.tsx # frontend/src/api.ts # lineageweave/leftover_pairs.py # lineageweave/period_report.py # scripts/seed_demo_data.py # tests/test_leftover_pairs.py # tests/test_migration_replay.py # tests/test_period_report.py # tests/test_schema.py
| @@ -0,0 +1,9 @@ | |||
| ## 2.12.19 — Persist leftover interaction-map coordinates | |||
There was a problem hiding this comment.
📝 Info: Version naming inconsistency in changelog fragment
package.json/pyproject.toml and CHANGELOG.md ship 2.12.20, but the PR title and the CHANGELOG.d fragment (filename and its ## 2.12.19 header) say 2.12.19. Documentation-only, no functional impact.
Was this helpful? React with 👍 or 👎 to provide feedback.
…wave 2 conflict resolution) # Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # CLAUDE.md # backend/tests/test_api.py # frontend/package.json # lineageweave/leftover_pairs.py # pyproject.toml # scripts/seed_demo_data.py # tests/test_leftover_pairs.py # tests/test_period_report.py # tests/test_schema.py # uv.lock
|
Cycle 2026-08-25T04:01 KST: leftover interaction-map coordinates remain independent of leftover-share/reconstruction stacks. Independent exact-head APPROVE required. This identity will not self-approve. Squash-merge only with independent APPROVE + exact-head required success. |
|
Cycle comment: leftover-map coordinates (#579) still waits for independent APPROVE + exact-head required success. Do not self-approve. Recutting leftover-map length onto protected main as independent v2.12.31 / ADR 0187 (0183–0186 remain claimed by open leftover PRs). Never mix reconstruction/share/cosine/inner-product/coordinates into that recut. |
|
Cycle comment: leftover increment still waits for independent APPROVE + exact-head required success. Author must not self-approve. Do not squash-merge without that APPROVE. Recut leftover-map length onto protected main as independent v2.12.31 / ADR 0187 (0183–0186 claimed by open leftover share/reconstruction PRs). Do not mix leftover stacks. Issues #79 and #87 stay open. |
# Conflicts: # AGENTS.md # ARCHITECTURE.md # backend/app/report_ingestion.py # backend/tests/test_api.py # frontend/src/App.test.tsx # frontend/src/App.tsx # frontend/src/i18n.test.ts # lineageweave/leftover_pairs.py # lineageweave/period_report.py # scripts/seed_demo_data.py # tests/test_leftover_pairs.py # tests/test_schema.py
| ) | ||
| ) | ||
| if not candidates: | ||
| # ADR 0168: without a complete-case Gabriel map there is no | ||
| # ADR 0183: without a complete-case Gabriel map there is no | ||
| # leftover pair to name. The report carries coverage counts | ||
| # instead of a center-distance stand-in pair. | ||
| return (), () | ||
| return LeftoverInteractionMap(pairs=(), persons=persons, items=items, axes=axes) | ||
| closest = min(candidates, key=lambda row: (row[0], row[1], row[2])) | ||
| farthest = max(candidates, key=lambda row: (row[0], row[1], row[2])) | ||
| pairs = ( | ||
| _pair_from_candidate(PAIR_KIND_CLOSEST, closest, leftover_map_rank), | ||
| _pair_from_candidate(PAIR_KIND_FARTHEST, farthest, leftover_map_rank), | ||
| return LeftoverInteractionMap( | ||
| pairs=( | ||
| _pair_from_candidate(PAIR_KIND_CLOSEST, closest, leftover_map_rank), | ||
| _pair_from_candidate(PAIR_KIND_FARTHEST, farthest, leftover_map_rank), | ||
| ), | ||
| persons=persons, | ||
| items=items, | ||
| axes=axes, |
There was a problem hiding this comment.
📝 Info: Map coordinates and pair distances share one basis
leftover_map_from_residual emits person/item coordinates from the same padded two-axis arrays used for the closest/farthest pair distances, so persisted node positions and pair distances stay mutually consistent and hidden higher SVD components cannot shift a visible pair off the map. Confirmed by test_rank_three_pair_distances_match_the_persisted_two_axis_map.
(Refers to this code)
Was this helpful? React with 👍 or 👎 to provide feedback.
| for person in report.leftover_map_persons: | ||
| await conn.execute( | ||
| """ | ||
| insert into report_leftover_map_person ( | ||
| grouping_kind, grouping_key, period_code, rubric_version, | ||
| post_id, axis_one, axis_two | ||
| ) values ($1,$2,$3,$4,$5,$6,$7) | ||
| """, | ||
| grouping_kind, | ||
| grouping_key, | ||
| period_code, | ||
| RUBRIC_VERSION, | ||
| person.post_id, | ||
| person.axis_one, | ||
| person.axis_two, | ||
| ) | ||
| for item in report.leftover_map_items: | ||
| await conn.execute( | ||
| """ | ||
| insert into report_leftover_map_item ( | ||
| grouping_kind, grouping_key, period_code, rubric_version, | ||
| criterion_code, axis_one, axis_two | ||
| ) values ($1,$2,$3,$4,$5,$6,$7) | ||
| """, | ||
| grouping_kind, | ||
| grouping_key, | ||
| period_code, | ||
| RUBRIC_VERSION, | ||
| item.criterion_code, | ||
| item.axis_one, | ||
| item.axis_two, | ||
| ) |
There was a problem hiding this comment.
📝 Info: Map rows rely on period-score cascade for cleanup
persist_period_report adds no explicit delete for the new map tables; it relies on the on delete cascade FK to report_period_score, which it deletes first (same pattern as pairs/axes/coverage). Insert order satisfies the composite FKs (members before map persons, item_information before map items), so rebuild stays idempotent.
Was this helpful? React with 👍 or 👎 to provide feedback.
Period reports now persist complete-case leftover interaction-map coordinates ξ / ζ after IRT main effects and render a 2D Jeon / Gabriel map above leftover pairs (ADR 0121 / 0126). Click a post node or a leftover-pair criterion node to open that post.
This restacks the unique 2D-map increment from #481 onto current
main@b4911f8as v2.12.19. Closest/farthest leftover pairs already live on main. Do not mix into #74/#92. #96 stays closed.Buyer next action
After seed, the leftover interaction map sits above leftover pairs. Click a post node or a highlighted leftover-pair criterion to open that post.
Constraints
0172_report_leftover_interaction_map.sqlis four-digit replayed (ADR 0166).Tests
Independent review required. Never self-approve. Squash-merge only with independent APPROVE + exact-head required success. Do not wait on Checks.