Skip to content

lp612 lane extraction → main (cherry-pick vehicle) — DO NOT MERGE without operator go - #701

Merged
hyasin270 merged 3 commits into
mainfrom
lp612-to-main-1788699662
Sep 6, 2026
Merged

lp612 lane extraction → main (cherry-pick vehicle) — DO NOT MERGE without operator go#701
hyasin270 merged 3 commits into
mainfrom
lp612-to-main-1788699662

Conversation

@hyasin270

Copy link
Copy Markdown
Contributor

DO NOT MERGE without a fresh operator "go"

The operator refused the develop → main merge (2026-09-06): "There are too many other random commits and unusable features on develop, we need cherry picking." PR #676 (the full merge) is therefore dead as a vehicle and stays open only as the record of what it would have shipped. This branch is the replacement: the lp612 lane extracted onto main by dependency closure, not by commit cherry-pick.

Branch is off origin/main e7b10e7. Source of the lane: origin/develop a33f74a.

Why closure and not cherry-pick

OPTION_B.md showed a commit-level pick fails on hidden dependencies — the named case being bot/workers/sqs-worker.js:44 requiring sqs-visibility-heartbeat.js, a file absent from main, added by an lp612 commit outside the path patterns, and mocked in every test: it would boot every SQS worker into MODULE_NOT_FOUND on a fully green suite. So the lane was taken as the transitive require() closure of its entry points instead (00_vehicle/extract/closure.py).

Closure: 319 files — 291 absent from main, 9 present-and-different, 19 already identical.

What came across

  • 16 lane modules + the 322-file bot/vendor/lp-v9 engine + the 5 bot/scripts/*lp612* importers.
  • 11 migrations V1.2.8__lp612_runtime_lesson_plansV1.3.8__lp612_over_time, and the lp612 sections of the bootstrap schema (00_complete-schema.sql), including lp_feedback.lp612_segment_id — a column that ships only in a migration is invisible to bootstrap.
  • COPY-WHOLE (every hunk lane work): pakistan-lp-endpoint.js, registration-endpoint.js, lp-intent.js, docs/flows/pakistan-lp-flow-v3.json (gains SELECT_CHAPTER_MORE + SELECT_LANGUAGE).
  • SPLICED hunk-by-hunk: ux-strings.js (2 key blocks of 7), llm-client.js (the timeout/maxRetries budget only), menu.service.js, flow-response.handler.js, sqs-worker.js (6 of 9), text-message.handler.js (8 hunks + 2 gates of 19), voice-message.handler.js, whatsapp-bot.js, lp-context.service.js (the one_screen render only), tests/jest.config.js, .env.template, bot/package.json.
  • Deps: ajv, katex, openchemlib only — derived from every bare require() in the closure. Lock entries injected surgically: 7 added, 0 removed, npm ci clean.

Per-file rationale with the hunks taken and left: 00_vehicle/SPLICES.md. Full record: 00_vehicle/EXTRACTION.md.

The Gamma cut is a GATE, not a deletion

develop deleted the generation. On main it is wrapped in isLp612Enabled() && isLp612RouteAll() && PAKISTAN_LP_FLOW_ID at three doors — the typed one (handleLessonPlanRequest), the voice one (handleVoiceLessonPlanRequest), and the old Oxbridge picker (tryCurriculumLessonPlanServe). Turning either flag off restores today's production behaviour with one Railway variable and no deploy. A Flow-send failure falls through to generation rather than leaving the teacher an explanation and nothing else.

Presentations are deliberately NOT gated — the operator's instruction names lesson plans. handlePresentationRequest and its voice twin still run Gamma; a test pins that so it is a recorded decision, not an oversight.

bot/workers/lesson-plan-generation.worker.js takes zero hunks: it must keep processing, or a flag-off request enqueues a job the worker immediately fails and the rollback lever does nothing.

Red-first

tests/lp-v8/bd-oak77-9-route-all.test.js and -voice-route-all.test.js drive the real handlers with only the network boundary mocked. 3 of 18 failed before the gates. Both carry the case the develop originals could not: with both flags off, createAndQueue({contentType:'lesson_plan'}) is still called and no Flow is sent. A rollback lever that is defined but not proven is not a lever.

Three things the closure walk missed — all caught by the lane's own tests

  1. 47 of 322 git-tracked bot/vendor/lp-v9 files (51 pictogram SVGs among them). The walk expanded that directory from the filesystem, and the develop worktree was short those files. git ls-tree is the source of truth, not os.walk.
  2. tests/jest.config.js needed the katex/mhchem/ajv/openchemlib moduleNameMapper entries and their six mocks — without them seven lane suites did not parse.
  3. lp-context.service.jslp612-serving writes one_screen, so something has to read it. A half-take leaves a value nobody consumes.

Proofs

(a) Boot — 27/27 modules load, 0 MODULE_NOT_FOUND, in a fresh npm ci tree: every lane entry point, the vendored diagram loader, the spliced callers, and both process mains bot/workers/sqs-worker.js and bot/whatsapp-bot.js. This is the check that catches the class of failure Option B was rejected for.

(b) Delta gate, two full runs vs a fresh worktree of origin/main: zero regressions and zero failures caused by the extraction. The only difference either run showed was tests/queue/sqs-cancel-by-group.test.js — the first entry on tests/BASELINE.md's own quarantine list — which passes 3/3 in isolation here.

(c) Staging — recorded in EXTRACTION.md with deployment ids.

What is deliberately NOT on this branch

FICO stays main's v3 (37 indicators × 1–4, max 148) — develop's v4 rescale is not here. pic-to-LP stays exactly as main has it: its Flow config (18 entries, Pic-to-LP Confirm included), its services, its worker case and @google/generative-ai. And the calls/Uplift lane, transcript-quiz/student-mode, attendance/roster, observe/HITL, training, coaching/uptake-loop and portal work all stay on develop.

Before this is merged

Migrations do not run on deploy in this repo — the 11 lp612 files must be applied to prod by hand first, effect-asserted per file. LP_612_ENABLED and LP_612_ROUTE_ALL stay unset until then. Note LP_612_ROUTE_ALL is inert on sqs-worker (the Gamma worker keeps processing by design); keep it in the env package for parity.

Haroon Yasin added 3 commits September 6, 2026 18:04
…dules, 11 migrations, 98 tests

Lane extraction onto main, not a merge (operator: 'too many other random commits
and unusable features on develop, we need cherry picking').

Computed as the transitive require() closure of the lane's entry points on
develop a33f74a — script and result in
prod_golive_2026-09-06/00_vehicle/extract/{closure.py,seeds.json,closure.json}.
319 files in the closure: 291 absent from main (274 bot/vendor/lp-v9 + 16 lane
modules; the 292nd is a .figcache render artefact, gitignored), 9 present-and-
different (spliced separately), 19 already identical.

The two dynamic require() sites the walker cannot follow were resolved by hand:
bot/vendor/lp-v9/diagrams/index.js loads every file under its own TYPES_DIR
(inside the copied tree), and lp-v8-catalog.service.js loads bot/data/
lp_catalog.json (already on main).

Refs: bd-oak77.9, bd-oak77
…rgically

ajv (schema), katex + mhchem (server-side maths), openchemlib (molecule
diagrams) — the only bare modules the 291-file closure requires that main's
bot/package.json lacked (computed, not guessed: every non-relative require()
across the copied files, minus node builtins, minus what main already had).

The lock entries were INJECTED from develop's lock rather than resolved by a
local `npm install`: this machine runs npm 11 and CI runs node 22 / npm 10, and
an install here prunes transitive entries the CI lock still needs. Result vs
main: 7 entries added, 0 removed, 1 changed (the root manifest). `npm ci` is
clean and all three resolve.

Deliberately NOT taken from develop's manifest: @roamhq/wrtc, socket.io-client
and ws (the calls lane, which is not in this extraction), and the REMOVAL of
@google/generative-ai (that is develop's pic-to-LP strip, which main keeps).

Refs: bd-oak77.9
…re missed

SPLICES (per prod_golive_2026-09-06/00_vehicle/SPLICES.md, applied hunk by hunk).
COPY-WHOLE where every hunk was lane work: pakistan-lp-endpoint.js,
registration-endpoint.js, lp-intent.js, docs/flows/pakistan-lp-flow-v3.json
(gains SELECT_CHAPTER_MORE + SELECT_LANGUAGE). SPLICED where it was not:
ux-strings.js (2 key blocks of 7 — no coaching/calls/roster/quiz keys came
across, asserted), llm-client.js (the timeout+maxRetries budget; the
anthropic-direct lane and the cassette wrap left), menu.service.js,
flow-response.handler.js (the per-screen-persist companion), sqs-worker.js
(6 of 9 — lp612_author + heartbeat + WORKER_QUEUES boot status + the stranded-
render reaper; the pic-to-LP deletion, the three quiz cases and the stale-session
override all left), text-message.handler.js (8 hunks + 2 gates of 19),
voice-message.handler.js, whatsapp-bot.js (the lp612_fb_ receiver).
UNCHANGED, deliberately: whatsapp.service.js, r2.js, constants.js,
lp-v8-delivery.service.js, flow-configs.js (main is already correct at 18
entries, Pic-to-LP Confirm included), lesson-plan-generation.worker.js.

THE GAMMA CUT IS A GATE, NOT A DELETION. develop deleted the generation; on main
it is wrapped in `isLp612Enabled() && isLp612RouteAll() && PAKISTAN_LP_FLOW_ID`
at three doors — the typed one (handleLessonPlanRequest), the voice one
(handleVoiceLessonPlanRequest) and the old Oxbridge picker
(tryCurriculumLessonPlanServe). Turning either flag off restores today's
production behaviour with one Railway variable and no deploy. A Flow-send failure
falls THROUGH to generation rather than leaving her with an explanation and
nothing else. Presentations are NOT gated: the operator's instruction names
lesson plans, so handlePresentationRequest still runs Gamma, pinned by a test so
the omission is a recorded decision.

RED-FIRST. tests/lp-v8/bd-oak77-9-route-all.test.js and -voice-route-all.test.js
drive the real handlers with only the network boundary mocked. 3 of 18 failed
before the gates. Both files carry the rollback case the develop originals could
not have — with both flags off, createAndQueue({contentType:'lesson_plan'}) is
still called and no Flow is sent. A rollback lever that is defined but not proven
is not a lever.

THREE THINGS THE CLOSURE WALK MISSED, all caught by the lane's own tests:
- 47 of 322 git-tracked bot/vendor/lp-v9 files (51 pictogram SVGs among them).
  The walk expanded that directory from the FILESYSTEM, and the develop worktree
  was short those files; git ls-tree is the source of truth, not os.walk.
- tests/jest.config.js needed the katex/mhchem/ajv/openchemlib moduleNameMapper
  entries and their six mocks — without them seven lane suites did not parse.
- The lp612 sections of infrastructure/supabase/00_complete-schema.sql, including
  lp_feedback.lp612_segment_id. A column that ships only in a migration is
  invisible to bootstrap.
Also brought: the five bot/scripts/*lp612* importers, and the one_screen render in
lp-context.service.js — lp612-serving WRITES that field, so something has to read
it; a half-take leaves a value nobody consumes.

DROPPED per the splice report: e2e-cassette.js and lp-delivery-marker.service.js
(each was in the closure only via a hunk we left behind), and the three
anthropic-direct test cases.

.env.template documents the 25 LP_612_*/LP612_*/LP_AUTHOR_*/LLM_* names this
branch's code reads, and nothing else from develop.

GATE, two full runs against a fresh worktree of origin/main: zero regressions and
zero failures caused by the extraction. The only difference either run showed was
tests/queue/sqs-cancel-by-group.test.js, the first entry on tests/BASELINE.md's
own quarantine list, which passes 3/3 in isolation here.
BOOT: 27/27 modules load in a fresh npm ci tree, including bot/workers/
sqs-worker.js and bot/whatsapp-bot.js — 0 MODULE_NOT_FOUND.

Refs: bd-oak77.9, bd-oak77
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

Data standards — advisory

Findings on 11 schema file(s) this PR touches. Advisory — does not block the merge. About a quarter of D8 findings are known false positives (commented-out SQL read as live destructive statements).

Schema validation — FAIL

  • D1 (HIGH) infrastructure/supabase/migrations/V1.2.8__lp612_runtime_lesson_plans.sql table niete_lp612_segments: table niete_lp612_segments's primary key column is not typed uuid
  • D3 (MEDIUM) infrastructure/supabase/migrations/V1.2.8__lp612_runtime_lesson_plans.sql table niete_lp612_segments: table niete_lp612_segments has FK-shaped column(s) (segment_id) but no REFERENCES/FOREIGN KEY clause anywhere in the table body
  • D4 (MEDIUM) infrastructure/supabase/migrations/V1.2.8__lp612_runtime_lesson_plans.sql table niete_lp612_renders: table niete_lp612_renders column error_detail looks like PII (matched phone) with no classification marker comment (-- PII / -- Restricted-PII / -- Confidential)
  • D8 (MEDIUM) infrastructure/supabase/migrations/V1.2.8__lp612_runtime_lesson_plans.sql: raw CREATE/ALTER TABLE with no migration-tool marker in the same text
  • D8 (MEDIUM) infrastructure/supabase/migrations/V1.3.0__lp612_slo_enrichment.sql: raw CREATE/ALTER TABLE with no migration-tool marker in the same text
  • D8 (MEDIUM) infrastructure/supabase/migrations/V1.3.1__lp612_also_grades.sql: raw CREATE/ALTER TABLE with no migration-tool marker in the same text
  • D8 (MEDIUM) infrastructure/supabase/migrations/V1.3.3__lp612_overlay_dropped.sql: raw CREATE/ALTER TABLE with no migration-tool marker in the same text
  • D8 (MEDIUM) infrastructure/supabase/migrations/V1.3.6__lp612_pickup_clock.sql: raw CREATE/ALTER TABLE with no migration-tool marker in the same text

@hyasin270
hyasin270 marked this pull request as ready for review September 6, 2026 13:53
@hyasin270
hyasin270 merged commit b6c7712 into main Sep 6, 2026
6 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant