JTP-of-whom rebuild from práctica picks (Q2 systemic reconcile) + own-students-first visibility (Q1) — Elazar-ruled
Elazar ruled 2026-07-16 (org-model doc, commit 526048b): (Q2) systemic reconcile of assignment FROM práctica picks — 'JTP of who picked her, update everybody' = mechanism (b), roster derived as the SET of picked JTPs, SA slot demoted to a written primary-hint (not dropped); (Q1) teacher visibility = own-students-first + rest-of-comisión collapsed accordion (Pluto pattern), replacing the whole-comisión TCM fallback. Phasing: P1 db-mars builds evidence-derived roster view (student→picked-JTP set: count/share/primary/date-window); P2 coder re-points all SA-single-slot READ sites (alumnos.ts scope+roster HIGH, reporting.ts 5 scope predicates+studentCount+FROM-SA gather HIGH, practica.ts scope+?jtp= picker MED-HIGH, report-breakdowns/comisiones-teacher-view/vComisionStudentsByJtp/student→JTP displays MED) to the derived view + builds Q1 own-students-first UI; P3 optional retire SA writes. Class-A (schema view + auth-scope change). Blocked: P1 view shape from db-mars, Pluto pattern from coder-pluto-cc, Elazar sub-decision on 'primary' hint definition (modal/most-recent/admin-pinned). App-cost table + full spec in mars/shared/md/mars-org-model.md.
Questions
Activity
-
parent=#2039
-
coder-pluto-cc pattern intel (2026-07-16): Pluto's /alumnos does NOT match Elazar's 'own students + rest-of-comisión collapsed accordion' description. Pluto = own-JEFE-roster primary + a SEPARATE toggle-gated AYUDANTE-comisión secondary (mixed teachers only); NO 'rest of comisión' list, NO accordion. Primitive = ComisionDayToggle (Button flips ?verComision=1 via router.push) with SERVER-SIDE conditional fetch (secondary roster fetched only when param set, isolated 'secstudents' pagination prefix; collapsed = zero rows shipped) — NOT shadcn Accordion, NOT client lazy-load. Pluto keys 'mine' off the ROSTER/ASSIGNMENT slot (vActiveRoster.jtpId = comisionJtps pair), práctica facts joined for COUNTS only — OPPOSITE of Mars Q2 (mine = who PICKED me, evidence). So for P2: only the toggle+conditional-fetch SHELL is portable; the membership predicate + scope fn + KPI/context null-guards are a rewrite. Gotchas: isolated pagination prefix per section, keep secondary fetch OUT of mapWithConcurrency fan-out (PLUTO-93 pool-timeout crash), empty-own-roster no self-fallback (deliberate), per-section sort. Files: pluto alumnos/page.tsx, access-scope.ts, db/queries.ts getStudentsForTeacherPage, alumnos-page-client.tsx, comision-day-toggle.tsx. OPEN Q to Elazar: is Mars's collapsed 'rest of comisión' ACTIONABLE (gradeable) or view-only (Pluto's is read-only)?
-
P1 LANDED: db-mars view vStudentTeacherRoster (migration 045) pushed by coder-mars-cc as a74273f (v bump); audit-mars-ca design-cleared the SQL + folded 4 required changes + isTeacherActive micro-fix; Class-A PTD (deploy-terminal + live-version) with audit. Final column contract: comisionId,comisionName,periodoId,periodoIsActive,studentUserId,studentName,pickedRole(jtp|ayudante),teacherUserId,teacherName,teacherDeletedAt,isTeacherActive,practicaCount,roleTotal,share,firstPickedAt,lastPickedAt,pickRank,isPrimary,isModalTie,topPickTieCount,isMultiTeacher,source(picks|sa). P2 (coder read-repointing + own-students-first UI) now gated ONLY on: Elazar Q1 (collapsed rest-of-comisión view-only vs gradeable, a/b/c put to him) + a joint perf EXPLAIN with db-mars before writing read code (audit flagged the picks CTE aggregates full practicas per-comisión; decide LATERAL-unpivot vs matview).
-
P2 fully design-unblocked + de-risked (2026-07-16). Elazar resolved both gates: (1) primary=modal (isPrimary, ties stay visible via isModalTie/topPickTieCount, no auto-break); (2) rest-of-comision gradable+comision-scoped. CODE-VERIFIED both auth+scope are ALREADY comision-wide: grading gate reviewPractica->canViewPractica->isTeacherForComision reads vTeacherComisionMemberships (not SA slot); and buildScopeAndFilters (alumnos.ts:122-133) JTP/ayudante clause has a pure-OR comision-membership fallback, so a TCM member already SEES the whole comision. => P2 is NOT a scope/auth change; it collapses to Class-S display+presentation on /alumnos: (a) swap getScopedStudents jtp/ayudante display cols from stale SA slot (=the multi-JTP 'mezcla' Paula reported) to vStudentTeacherRoster modal-primary + tie flag; (b) own-picked-first ordering + collapsed-but-gradable 'resto de la comision' accordion. Perf gate CLEARED (db-mars EXPLAIN comision A/40): no matview (picks CTE = optimization fence, O(total practicas ~2200) not O(comision), cache-hit ~116ms; revisit at 5-10x or hot-path -> LATERAL-unpivot). MUST use ONE GROUP BY join (planner doesn't dedup two subqueries): LEFT JOIN vStudentTeacherRoster r ON comision+student, pickedRole='jtp'; max(teacherUserId) FILTER(isPrimary), bool_or(isModalTie) FILTER(isPrimary), bool_or(teacherUserId=$1) AS isOwnPicked; GROUP BY student. HELD from unattended 3am implementation: user-visible /alumnos UX is taste-sensitive -> implement in fresh context w/ Elazar reachable; send db-mars final scoped SQL for pre-commit EXPLAIN; Class-S cross-vendor audit post-push.
-
P2 LANDED: f126838 (v2.29.0, Class-S). getScopedStudents jtp/ayudante display cols now evidence-derived from vStudentTeacherRoster via single GROUP BY join (max(::text) FILTER isPrimary per role — max(uuid) doesn't exist, db-mars caught it pre-push — + isModalTie 'empate' badge, + surrogate-aware bool_or viewer keys as InitPlans); own-picked-first split in alumnos-table.tsx with collapsed fully-actionable 'Resto de la comision (N)' (engages only when viewer has own-picked rows; admins keep flat list); ?jtp= row link keys on isOwnJtpPicked (secondary JTPs get their subset, ayudantes still omit per MARS-23). db-mars pre-commit EXPLAIN PASS: 32ms/93 rows cache-hit; sa-fallback rows all isPrimary=true so zero-pick students keep SA teacher; functional check Harumi->Eugenia (8 picks, SA said Paula) + LAZARTE->Eugenia (7) = the SOP-27 mezcla fixed on display. Side-effect: practicas/nueva teacher prefill now evidence-primary (consistent w/ ruling). Awaiting audit-mars-ca cold review + PTD on f126838; self-verify version probe in flight (expect 2.29.0). REMAINING P2 surfaces (later passes): reporting.ts roster CTE studentCount + scope displays, practica.ts ?jtp= picker options (still DISTINCT SA), report-breakdowns, comisiones-teacher-view/vComisionStudentsByJtp, student->JTP displays, persona-detail; MARS-355 (raw-UUID render in /alumnos) folded into next pass per PM agreement.
-
coder02-mars-cc MARS-437 investigation surfaced a latent gate asymmetry: canViewPractica->isTeacherForComision (roster+postgrado only) vs isStudentInScope/getPracticas list scope (which DOES honor SA-only bindings) — an SA-only-bound staff viewer (non-roster assignedTeacher/ayudante) can list a práctica at /alumnos/[id] then dead-end on click. Same scope model this WI is already reconciling onto vStudentTeacherRoster — fold the parity check into your reporting.ts/practica.ts pass rather than a separate Class-A WI.
-
--agent
-
--agent
-
--agent
-
--agent
-
P1 (migration 045, a74273f) + P2 (f126838/047aca5, d9f91d5/d7352bc, d498db5/768610f, mig 052) all audit-PASS'd, live v2.32.1. Evidence-derived roster (vStudentTeacherRoster) now drives /alumnos, reporting.ts, practica.ts picker, /comisiones/[id]; own-students-first + collapsed-gradable UI shipped; SA-parity gate asymmetry + MARS-355 folded in and resolved. P3 (optional SA-write retirement) intentionally left unscheduled — separate decision, not blocking this close.