Files
compass_teams_nhs/docs/phase-6b7b-notes.md
Sam Rolfe 047af0f31d Phase 6b/7b: per-child decoded periods, separate brief blocks, idempotent calendar (AUD-119)
- Parse each child's own "Today" day widget for the timetable (FR-16); drop the
  school-wide week calendar's lesson grid and clean the leaked routine rows.
- Add the editable codes map (FR-17): subjects, rooms, teachers and period
  labels, seeded, an unknown code falls back to the raw code; `school codes` CLI.
- Brief: Finn's block first, then Harry's, four sections always present (FR-9);
  periods decoded into plain English; the undated tail is one counted line (FR-18).
- Calendar: write periods + work due + work overdue + major events, per child,
  on every pass. Identity is the stable per-item key, so a re-run never re-inserts
  (FR-8). morning-brief.sh now runs scan -> calendar push -> notify.
- Day-widget labels are 12-hour: 1-6 read as PM, fixing afternoon periods.

Proven live on .13: image 0.6.2-phase6b7b; both children's briefs decoded and
separate; 35 events in calendar.school; runs 2 and 3 of the scan added nothing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 10:25:55 +11:00

11 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 on first read and never overwrites a correction. An unknown code renders as the raw code, never blank.

=== FINN ===
PERIODS TODAY
- Period 1 — Year 7 Science — Room H14LAB — Mr KNI (08:55)
...
- Period 4 — Year 7 Physical Education — Gym 4 — Mr LTA (13:26)

Sam edits it without a rebuild:

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. 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/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; only Sam can supply the surnames.