Skip to content

#711 16 to 19 Include journey (AB#301154) - #721

Merged
ajs-uk-dev merged 17 commits into
mainfrom
711-post16-include-journey
Oct 30, 2026
Merged

ajs-uk-dev merged 17 commits into
mainfrom
711-post16-include-journey

Conversation

@ajs-uk-dev

@ajs-uk-dev ajs-uk-dev commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Closes #711 (AB#301154).

What changes

A school on a 16-19 window can ask to include a student. Include_Post16.json turns the journey on: pick the student, give or skip PDF evidence and an explanation, review, submit, get a reference and the deadline for further amendments.

Who can be picked (AC9). Students in the non-included file, and students the included file carries with P_INCL 502 ("not included in performance measures"). Ingress now writes a second stamp, INCLUDABLE, beside INCLUDED: true when the record is not included, or when its code is one the schema's new x-ingress.includable rule names. Only students-included_schema.json carries the rule (502). KS4 and KS2 get !INCLUDED, so nothing changes for them. INCLUDED, the tabs, Remove and Merge are untouched: a 502 student is still included for those.

  • PupilFilter: Includable and NotIncludable added, NonIncluded removed. The KS4 Include flow uses Includable and returns the same pupils as before.
  • The Include journey's three "already included" guards look a name up among NotIncludable pupils, so a 502 student can never trip the guard against themselves.
  • "Pupil not found" and "This pupil is already included" use the window's noun and offer "Start adding" only where the window type has an Add flow. 16-19 has none.
  • The KS2 dev seed skips the new stamp (it builds CSV columns from the schema).
  • An x-ingress.includable rule with no field, an undeclared field, no codes or a blank code fails the ingress run by name. So does a schema that declares INCLUDED but not INCLUDABLE, shipped or uploaded: it would otherwise offer nobody for inclusion.
  • Rules: no change. Every 16-19 include goes to Scrutiny (INC-DEF); the Inclusion rules name KS4 codes only.
  • Docs: question-flows, request-journey, domain-model, blob-storage, ks2-journeys, the 16-19 schema README, the functional overview's flow list, one AGENTS.md bullet.

Data note. A pupil file ingested before this change has no INCLUDABLE. This affects every key stage, not only 16-19. Until the exercise is validated again, the Include search finds nobody, and the "already included" check matches every typed name, so a school sees "This pupil is already included". The dev seed (SeedDevelopmentData, on in development and review only) validates each seeded window again at each start, so those windows restamp themselves. Every other exercise keeps its old files until an admin validates it again. The service is not live.

Not in this PR. The suggestion label still says INCLUDED for a 502 student (true by file) - a wording question for the BA. 16-19 auto-decision rules - a BA question.

After deploy

Do this in each environment after this change deploys to it:

  • QA: validate each pupil-data exercise again (the window summary page, Validate Pupil data checking).
  • Preprod: the same.
  • Production: the same, if it has any pupil-data exercise.
  • Development: the same for an exercise an admin made by hand. The seeded windows need nothing.

Security

Touches the journey's personal-data pages (the two decision pages) and file upload only through the existing EvidenceUpload page. No new endpoint, parameter or dependency. No new POST action. Nothing logged beyond the existing lookup-failure messages, which carry the window id only.

Journeys checked by hand

At 7fa5e85a (main merged after #745), in the local containers, as the dev editor (Kingsmead). The later merge of #698 changes sign-in and impersonation only, no file this PR changes:

  • 16-19 Include, 502 student (Julia Smith): offered in the search, evidence, summary, submit. Reference CYPMD_16to19_CA80BE9; the rules engine decided Scrutiny, INC-DEF.
  • 16-19 Include, 501 student (Alice Smith): not offered; typed, it gives "This student is already included" with Abort only.
  • 16-19 Include, unknown name: "Student not found" with Search again only; Search again goes back to the search.
  • 16-19 What to change: Merge, Include, Remove.
  • KS4 June Include: the search offers only NOT INCLUDED pupils; a pick reaches the evidence page; an unknown name gives "Pupil not found" with Start adding and Search again.

Checks

All at the head commit, 74af814b (main merged after #698):

  • Build 0 errors; unit 7,744 passed, 0 failed; integration 1,144 passed, 0 failed (CI build job)
  • Review app: smoke set green, ZAP baseline green, whole-suite E2E 381 passed, 0 failed, 4 skipped
  • scripts/check-pins.sh, scripts/check-playwright-pin.sh

Andy Smith and others added 7 commits October 28, 2026 14:19
A second stamp beside INCLUDED: true when the record is not included, or when its P_INCL is a code the schema's x-ingress.includable rule names. The 16-19 included file names 502. Every pupil schema declares it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
IPupilRecord.IsIncludable reads the INCLUDABLE stamp. PupilFilter gains Includable and NotIncludable and loses NonIncluded; the KS4 Include flow uses Includable, which returns the same pupils as before. The unit tests that named NonIncluded are renamed to Includable so the project compiles; Task 3 re-points the guards.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A 16-19 student with P_INCL 502 is included by file but includable by rule. The already-included guards now ask NotIncludable, so such a student can never trip the guard against themselves; on KS4 the answer is the same as before.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…here it exists

16-19 has no Add flow, so Start adding would only bounce to Check your data. The pages take CanAdd from the same list What to change renders.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Include_Post16.json: pick an includable student, give or skip evidence, review, submit. What to change now offers Include on a 16-19 window. Rules: Scrutiny only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The KS2 seed builds its CSV columns from the schema and skips the stamps ingress writes. INCLUDABLE is a new stamp, so the seed stopped the web container at start.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A non-included student to the confirmation, a 502 student to the evidence page, a 501 student to the already-included warning with no Add button, an unknown name to Student not found. What to change on 16-19 offers Include, Merge and Remove. The reference token for 16-19 is 16to19, so the test matches CYPMD_16to19_ (the plan said Post16).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review app for PR 721 was deleted

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

E2E tests passed

381 passed, 0 failed, 4 skipped in 18 min 16 s

Commit 74af814 against https://check-performance-data-pr-721.test.teacherservices.cloud (run)

Andy Smith and others added 2 commits October 28, 2026 16:30
An includable rule with no codes or a blank code fails the run by name. A blank code would match every empty field. A test covers each rule check, including no field.

A unit test proves the autocomplete guard asks NotIncludable and never Included.

C# comments no longer name inclusion codes. The schema holds them.

The unknown-name E2E test waits for the empty-state row, not a fixed time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- IncludeNoResultsPathTests: two comments still named the removed
  NonIncluded filter; they now say Includable / NotIncludable.
- Unit test: StartAddingPupil on a window type with no Add flow redirects
  to Check your data and leaves the Include attempt as it was, so a forged
  POST from a 16-19 decision page is refused by the action, not just hidden.
- Integration test: SearchPupilsAsync throws for a filter it has no rule for.
- Integration test: a schema that declares INCLUDABLE when nothing stamps
  INCLUDED fails the run (both stamps stay null and fail row validation),
  pinning that this case is not silent. No processor change was needed.
- docs/blob-storage.md: a pupil blob written before INCLUDABLE existed
  reads as nobody includable until the exercise is validated again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfe-lance
dfe-lance previously approved these changes Oct 29, 2026

@dfe-lance dfe-lance 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.

LGTM

#736 (#712) moved q-missing-grade and q-revised-grade out of
JourneyController and JourneyViewModelBuilder into EnquiryQuestionIds.
It merged after #740 tightened the baseline, so main fails both
FlowIdCouplingTests ratchet checks. Move the two ids to their new owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfe-lance
dfe-lance previously approved these changes Oct 29, 2026

@dfe-lance dfe-lance 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.

LGTM

Such a schema ingested cleanly and then offered nobody for inclusion.
The check runs on every schema, including ones an admin uploads, so a
shipped-schema test alone would not cover it. The shipped-schema test
now also covers the KS2 December file. The blob-storage doc says that
pre-change pupil files need re-validating on every key stage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajs-uk-dev

Copy link
Copy Markdown
Contributor Author

Response to the review (suggestions 1-6):

  1. Data note. Confirmed. On a pupil file written before INCLUDABLE, IsIncludable reads false on every key stage, so the Includable search finds nobody and the NotIncludable guard matches every typed name ("This pupil is already included"). The PR's data note now says this and asks for a re-validation of each pupil-data exercise in any environment whose blob storage keeps pupil files across deploys. docs/blob-storage.md says the same. I have not added a fallback that reads a missing stamp as !INCLUDED, because AGENTS.md says not to write fallbacks for data written before a change while the service is not live.

2 and 3. Stamp coupling. All five schemas that declare INCLUDED already declare INCLUDABLE. But schemas can also be uploaded from the admin screen, and a test that walks Data/Ingress would not catch an uploaded one. So the check is in ingress itself (748e7d9): a schema that declares INCLUDED but not INCLUDABLE fails the run by name before any row is read, the same way a broken x-ingress.includable rule does. The old test that allowed the omission is now A_schema_declaring_INCLUDED_but_not_INCLUDABLE_fails_the_run_by_name, and the inline test schemas declare both. The shipped-schema test was missing ks2/pupils-december_schema.json; it covers it now.

  1. Trimmed codes. Already pinned: The_schemas_includable_rule_stamps_INCLUDABLE_from_the_code_or_from_not_included has a " 502 " case (CsvSchemaFileProcessorTests.cs). 0502 and 502.0 are not normalised, so the includable rule compares codes exactly as the existing inclusion rule does.

  2. Checks at head. At 748e7d9: unit 7,775 passed, 0 failed; integration 1,126 passed, 0 failed (CI build job); review-app whole-suite E2E 381 passed, 0 failed, 4 skipped; smoke set and ZAP baseline green. The PR's Checks list is updated.

  3. 16 to 19 - Include journey AB#301154 #711 in comments. No change. Each reference also states the reason, so the comment still reads if the number goes away, and none of them reads as a plan or phase. Ticket references in comments are already common in src (about 345 on main, for example EnquiryQuestionIds cites Results Enquiry - Recent Enquiries - Show grade information #712).

@ajs-uk-dev
ajs-uk-dev requested a review from dfe-lance October 29, 2026 14:00
identifier_mapping_invalid describes an identifier problem. This check
is about a missing INCLUDABLE stamp, so the run summary now says
includable_not_declared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 16-19 record had a test that a blob without the stamp reads as not
includable. The KS4 and KS2 record had none, though pre-change blobs on
every key stage lack it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One conflict, in the FlowIdCouplingTests baseline comment: both sides
made the same #712 baseline change. Kept main's comment, so the file
is the same as on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajs-uk-dev
ajs-uk-dev merged commit 140524c into main Oct 30, 2026
10 checks passed

This branch was successfully deployed

1 active deployment
review — 74af814b Deployed Oct 30, 2026 by ajs-uk-dev via Delete Review App 721 #391
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

16 to 19 - Include journey AB#301154

3 participants