Skip to content

Releases: timerloggedout-spec/studysprint

StudySprint webapp v0.5.2

Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Nov 05:54

Surface release webapp v0.5.2, cut by the release-cut workflow (issue #4455 seam 3) from tag webapp-v0.5.2. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.2 (tag webapp-v0.5.2)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag webapp-v0.5.2.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

StudySprint tui v0.5.2

Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Nov 05:54

Surface release tui v0.5.2, cut by the release-cut workflow (issue #4455 seam 3) from tag tui-v0.5.2. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.2 (tag tui-v0.5.2)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag tui-v0.5.2.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

Submission freeze 2026-11-04

Pre-release

Choose a tag to compare

⚠ Submission freeze snapshot — SUITE: FAIL at freeze time (counts in MANIFEST.json). The red state is preserved deliberately (issue #4490 red-suite rule); the run that published this failed loudly after publishing.

StudySprint apk v0.5.2

Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Nov 05:54

Surface release apk v0.5.2, cut by the release-cut workflow (issue #4455 seam 3) from tag apk-v0.5.2. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.2 (tag apk-v0.5.2)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag apk-v0.5.2.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

StudySprint v1.0.0

StudySprint v1.0.0 Pre-release
Pre-release

Choose a tag to compare

@timerloggedout-spec timerloggedout-spec released this 04 Nov 01:10

[1.0.0] — 2026-11-04

The submission cut. Foundation v1.0.0: the version of
record (VERSION, read into every agent receipt as
agent_version) moves 0.5.0 → 1.0.0 on the tree that carries
the complete catch-up slate — parity iterations 1–4 binding
§1d calendar/geography, §1c memory methods, multi-course, and
§1b term-expansion + opt-in hardening on all three surfaces,
plus the second bundled sample course (STAT 210). Surfaces
version independently and stay at 0.5.0; post-1.0.0 foundation
motion is PATCH only (VERSIONING.md). Cut for the D1
submission freeze (Nov 4, 23:59 PT) on the D1 seat's sequence:
suite receipt-version tests green on this tree, or no cut.

Provider credit: command-dispatch (Swarm Optimizations &
Implementation Assurance seat), session
6628d41d-9519-4881-9063-3afe501df815.

Foundation v1.0.0

  • Version of record 1.0.0 — apps/studysprint/VERSION
    bumped; the receipt pin in tests/test_studysprint.py
    follows it, and the parity matrix header names core v1.0.0.
    Everything below in this release section shipped on the
    0.5.0 foundation during the Nov 3 slate and is carried into
    1.0.0 unchanged: the foundation's capabilities at the cut
    are exactly the slate's sum (core pipeline · SR (FSRS-6 +
    SM-2 + Leitner) · memory methods · courses · reader/term
    bank · hardening (opt-in) · calendar/geography).
  • Evidence artifacts keep their 0.5.0 stamps —
    evidence/demo-run.json and the strands-aws golden receipts
    record runs that happened under 0.5.0 and are not rewritten.

Surfaces 0.5.0 (parity iteration 4, #4417 — hardening + §1b completion)

  • State recall + stress hardening binds on all three
    surfaces (opt-in only).
    The core's study_hardening arrives
    as a Hardening view (web/APK) and tab (TUI): varied-context
    practice rotations, the mental-reinstatement script, and
    graduated SIT drill plans whose pressure elements are seeded
    by the drill id (receipt-reproducible). The mode is OFF by
    default; without the student's opt-in the plan is the core's
    refusal receipt and no drill exists. Ceilings ride verbatim
    ("performance under stress/anxiety — not recall gains");
    results record answered + 'not yet' counts with a supportive
    close — no score, deduction, or penalty field exists, by
    construction. Web runs browser ports battery-pinned to the
    core; the TUI runs the real functions.
  • §1b completes on a real book. The demonstration book —
    Darwin, On the Origin of Species, 6th edition (Project
    Gutenberg #2009), Chapter XIV plus the book's complete
    Glossary and Index (typographic normalization only) — is
    ingested through the core pipeline on every surface. The
    ingest receipt shows the counts on each surface: 62 terms
    mined · 62 with definitions · 2 with index refs

    (Embryology p.386 · Morphology p.382). Chapter XIV is the
    demonstration chapter because its own title names two
    indexed headwords, so every leg of the machinery fires on
    real data.
  • Inline term expansion in all three readers. The book's
    sections render with the core's emphasized terms; selecting
    one expands its tap payload inline — glossary definition,
    index pages, and the sections it appears in (the web renders
    the core-computed segments and payloads from the build-time
    bundle; the TUI computes them live).
  • Hypothes.is annotations view. Annotations over the
    book's sections render in the W3C Web Annotation model (the
    core's make_annotation), anchored by TextQuoteSelector. The
    API leg syncs with an account token — not configured on
    these surfaces, so nothing leaves the device.
  • OCR seam, wired where the platform allows. The TUI/CLI
    path runs the core's tesseract default through ingest_any
    (provenance stamped ocr); on web/APK a photographed page
    is recorded as awaiting core OCR — the browser cannot run
    tesseract, and the surface says so.
  • Core fix carried by this iteration: ingest_any no
    longer extracts a textbook's structure from its own back
    matter — a single-file book's Glossary/Index are the term
    bank's spine, not a chapter, so mined counts never count
    the glossary against itself (185 → the honest 62 on the
    demonstration book). ingest_any's textbook receipt now also
    carries the with-definitions / with-index-refs counts every
    surface shows.

Surfaces 0.4.0 (parity iteration 3, #4416 — multi-course)

  • Multi-course binds on all three surfaces. The course set
    (both bundled samples + the student's own courses) is intaken
    through the core's course-set machinery (study_courses:
    per-course plans + countdowns + merged totals + conflict
    flags) and every surface switches between courses with
    per-course state: on web, SR state and check-ins persist
    under per-course storage keys (the pre-0.4.0 global keys are
    adopted once, by the first course only); on the TUI,
    check-ins persist per course in checkin-logs.json while the
    flat checkin-log.json keeps carrying the active course's log.
  • Countdowns + .ics per course. Each course's header/pane
    shows its exam countdown from the intake (honestly "unset"
    when the syllabus carries no exam date); the .ics download
    (web) / file export (TUI) is the core's export_ics over that
    course alone — validated, and carrying no other course's
    events.
  • Create-a-course on both surfaces. Web: paste a syllabus
    document in Ingest — plan and countdown come from browser
    ports of build_study_plan / exam_countdown, battery-pinned
    to the core in tests. TUI: a Courses-tab form persists the
    syllabus document under ~/.studysprint/courses and the set
    re-intakes through the real core. A created course's progress
    lives under its own keys from its first minute.
  • Honest edges, kept: the STAT 210 sample's calendar uses
    an assessment kind the core calendar intake refuses
    ("problem set"); the refusal is recorded on the course's
    bundle and shown in its Calendar view — the course itself
    ships whole. A created course's .ics export and memory
    bundle arrive with its first bundle build; its views say so
    rather than borrowing another course's.

Surfaces 0.3.0 (parity iteration 2, #4415 — memory methods)

  • §1c memory methods bind on all three surfaces. The core's
    five surface-named methods (study_memory) arrive as one
    Memory surface per client: the palace walk runs over
    iteration 1's temple route (the student's real walk, core-
    built placements), scored by the core's ordered-recall rule
    with misses named and the claims ceiling attached; the
    Feynman pane grades an explanation by key-term coverage of
    the verified section text — abstain/escalate/graded, the
    kernel's discipline, never semantic claims; retrievability
    reminders fire at R ≤ 0.9 over the student's own reviewed
    FSRS cards, each carrying a one-tap grade that IS the review.
  • Leitner rotation joins SR as the third scheduler on
    webApp + TUI (boxes 1–5, plain-language move receipts, its
    own per-card state line), and the Plan view gains the
    interleaved session
    : today's sessions + due cards mixed by
    the core's deterministic rotation.
  • Binding shape: the TUI runs the real core functions
    (walk_review · explain_back ·
    retrievability_notifications · leitner_review ·
    interleave_sessions); the webApp/APK run browser ports of
    the same scorers over the core-built bundle
    (state.memory from web/build_data.py), equivalence-pinned
    by tests/test_iteration2_memory.py (node-executed ports vs
    core outputs on shared fixtures). Foundation stays 0.5.0;
    android:versionCode stays 1 (its bump rides the APK trust
    line, not the surface line).

v1.0.0 content — second bundled sample course (#4593)

  • STAT 210 — Data & Chance (sample, synthetic) joins BIO
    101 as the second bundled example course: a structurally
    different subject AND assessment shape (weekly problem
    sets + a final project, vs quiz/lab/midterm), riding the
    same pipeline with no new code paths — fixtures
    examples/{syllabus,calendar,readings,practice_set}_stats.json
    • demo evidence in tests/test_second_sample.py (ingest →
      plan → SR over the new fixtures; counters Findings
      Register F-O4 cap 1, the mirror baseline's "single sample
      course" cap).

Surfaces 0.2.0 (parity iteration 1, #4414 — calendar + geography)

  • §1d calendar awareness + geography bind on all three
    surfaces.
    One core assembler —
    study_geo.surface_calendar_geo — computes the whole binding
    from a calendar document: intake, assessment briefings
    (frequency ramps + SHIFTED time/place notices), the day's
    frequency plan, quiet-hours probes against the class blocks,
    deduped locations, per-assessment routes (coordinate
    estimates with leave-by times), and the temple route (loci
    placements over the student's real walk) with audio cues.
  • TUI gains Calendar and Routes tabs (8 panes), assembled
    live at runtime. webApp gains Calendar and Routes views
    over the same assembler, computed at build time like the
    rest of the bundle's state (disclosed in the parity
    statements). APK follows the bundle.
  • Bundled example calendar (examples/calendar.json, synthetic
    like the other examples): BIO 101 Tue/Thu in Science Hall
    204, a quiz tomorrow (final-stretch ramp ×3), and a final
    SHIFTED to 18:00 in the Gym Annex — the shift briefing and
    its route are in the demo data, not just the tests.
  • Honest edges kept: a calendar without coordinates yields
    locations and NO routes (omitted, never faked); a root
    without a calendar file renders a named empty state on the
    new panes/views.

Surfaces 0.1.3 (#4412 — APK https-origin asset serving)

  • APK shell serves the bundle from a secure https origin —
    MainActivity loads
    https://appassets.androidplatform.net/assets/web/index.html
    and intercepts that reserved domain's /assets/ tree onto the
    APK assets (the WebViewAssetLoader pattern, implemented with
    framework APIs on...
Read more

StudySprint webapp v0.5.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 01:52

Surface release webapp v0.5.1, cut by the release-cut workflow (issue #4455 seam 3) from tag webapp-v0.5.1. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.1 (tag webapp-v0.5.1)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag webapp-v0.5.1.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

Correction (2026-11-03): the parity matrix embedded above was composed from a tree whose matrix header had not yet rolled to the 0.5.1 surface line; the header lines in the embed are corrected to 0.5.1 to match the matrix of record. No other content changes.

StudySprint webapp v0.5.0

Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 00:38

Surface release webapp v0.5.0, cut by the release-cut workflow (issue #4455 seam 3) from tag webapp-v0.5.0. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v0.5.0 · this surface: v0.5.0 (tag webapp-v0.5.0)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag webapp-v0.5.0.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v0.5.0 + surface line
0.5.0. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.0 TUI 0.5.0 APK 0.5.0
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound absent bound (Export tab) absent
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync needs an account token, not configured); OCR: photographs recorded as awaiting core OCR — the browser cannot run tesseract, the named platform limit; finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

StudySprint tui v0.5.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 01:52

Surface release tui v0.5.1, cut by the release-cut workflow (issue #4455 seam 3) from tag tui-v0.5.1. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.1 (tag tui-v0.5.1)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag tui-v0.5.1.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

Correction (2026-11-03): the parity matrix embedded above was composed from a tree whose matrix header had not yet rolled to the 0.5.1 surface line; the header lines in the embed are corrected to 0.5.1 to match the matrix of record. No other content changes.

StudySprint tui v0.5.0

Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 00:38

Surface release tui v0.5.0, cut by the release-cut workflow (issue #4455 seam 3) from tag tui-v0.5.0. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v0.5.0 · this surface: v0.5.0 (tag tui-v0.5.0)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag tui-v0.5.0.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v0.5.0 + surface line
0.5.0. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.0 TUI 0.5.0 APK 0.5.0
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound absent bound (Export tab) absent
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync needs an account token, not configured); OCR: photographs recorded as awaiting core OCR — the browser cannot run tesseract, the named platform limit; finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)

StudySprint apk v0.5.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 07:36

Surface release apk v0.5.1, cut by the release-cut workflow (issue #4455 seam 3) from tag apk-v0.5.1. Changes: see CHANGELOG.md at this tag.

Surface parity at this cut

Foundation: v1.0.0 · this surface: v0.5.1 (tag apk-v0.5.1)

Parity matrix of record: evidence/PARITY-MATRIX.md at tag apk-v0.5.1.

Surface × core feature-parity matrix (iteration 1 of #4282)

Ground truth: the shipped bindings, read from the surfaces'
own builders (web/build_data.py, tui.py: build_state, the
APK bundle = the web bundle) at core v1.0.0 + surface line
0.5.1. This matrix is the catch-up program's baseline;
every iteration updates it and the per-surface parity
statements together (standing surface gates). Owner rule (2026-11-03): this table rides every release body from v1.0.0 — release-cut embeds it verbatim from the cut tag; a pre-matrix tag’s body falls back to a named versions-of-record line. Legend:
bound = the surface runs the real core path ·
partial = a named subset, with the gap stated ·
absent = not on the surface.

Core capability (FEATURES.md) CLI/core webApp 0.5.1 TUI 0.5.1 APK 0.5.1
§1/§2 Plan + trust receipt + Today (§2/§3) bound bound bound bound (build-time state, disclosed)
§3 Daily check-in + no-guilt shift bound bound (persisted; surface-level shift, core reflow not bound) bound (persisted; real week/day identity) as webApp
§3 SR review — FSRS + SM-2, receipts bound bound (browser engines over the core UX export) bound (real review_card) as webApp
SR exports — Anki .apkg · Obsidian vault bound bound (browser ports of both writers over the web SR state: .apkg semantic parity · Obsidian byte parity, battery-pinned — tests/test_sr_exports_web.py) bound (Export tab) bound (as webApp)
§1/§3 Reader (sections + RSVP) bound bound (all 6 sections, 0.1.1) bound as webApp
§1 Intake — syllabus/textbook ingestion bound bound (in-browser grammar; photos = awaiting-core-ocr, disclosed) bound (real ingest_any, confirm-gated) bound (native file chooser + camera wiring)
§1b Reading pipeline — finder · OCR · structure · term bank bound bound (ingestion grammar + the demonstration book's bundle at build time: ingest receipt counts shown (62 terms mined · 62 with definitions · 2 with index refs — Darwin, Origin of Species 6th ed., Ch. XIV + the book's own Glossary + Index); term expansion in the Reader (core-emphasized segments; tap → term_tap_payload: definition · index pages · sections); hypothes.is annotations view over the sections (W3C model; API sync via the config-injected token seam — token entered on-device in the pane, sync merges the account group's annotations into the view, provenance-stamped); OCR: photographs run through tesseract.js (WASM) in the browser — photo → OCR text → the ingestion grammar, provenance stamped ocr (battery: tests/test_ocr_web.py, two-engine agreement over a photo fixture); finder stays the core's separate leg) bound (the REAL pipeline live: Book tab over the bundled demonstration book (same counts), Ingest reports the three counts for any textbook via ingest_any; OCR seam wired through the core's tesseract default, provenance stamped ocr; hypothes.is annotations pane (W3C model, as webApp)) bound (as webApp)
§1c Multi-course + exam countdowns + .ics export bound bound (course set = both bundled samples intaken through the core's intake_courses; header switcher rebinds every view; SR + check-ins persist under per-course keys, legacy keys adopted once by the first course; countdown from the intake (port-pinned for user courses); .ics download = the core's per-course export; create-a-course from a syllabus document in Ingest) bound (Courses tab: the real intake_courses set incl. user courses from ~/.studysprint/courses; switching rebinds all panes; check-ins persist per course in checkin-logs.json (the flat file keeps the active course's log); .ics export writes the active course's calendar file; create-a-course form persists the syllabus doc) as webApp
§1c Memory methods — loci/palace · Feynman · retrievability notifications · interleaving · Leitner bound bound (Memory view: palace walk over iteration 1's temple route · Feynman pane · retrievability list with one-tap grades · Leitner in SR · interleaved plan — browser ports battery-pinned to the core) bound (Memory tab runs the real core functions; Leitner via leitner_review; interleave in the Plan pane) as webApp
§1d Calendar awareness — intake · frequency ramps · shift briefings · quiet hours bound bound (build-time state, disclosed) bound (Calendar pane, live-assembled) as webApp
§1d Geography — locations · routes · temple routes bound bound (build-time state, disclosed) bound (Routes pane, live-assembled) as webApp
§1d State recall + stress hardening (OPT-IN, ceilings in FEATURES §1d) bound bound (Hardening view: opt-in only, per-device flag off by default; ceilings verbatim; varied-context plan + reinstatement script + SIT drill plans (seeded pressure picks, receipt-reproducible) as browser ports battery-pinned to study_hardening; results record answered + 'not yet' with the supportive close — no score/penalty fields exist) bound (Hardening tab runs the real study_hardening: opt-in persisted, off by default, refusal receipt when off; contexts + script + drill plan/result live) bound (as webApp)