Files
compass_teams_nhs/docs/phase-6b7b-notes.md
Sam Rolfe 3e25011399 Phase 6b/7b: dashboard codes editor, decode events, human-readable briefs (AUD-115)
- New /codes dashboard page (behind the session login, linked in the top bar):
  lists every mapping by kind with Add, inline Edit+Save and Delete. Sam can put
  real teacher surnames in without a rebuild (FR-17).
- Decode timetable EVENTS through the same map as periods, so an ensemble reads
  'JAZZ ENSEMBLE - Ensemble Room - Mr KWO' instead of raw codes.
- teacherName splits comma- or space-separated codes ('HHL, OFG').
- SeedCodes is a one-time bootstrap while the table is empty, so a correction or
  a delete is never overwritten or restored.
- Tests: decode Label/Event, the /codes page (save, refuse, csrf, delete, auth),
  store re-seed behaviour. go test ./internal/... passes.
2026-10-16 12:50:31 +11:00

12 KiB
Raw Blame History

Phase 6b/7b — per-child periods, decoded brief, idempotent calendar writes

Status: done (AUD-119). Supersedes the scope notes in phase-6-calendar-notes.md and phase-7-notify-notes.md where they differ.

Spec: AGENTS.md §4 FR-8, FR-9, FR-16, FR-17, FR-18; §7 data model; §11 Phase 6/7. Image compass-teams-nhs/school:0.6.2-phase6b7b.

1. Periods are per child (FR-16) — the bug fixed

The Compass week calendar is school-wide: its lesson grid belongs to the eldest child, so every child's items carried Harry's Year 11 periods. Finn (Year 7) was shown 11MGMAC2 - B11 - GT.

The per-child timetable is the day widget Compass renders on each child's own pages (/Records/User.aspx?userId=… and the Learning Tasks page), labelled "Today":

8:55: 1 - 7SCF - H14LAB - KNI
  • internal/parse/daywidget.go reads that widget from the child's own pages and stores the periods against that child.
  • internal/parse/calendar.go now drops routine lessons from the school-wide week calendar and keeps only real school events.
  • A re-parse deletes the child's leaked routine calendar-page rows, so the wrong periods cannot survive.

The day-widget label prints a 12-hour clock with no AM/PM (1:26 is the afternoon period), so the parser applies the school-day rule: 1–6 are PM, 7–11 are AM, 12 is noon. The widget's grid offset is not used, because its start hour moves with the day's first event (07:00 on one page, 06:00 on another).

2. The decode map (FR-17)

codes (migration 005_codes.sql) is the editable map: subject, room, teacher and period. It is seeded once, while the table is empty, and never overwrites or restores a row after that, so a correction or a delete sticks. An unknown code renders as the raw code, never blank.

The same map decodes the timetable events, not only the lesson periods, so an ensemble reads in plain English too:

EVENTS TODAY
- JAZZ ENSEMBLE — Ensemble Room — Mr KWO (07:45)
- JUNIOR GUITAR ENSEMBLE — Theatre — Mr HHL / Mr OFG (07:45)

Sam edits it without a rebuild, in the dashboard or by CLI:

  • dashboard: /codes (linked as Codes in the top bar) lists every mapping by kind with an Add form per kind, an inline Edit + Save per row, and Delete. The page sits behind the same session login as the dashboard.
docker exec compass-teams-nhs /app/school codes list
docker exec compass-teams-nhs /app/school codes set --kind teacher --code KNI --name 'Mr Knight'
docker exec compass-teams-nhs /app/school codes delete --kind room --code Z9

Teacher rows are placeholders (KNI -> Mr KNI) because Compass gives only initials; Sam replaces them with surnames in the dashboard. Real unknown-code fallback from the live brief: Harry's period 2 teacher field is GT AGE_13, and AGE_13 is not mapped, so it renders raw (Mr GT / AGE_13).

Seed size: 65 rows — 23 subjects, 22 teachers, 18 rooms, 2 period labels.

3. The calendar (FR-8)

For each child separately, every pass writes to calendar.school:

  • that day's periods;
  • work due — any future date;
  • work overdue;
  • major school events (concerts, excursions, exams).

Selection: internal/store/calendar.go adds CalendarPeriodCandidates (today's day-widget periods) and CalendarTaskCandidates (outstanding work with a due date); the existing CalendarCandidates keeps the important school events. Submitted work and work with no due date are never written.

Idempotency is unchanged and still uses the stable per-item key: an item with a Home Assistant event id is not a candidate, and an event whose description carries source: [compass-nhs:<item id>] is adopted instead of written again. Periods and work are per child; a school-wide event is still written once and recorded against every child.

scripts/morning-brief.sh now runs scan → calendar push → notify, so the 6:00 pass writes the calendar. scripts/calendar-push.sh events gained --past so overdue work (which sits at its Compass due date) can be read back.

Evidence (2026-10-15 UTC / 2026-10-16 AEDT)

The rendered brief — real pass

Finn block, first, with his own decoded Year 7 periods:

=== FINN ===

PERIODS TODAY
- Period 1 — Year 7 Science — Room H14LAB — Mr KNI (08:55)
- Period 2 — Year 7 Design — Room B1 — Mr PSI (09:54)
- Connect — Year 7 Tutorial — Room G7 — Mr KDI (11:18)
- Period 3 — Year 7 English — Room G7 — Mr DCA (11:47)
- Period 4 — Year 7 Physical Education — Gym 4 — Mr LTA (13:26)
- Period 5 — Year 7 Drama — Theatre — EBA (14:20)

EVENTS TODAY
- JAZZ ENSEMBLE - ENS - KWO (07:45)
- JUNIOR GUITAR ENSEMBLE - THEATRE - HHL, OFG (07:45)
- HHL GUITAR E - IM3 - HHL (09:54)

OVERDUE
- 7PE PHYSICAL EDUCATION: CAT 3: Cardiorespiratory Fitness (due Thu 03 Sep 16:00) [overdue]
- 7DES PRODUCT DESIGN: CAT 2: Eco Light - Research and Development (due Thu 17 Sep 16:00) [overdue]

DUE IN FUTURE
- 7DRA DRAMA: CAT 2: Ancient Greek Theatre (due Mon 26 Oct 16:00)
- 7TUT CONNECT: Learning Behaviour Report - Self Reflection Term 4 (due Tue 03 Nov 11:45)
- 7DES PRODUCT DESIGN: CAT 3: Eco Light - Making and Evaluating (due Thu 19 Nov 15:15)
- 7MA MATHEMATICS: CAT 6: Measurement and Geometry Test (due Fri 20 Nov 16:00)
- 7DRA DRAMA: CAT 3: Performance or Research Project (due Mon 07 Dec 16:00)
- 8 task(s) with no due date (see the dashboard)

Harry block, second, with his own Year 11 periods:

=== HARRY ===

PERIODS TODAY
- Period 1 — Year 11 General Maths — Room B11 — Mr GT / SMH (08:55)
- Period 2 — Year 11 General Maths — Room B11 — Mr GT / AGE_13 (09:54)
- Connect — Year 11 Tutorial — Room M6 — Mr ANE (11:18)
- Period 3 — Year 11 Art Creative Practice — Room C1 — Mr BDR (11:47)
- Period 4 — Year 11 English — Room H3 — Mr CHA (13:26)
- Period 5 — Year 11 Music — Room A1 — Mr JBR (14:20)

EVENTS TODAY
- none

The combined brief for Jo and Sam carries the same two blocks, === FINN === first and === HARRY === second, never interleaved. The undated tail is one line with a count (17 task(s) with no due date …), never the old 20+ dump.

The Home Assistant calendar — per child (summary + start)

Read back from the Home Assistant API. 35 events in total.

Finn — 16 events:

2026-09-03T16:00  Finn — 7PE PHYSICAL EDUCATION: CAT 3: Cardiorespiratory Fitness
2026-09-17T16:00  Finn — 7DES PRODUCT DESIGN: CAT 2: Eco Light - Research and Development
2026-10-16T07:45  Finn — JAZZ ENSEMBLE - ENS - KWO
2026-10-16T07:45  Finn — JUNIOR GUITAR ENSEMBLE - THEATRE - HHL, OFG
2026-10-16T08:55  Finn — Period 1 — Year 7 Science — Room H14LAB — Mr KNI
2026-10-16T09:54  Finn — HHL GUITAR E - IM3 - HHL
2026-10-16T09:54  Finn — Period 2 — Year 7 Design — Room B1 — Mr PSI
2026-10-16T11:18  Finn — Connect — Year 7 Tutorial — Room G7 — Mr KDI
2026-10-16T11:47  Finn — Period 3 — Year 7 English — Room G7 — Mr DCA
2026-10-16T13:26  Finn — Period 4 — Year 7 Physical Education — Gym 4 — Mr LTA
2026-10-16T14:20  Finn — Period 5 — Year 7 Drama — Theatre — EBA
2026-10-26T16:00  Finn — 7DRA DRAMA: CAT 2: Ancient Greek Theatre
2026-11-03T11:45  Finn — 7TUT CONNECT: Learning Behaviour Report - Self Reflection Term 4
2026-11-19T15:15  Finn — 7DES PRODUCT DESIGN: CAT 3: Eco Light - Making and Evaluating
2026-11-20T16:00  Finn — 7MA MATHEMATICS: CAT 6: Measurement and Geometry Test
2026-12-07T16:00  Finn — 7DRA DRAMA: CAT 3: Performance or Research Project

Harry — 17 events:

2026-06-09T12:00  Harry — 11SBIO 11 SCIENCE - BIOLOGY: Unit 1 Biology Exam
2026-09-01T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: SAC #2: Creating
2026-09-01T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: VCE Unit #2 Outcome #2 Creating
2026-10-05T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: SAC #1: Performing
2026-10-05T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: VCE Unit #2 Outcome #1 Performing
2026-10-09T16:00  Harry — 11HLEG 11 HUMANITIES - LEGAL STUDIES: SAC 6: Human Rights Presentation
2026-10-16T08:55  Harry — Period 1 — Year 11 General Maths — Room B11 — Mr GT / SMH
2026-10-16T09:54  Harry — Period 2 — Year 11 General Maths — Room B11 — Mr GT / AGE_13
2026-10-16T11:18  Harry — Connect — Year 11 Tutorial — Room M6 — Mr ANE
2026-10-16T11:47  Harry — Period 3 — Year 11 Art Creative Practice — Room C1 — Mr BDR
2026-10-16T13:26  Harry — Period 4 — Year 11 English — Room H3 — Mr CHA
2026-10-16T14:20  Harry — Period 5 — Year 11 Music — Room A1 — Mr JBR
2026-10-19T16:00  Harry — 11EENG 11 ENGLISH - ENGLISH: SAC 3: Responding to Texts: The Handmaid's Tale
2026-10-30T16:00  Harry — 11MGMA 11 MATHS - GENERAL MATHS: SAC 4: Networks
2026-11-03T10:45  Harry — 11TUT CONNECT: Learning Behaviour Report - Self Reflection Term 4
2026-11-11T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: SAC #3: Analysing and Responding
2026-11-11T16:00  Harry — 11XMUS 11 PERF ARTS - MUSIC: VCE Unit #2 Outcome #3 Analysing and Responding

School-wide — 2 events (written once, shared by both children):

2026-10-15T15:05  Senior Sub-School Community Service for Uniform Infringement - A2 - PSU, CMA, JGE, LHT, QLM, ECU
2026-10-15T18:00  End of Year Senior Music Concert - HALL (Senior Music Concert) - KSH, CFR, AMG, OFG, NBA, CNI, JDF, SLT, RLE

The 3-run idempotency proof

Three real passes (scripts/scan-compass.sh then scripts/calendar-push.sh push), read back after each:

Pass candidates created failed HA events in calendar.school
1 33 33 0 35
2 0 0 0 35
3 0 0 0 35

Runs 2 and 3 added nothing; the event list after run 2 and after run 3 is byte-identical.

Files changed

internal/store/migrations/005_codes.sql   the editable codes table
internal/store/codes.go                   CodeMap, seed, list/set/delete
internal/store/calendar.go                period + work candidate queries, leak cleanup
internal/store/store.go                   DeleteItemsFromPages
internal/period/period.go                 lesson-label split (period/subject/room/teacher)
internal/decode/decode.go                 plain-English lesson rendering + raw fallback
internal/parse/daywidget.go               the per-child "Today" widget
internal/parse/parse.go, calendar.go, importance.go   per-child hook, week-calendar filter
internal/dashboard/dashboard.go           brief buckets + the required 4-section renderers
internal/brief/brief.go                   Finn-first order, codes decoder, new renderers
internal/web/server.go                    /codes page + save/delete handlers
internal/web/templates/codes.html         the dashboard decode-map editor
internal/calendar/sync.go                 periods + due + overdue + events, decoded, once
internal/calendar/ha.go                   Event JSON exposes start/end for evidence
cmd/school/{main,parse,calendar,codes,items,notify}.go   wiring, codes CLI, purge by page
scripts/{morning-brief,scan-compass,calendar-push,parse-compass}.sh   calendar step, version
docker-compose.yml, Makefile              image 0.6.2-phase6b7b

Not tested

  • A real email/WhatsApp send of the new brief was not repeated; the send path is unchanged and was last proven in Phase 7. The dry run prints exactly what is sent.
  • The 6:00 n8n job was not re-published. It calls scripts/morning-brief.sh, which now includes the calendar step; Sam owns the shared n8n service.
  • The week calendar is still not fetched by the daily scan, so a new major event is only written if a run fetches that page. The two existing school-wide events remain in the calendar.
  • Teacher names are placeholders; Sam supplies the surnames in the new /codes dashboard page. Until then they render as initials.