Skip to documentation

SPARC Instructional Cycle Specification

Dynamic instruction: October 12, 2026

Status: Implemented in the local working tree with isolated contract coverage. Both new lesson variants have been uploaded privately to localhost; browser acceptance is partial, with the observed repairs and remaining image-quality issue recorded. No deployment, commit, or push has occurred. The sections below this addition retain the history and specifications of the previous policies.

Rule family and policy routing

learning-components/units/sparcsession/sparcDynamicInstructionRules.ts contains a new rule family with student and agent variants. Policies are dynamic-instruction-student-v1 and dynamic-instruction-agent-v1, using adapterId: "sparc-autotutor-v1" and policyVersion: 1. Account routing retains these explicit policies for admins and rejects non-admin access. The trial-display runtime dispatches to the new family. Previous production definitions remain available; their move sets and selector targets are not replaced by shared-default changes.

The new rules share the existing evaluator and target-progression conditions. Evaluation updates expectation and misconception evidence; a separate production invokes instruction.feedback; selection and terminal handling require that response's saved feedback node. The dependency is expressed in production conditions, not an external sequence of controller calls.

Instructional moves and feedback

Move Components Total assistance in logits
instruction.dynamic.question Focused question 0
instruction.dynamic.explanation-question Explanation, question 1.8
instruction.dynamic.explanation-rich-question Explanation, worked example or figure, isomorphic question 2.77

All three apply to expectations and selected misconceptions. Misconceptions retain their distinct state representation and can interrupt an expectation under the existing conditions. The instructional destination for a misconception is its relevant correct distinction.

Feedback uses the actual prior problem, learner answer, and existing assessment. It identifies correct content and corrects the specific error or omission, explaining enough to understand the correction; it can state the correct answer when necessary. It does not automatically expand into a complete worked example, ask another question, or select the next move. Its acknowledgment and terminology instructions build on the existing assertion prompt. After saving feedback, the app publishes the accepted nodes through the existing surface update and awaits a render tick before the production engine continues. Feedback therefore does not wait for subsequent instruction generation. Final-answer feedback is saved before terminal handling, and the completion display waits until submission finishes. Tutor corrections remain context rather than learner evidence in the unchanged evaluator.

The student menu offers the three moves and a separate Move to the next KC navigation option. Choice events reuse the prior assessment and do not count as another answer. Automatic target selection excludes covered expectations and advances once the current goal is met. Explicit navigation retains the authored KC cycle and does not override completion or introduce a fourth instructional move. Saved choices remain visible as disabled selected buttons between feedback and instruction, including after reload.

Numerical and completion behavior

Initial operational knowledge is 0.2, with a fixed 0.2 floor. The agent's instructional target is fixed at 0.8: utility = -abs(expectancyLogit + assistance - logit(0.8)). Boltzmann temperature remains 0.1. The new agent productions do not ramp OET. The existing evaluator retains learner evidence; no forgetting or future-retention model has been introduced.

Completion preserves the admin cycle calculation. The competitive agent stops when no post-assessment expectation or misconception candidate is eligible. A triggered misconception ceases to be eligible when 1 - supportStrength >= coverageThreshold. The student stops when all expectation coverage goals are met and no misconception is eligible; its existing eligibility uses supportStrength >= misconceptionThreshold. At defaults, these retain the respective equality boundaries at 0.8 and 0.2. The general AutoTutor graduation calculation's maximum-turn condition is overwritten by the admin cycle and is not an operative cutoff for these new policies.

Primitives, assets, and resume

The generation service selects or generates rich support before producing the explanation and question. Display order remains explanation, support, question. Each component receives the selected target and actual support, including saved image pixels when present. A worked example demonstrates a complete case and may include a formula. A figure illustrates a model or relationship using Sunburst 2.5 and the shared situation library described below. It is a teaching figure, so the old supported-prompt requirement to omit a feature is not automatically applied. The AI chooses between the two rich forms pedagogically, with figures encouraged for models and worked examples for principles.

The following question uses an analogous case with the same underlying relationship or task structure. It receives the actual figure pixels when present, along with the description and explanation. Necessary question givens are included. Generation constraints and existing parsers validate composition and bounded output; there is no mandatory extra AI reviewer call, and these checks do not prove semantic accuracy.

The learner sees all parts of one composite in one tutor bubble, in component order, with one production diagnostic. Primitive nodes retain their separate persistence identities for retry. Only the question primitive may ask a learner question; explanation, figure description, and image brief contain teaching material only. This corrects the October 12 browser findings of separate boxes and a question repeated in the figure description; previously generated content is retained as history.

Generated text is plain text. The old generic all-components HTML-generation branch has been retired; intentionally retained component callers also use the dependent primitives, preserving their existing move identities and assistance values. Historical HTML nodes still replay. Private historical and incomplete supported-Prompt figures retain their owner access; new complete teaching figures are shared through the same admin-authorized reader. Generic asset downloads remain blocked.

Assessment, feedback, decision, and individual components use the existing canonical transition/node persistence. Component transitions end in :primitive:explanation, :primitive:richContent, or :primitive:question. A failed later step reuses earlier saved components and the accepted decision; retries do not rescore or select another move. Feedback readiness comes from its event-linked dialogue.utterance, not a second durable feedback-state representation. Figure failure remains explicit rather than silently becoming a worked example.

The seven-KC agent browser test exposed a 16 KiB history-extension failure when initial and updated model observations were bundled with the assessment. Competitive cycles now checkpoint the assessed evidence in :assessment and persist each KC's derived observations atomically in :assessment:model:<targetKey>. Evaluation publishes the combined facts only after those writes succeed. Retry reuses the accepted assessment and target updates; no second score, duplicated initial value, or duplicated gain is added. Existing records with observations inside the assessment remain readable without migration. The history budget is unchanged.

Seven-expectation package

C:\dev\mofacts_config\SPARC Dynamic Confidence Interval contains:

  • SPARC_Dynamic_Confidence_Interval_agent_TDF.json
  • SPARC_Dynamic_Confidence_Interval_student_TDF.json
  • SPARC_Dynamic_Confidence_Interval_agent_stims.json
  • SPARC_Dynamic_Confidence_Interval_student_stims.json

The original three expectation texts and three misconception texts are retained exactly. Four expectations add interval construction, the sample-size/margin-of-error relation, t-versus-normal method selection, and proportion-interval normal-approximation conditions. Each TDF has a new identity and uses all seven clusters; existing packages remain intact. Each stimulus file contains the same target definitions and complete symmetric graph of conceptual relationships, with node centralities derived from those authored strengths. The application requires each stimulus page to be referenced by its TDF, so the two conditions have separate matching files. These graph values are authoring choices, not new mastery prerequisites or a fixed worksheet sequence.

The canned opening remains the authored 95% confidence interval [42, 50] question. The original misconception wording retains those numbers, but evaluation interprets its defining meaning in generated cases. No worksheet problems, explanations, assets, or sequence are imported. The retained unit-level scheduler configuration is separate from the production-owned KC selection and assistance calculation.

Full implementation details and the local contract runner are described in the application's docs/sparc-instructional-cycle.md. Run full app typecheck and lint, plus node scripts/sparcAutoTutorRules.test.cjs --include-general-rules --include-client-contracts from mofacts/. This runner uses injected providers and history writers; it is not live Meteor, MongoDB, or AI-provider acceptance. A fresh npm run test:ci requires explicit authorization under the repository instructions.

Local verification for this revision: full app typecheck passed; lint passed with zero errors and the 28 existing bundled-package warnings; all 218 isolated SPARC/general/client tests passed across 21 suites. Both TDF/stimulus pairs passed the application's upload-time content contract locally and resolved to 18 agent rules and 16 student rules, with seven expectations and three misconceptions each. Archives contain the corresponding TDF and stimulus files. Browser evidence and its limits are recorded separately; these checks do not establish deployment.

Historical initial status (before the narrowed move-set revision below): Initial implementation is present in the application, with two separate reference lessons. Isolated contracts and Meteor integration pass. Provider-backed browser acceptance is partial: both cycles and all five primitives were observed; rich-output reliability, input labeling, and remaining acceptance cases are open. See browser acceptance evidence. Decision date: October 9, 2026. Implementation review: October 9, 2026.

Selection implementation, October 10, 2026: The working tree implements oet-boltzmann-v2 for admin AutoTutor accounts and now honors student-selected-v2 when selected by the package. Every non-admin account retains the deterministic reference. The numerical and history contract below incorporates the final discussion and supersedes the earlier logit-increment example. Verification for this revision is reported separately from the earlier cycle implementation.

Extend the existing SPARC production loop. Productions select moves and targets; primitive actions carry them out. Keep separate student-selected and agent-selected versions using shared primitives, and preserve the deterministic AutoTutor reference. The initial implementation calculates a passive probability from logit changes saved in response history; the competitive policy uses the underlying expectancy logit for selection. Keep the current AI scoring contract.

This document records the user's decisions. Component names below describe responsibilities; they do not authorize duplicate registries, new controllers, or parallel representations of existing state. Exact identifiers and field placement must reuse current contracts wherever possible.

Current test scope: four AutoTutor moves

Latest decision, October 10, 2026: Leave composite moves out of both test versions. The student menu contains exactly Pump, Prompt, Hint, Assertion, and Move to the next KC. Each instructional button selects its named move directly; there is no bundled AutoTutor response choice. The competitive agent considers only the same four moves for the current target. Existing model, assistance, OET, temperature, KC progression, scoring, generation, and feedback contracts are otherwise unchanged. Moving to the next KC means advancing between expectations within the same case, without a mastery gate for student choice.

The current packages use student-selected-v2 and oet-boltzmann-v2. Reimport the updated AutoTutorMoves-v2 ZIPs into the existing lesson identities before testing. Old v1 histories are retained separately; existing policy partitioning prevents their pending composite menus and decisions from being replayed under v2. No history is deleted or migrated. Composite primitives remain implemented for later work but are not loaded as instructional choices by these two production sets. The earlier composite plans and verification below are historical and do not expand this current test scope.

Architecture and approved simplifications

Prompt generation revision, October 10, 2026: The shared Prompt move uses prompt version v4. For a selected target expectation, ask one focused question seeking a short answer about a missing, substantive part: a conceptually important entity, property, process step, or technical concept. Make the requested information clear without supplying it or explaining the relationship the learner needs to establish. Ground the question in the expectation's conceptual content; opening-example details are used only when needed for understanding. For a selected target misconception, use the relevant correct expectation to identify the missing content needed to recognize or correct the misconception the learner actually expressed, without stating the correction or supplying an explanatory clue. Natural questions and brief completion requests are allowed; fill-in-the-blank form is optional. This changes the shared generation instruction used by agent-selected and student-selected Prompt productions; it does not change assistance values, scoring, selection, or TDF fields. Previously accepted tutor messages retain their recorded wording and prompt version.

  • Keep the production engine, working-memory facts, node renderer, canonical history, and replay mechanisms.
  • In the new competitive agent version, matching instructional productions compete by OET distance and Boltzmann probability, without salience. The winning production invokes the selected primitive in its THEN. Keep the existing deterministic AutoTutor version independently usable.
  • In the student version, a production invokes a menu primitive with predefined options in its THEN. A subsequent production matches the selected option and invokes the instructional primitive. The button press is a selection event, not a scored answer.
  • Both versions use the same primitive implementation for the same instructional output. There is no extra production layer just to realize a selected move.
  • Load only the selection productions belonging to the authored version. No authority evaluator, runtime switching, or choice driver is included. A fixed sequence of choices remains deferred.
  • Eligibility and target selection belong to productions and existing derived facts. Do not add a separate eligibility service or duplicate move catalog.
  • Extend existing history and replay state only as needed. Do not create a separate durable subsystem or mandatory record for assessment, request, preparation, and presentation.
  • Reuse existing event, decision, transition, target, and node identities. Do not prescribe an additional instruction-request identity when the existing identities suffice.
  • Save the logit-change vector with existing expectation/KC identities in the response record. Reuse scores, context, and versions already recorded; do not duplicate bounded inputs, before/after scores, or full context solely for this feature.
  • Use existing facts, productions, and page state to represent pending interaction. Do not introduce another interaction state machine.
  • Keep initial instructions consistent with the existing AutoTutor opening. No fabricated response is needed to initialize a lesson.
  • Remove the agreed pre-canonical support branches coherently during implementation. This does not authorize deletion of learner histories or a destructive migration.

Revised selection contract: OET, assistance, and production competition

Preserve deterministic AutoTutor alongside the new selector

The current deterministic AutoTutor behavior is an intentional supported reference, not an obsolete path or an automatic error-recovery substitute. Preserve the existing progressive-scaffolding-v1 lesson behavior, AI evaluation/generation, scaffold transitions, completion, and resume while developing the new selector. Keep current lesson policies working; do not silently reinterpret agent-selected-v1 or other saved policy identities as the new algorithm.

The reference continues to make its existing condition-driven choices without the new all-candidate utility comparison or random sampling. Low-temperature Boltzmann selection is a separate behavior: it approximates deterministic selection of the closest OET match, but is not a substitute for preserving the original AutoTutor sequence. Both paths reuse the production engine, primitive/action registry, rendering, provider, and persistence contracts; do not copy the tutor engine to preserve the reference.

Temporary rollout decision, updated October 10, 2026: For SPARC AutoTutor, authenticated admin accounts use the package's student-selected policy when specified; other supported AutoTutor policies resolve to the competitive system. Every non-admin account uses the preserved deterministic system. The Confidence Interval pair selects student-selected-v2 and oet-boltzmann-v2 in its respective referenced stimulus pages. This supersedes the earlier role-only override that made every admin lesson competitive. Resolve membership through the existing authenticated role contract; do not trust a lesson field, request flag, or client-visible control to establish administrator status. Carry an explicit resolved policy/version into the learning component rather than making it query Meteor account state.

Preserve the original authored package and its content. The runtime already supplies AutoTutor production sets; extend that boundary to resolve the account-appropriate implementation without rewriting uploaded content or duplicating packages merely for admin/non-admin delivery. Reuse existing policy/version and history identity contracts to record the effective runtime version. Do not silently reinterpret a persisted attempt under another algorithm. Account/role changes or a previously started reference attempt require explicit compatible resume handling or a separate attempt; do not reset or rewrite learner history. Exact version identifiers and resume handling are implementation decisions to resolve before rollout.

This account-based rollout does not introduce adaptive switching between student and agent authority, permit sampling to override an offered student choice, or route a failed new-system request into the reference. Preserve the reference for development/debugging and until an explicit later decision retires it; this revision does not authorize its removal. The app resolves the role at lesson delivery and rechecks it before submission; the server restricts competitive and student-selected history and provider requests to admins. The student next-target choice means moving between expectations within the current problem, using existing target identities, not advancing to a different case or unit.

Salience is removed from the new selection specification. Do not use it as an initial candidate filter, utility term, or tie-breaker. Rule IDs and declaration order must not favor an instructional alternative. Assessment, feedback completion, persistence, and stopping are prerequisites/control behavior, not competing instructional moves; express their dependencies through conditions and accepted state rather than numerical priority.

The current shared executor still orders by salience. That is an implementation fact, not the new selection contract. Do not globally delete or change that ordering under the reference path before verifying its dependencies. Any shared-executor removal must replace required ordering with explicit prerequisites and prove unchanged reference behavior. Keep the reference operational throughout the work; preserving it does not permit salience to influence the new competition.

Quantities and equations

For each eligible production activation bound to knowledge component/expectation k and move m:

Quantity Meaning and scale
theta_k Learner expectancy on the natural-logit scale: max(logit(initialExpectation), accepted history sum). The initial expectation of 0.2 is also its minimum; no separately stored expectancy accumulator.
a_m Fixed assistance effect of the move on the natural-logit scale. A finite real number, not a fraction constrained to 0–1. Positive assistance increases predicted success.
tau Current OET on the natural-logit scale. It is state advanced by authored production effects, not a globally fixed threshold or an external periodic schedule.
T Fixed positive selection temperature for the configured policy. This is independent of the language model's generation temperature.

Temperature is a shared parameter of the competitive selector, not an effect or separate value on each competing production. For this temporary rollout, keep it in the runtime-owned selection-policy configuration so an administrator can test the same existing package with a low temperature without editing/reuploading each TDF. Reuse existing controller parameter plumbing where appropriate; settle the exact key/location during implementation rather than create a second settings system or a new UI. Productions continue to own their individual OET increments. SPARC_COMPETITIVE_DEFAULTS.temperature in learning-components/units/sparcsession/sparcCompetitiveSelection.ts is the selector setting (initially 0.1). The provider generation temperature is separate.

predicted_logit(k, m) = theta_k + a_m
predicted_success(k, m) = 1 / (1 + exp(-predicted_logit(k, m)))

distance(k, m) = abs(predicted_logit(k, m) - tau)
utility(k, m) = -distance(k, m)

P(k, m) = exp(utility(k, m) / T)
          / sum_over_eligible_activations(exp(utility / T))

Use the additive assistance convention above; subtracting an IRT difficulty would use the opposite sign. Inverse logit returns a probability, not a logit. If OET is authored as a probability, convert it to a logit at the explicit owning boundary; do not change the meaning of the existing adaptive scheduler's probability-valued optimalThreshold field.

Use absolute distance, so equally distant alternatives above and below OET receive equal utility. A raw signed difference is not the utility: a common OET subtraction would cancel in softmax, and for a common target its expectancy would cancel too. Implement softmax with the usual maximum subtraction for numerical stability without changing these probabilities.

Lower positive T concentrates probability on the highest utility; higher T spreads probability toward uniform selection. Exact ties have equal probabilities, including tied best alternatives as T approaches zero. A small positive temperature is nearly deterministic, not an exact deterministic guarantee. Do not divide by zero or add a special zero-temperature mode without a separate decision. The preserved reference provides exact deterministic behavior without candidate utility comparison.

Corrected target boundary, October 10, 2026: Existing target progression first determines the instructional target. Stay on the active unfinished KC; choose the next ranked eligible target only when that cycle cannot continue. Preserve the existing detected-misconception interruption and resolution conditions. Boltzmann competition compares Pump, Prompt, Hint, and Assertion only for that selected target; it must never sample among unfinished KCs. Both agent policies share target-condition builders. Continuing a target preserves its cycle identity and updates its turn count, rather than starting a fresh cycle. Rank targets and compute cycle status from the same eligibility projection, including the competitive model's reversed-misconception completion threshold. Duplicate rule matches must not give a move extra probability mass; mixed-target competitive activations fail explicitly. Execute only the selected move's THEN. Student-selected next-KC choices remain available without mastery.

Boundary-fix verification: 178 isolated SPARC/general/client contract tests pass, including no-progress retention when another KC has a better utility, partial progress and serialized-history resume, transition at coverage, natural stop, and misconception interruption/retention/resolution. Full application TypeScript passes; lint passes with 28 existing warnings. No new Meteor integration run was performed. Assistance remains Pump 0, Prompt 0.6, Hint 1.2, Assertion 2.4; the proposed 0.2 expectancy floor and revised assistance values are not part of this fix. The existing v2 packages and saved history remain usable without a migration.

Live boundary check on localhost after restarting the supported hotfix watcher: resumed the existing five-turn test conversation without another reset. Its pre-fix active target was e3. A new weak answer ("I still don't know what to say about the true mean and this particular interval.") selected instruction.competitive.expectation.continue.assertion on e3, with 0/3 expectations covered. A subsequent correct explanation that the fixed mean either belongs to the computed interval or does not raised coverage to 1/3 and selected e2. This verifies retention and permitted completion-driven transition with the actual provider; it does not establish complete browser acceptance for the remaining lesson. The local application was healthy after the supported restart.

Productions themselves advance OET

The selected production's THEN advances its target's OET by 0.2 probability points, then invokes its instructional primitive. The decision saves that effect before provider generation. Selection uses the pre-firing OET; the update affects the next decision. Computation and storage use logits:

initial tau = logit(0.2)
tau_next = logit(min(0.8, inverse_logit(tau) + production_increment))
production_increment = 0.2 probability points for each initial instructional rule

This replaces the earlier illustrative +0.2 logits proposal. Keep unfinished targets' OET when attention changes. Reset a completed target to logit(0.2). Completion uses the existing configured threshold, normally 0.8. Control productions do not advance OET.

Progress does not gate, cancel, or skip the production's OET increment. Its effect emerges through the equation:

preferred assistance = tau - theta
change in preferred assistance = change in tau - change in theta

Equal changes in OET and expectancy on the logit scale offset. With no progress, the rising OET favors more assistance. Greater progress can favor less assistance. Actual discrete moves compete probabilistically; this does not prescribe a fixed assistance increment or require a separate progress-to-scaffold rule.

Keep OET and its production effects in existing working-memory facts/transitions and canonical history. Bind the OET effect to the same accepted decision as the chosen instruction: an accepted decision advances it once; losing/conflicting/unaccepted selections do not. A failed generation retry, duplicate delivery, uncertain-write recovery, or reload must neither resample an already accepted choice nor apply its increment again. The current accepted decision/output replay remains the owner; do not add an independent counter service, timer, event stream, or second accumulator for expectancy. Restoring the current OET must agree with accepted history.

Final parameter, target, and history contract

  • Shared runtime defaults: initial and minimum expectancy 0.2, initial OET 0.2, maximum OET 0.8, selection temperature 0.1. Reuse initialExpectation for the floor rather than adding a duplicate parameter. Convert probabilities with clamps 0.0001 and 0.9999.
  • Assistance logits live in the existing primitive definitions: pump 0, question 0, unsupported prompt 0.66, supported prompt 1.33, explanation/question 1.0, hint 2, rich/question 1.4, explanation/rich/question 1.8, assertion 2.4. The Prompt split was requested October 11, 2026. These are provisional pedagogical values, not calibrated estimates.

Unsupported Prompt has assistance 0.66 and supported Prompt 1.33. Supported Prompt uses two calls: the configured dialogue model plans the text and an aligned image brief, then Seedream 5.0 Flash (bytedance-seed/seedream-5-0-flash), routed through Seed on OpenRouter, generates one 1K figure with automatic aspect ratio. General image settings are in mofacts/common/lib/sparcPromptImage.ts; dialogue model settings remain unchanged. The figure may be an illustration, table, process, comparison, plot, or other appropriate visual. Its meaningful omission need not be a cloze blank. Generated raster bytes are private owned DynamicAssets; text and {assetId, description, displayWidth} persist on one dialogue node. Resume loads the saved image, and subsequent model calls receive the actual image as tutor context. Failed generation has no substitute. Both comparison conditions use this primitive; the deterministic reference sequence remains unchanged. See docs/sparc-instructional-cycle.md for identity, storage, and capability contracts. No new TDF fields, package upload, dependencies, or historical record migration are required.

Parameter-change live check: automated checks were skipped at the user's explicit request. A correct long-run-coverage answer advanced to e1 and selected Prompt with assistance 1, expectancy logit -1.39 (the 0.20 floor), and OET logit -0.41. The subsequent ambiguous answer, "The method for constructing the interval can change each time," raised displayed progress from 2/3 to 2.75/3; e1 expectancy became 1.1 logits (0.75), causing continuation with Pump. The initial claim that this proved a scoring bug was withdrawn after discussion with the user: the wording permits multiple interpretations. Earlier in the same run, "I don't know how many of the intervals would contain the true mean" received an inappropriate scope refusal; that observation remains unresolved.

Eight additional live responses, October 10: an explicit claim that biased selection of only large observations preserves coverage earned no additional credit; an on-topic random-sampling clarification was accepted (although its explanation was circular). An explicit individual-observations misconception triggered M2 and four consecutive repetitions produced Pump, Prompt, Hint, Assertion with assistance 0, 1, 2, 2.4 and OET probabilities 0.2, 0.4, 0.6, 0.8. Misconception expectancy stayed at the 0.20 floor and the target remained M2. Explicit correction cleared misconception support and returned to e1; a complete random-sampling/same-procedure explanation brought coverage to 3/3 and replaced the response input with Continue. No code was changed or automated checks rerun during these probes. This is one cumulative conversation, not an estimate of scoring reliability. Generated Pump and Prompt language sometimes supplies substantial target content, so move wording merits separate review.

  • Record logit(0.2) once as the first observation for each target. Subsequent accepted observations store new oriented logit minus the prior raw history sum. For the first evaluation this subtracts the seed, not the old AI zero. Theta is the greater of this sum and logit(0.2); use the raw sum, never the floored value, when calculating the next observation. The floor therefore applies to new and replayed histories without rewriting observations or delaying improvement after repeated low scores. There is no stored theta accumulator. Existing expectation coverage remains nondecreasing; misconception support retains its bidirectional scoring.
  • Expectation orientation is coverage. A misconception becomes eligible only after its detector triggers; its orientation is 1 - supportStrength. Preserve raw AI meanings and authored misconception content. Do not invent a KC mapping or a separate correction model.
  • The same rules and utility apply to both target kinds. Completion removes eligibility; reverse expectancy reaching the configured completion threshold completes misconception work. A later detection can reintroduce it.
  • Ordinary durable instructional.modelObservation and instructional.oet working-memory facts live in the existing assessment/decision transitions. Old unseeded histories retain their old interpretation. No destructive migration.
  • The effective policy is recorded with the attempt. Resume only the latest compatible attempt; a policy change starts separately without rewriting history. Admin delivery honors the student-selected package and otherwise selects competitive AutoTutor; non-admin delivery remains deterministic.
  • Temperature belongs to shared policy configuration. Each rule owns its OET increment in THEN. Move assistance belongs to the existing move definition. The two existing Confidence Interval packages select the two new versions; no settings UI or choice driver is added.

Follow-up implementation and acceptance requirements

  1. Establish deterministic reference fixtures/traces and retain the original reference package and policy. Document its ordering dependencies before changing shared execution. Verify the same unchanged package resolves to the new system for admins and the reference for every non-admin role; do not broaden access to unrelated admin capabilities.
  2. Extend existing selection contracts for the account-resolved competitive policy: eligible activations, history-derived expectancy, assistance logits, current OET, fixed shared temperature, and production OET effects. Preserve the meanings of existing stored fields and policy IDs and explicitly retain effective runtime policy identity on resume.
  3. Implement distance utility and Boltzmann selection in the owning learning component, without salience or lexicographic preference. Keep control prerequisites outside instructional competition and share existing action execution.
  4. Integrate decision acceptance, OET effects, and replay through existing history ownership, without duplicate updates or random reselection after acceptance. Keep the original AI scoring contract unchanged.
  5. Verify both paths side by side: unchanged deterministic AutoTutor traces; equal-utility probabilities; low/high-temperature behavior; changed expectancy offsetting the same OET increment; no-progress escalation through authored effects; candidate-order independence; duplicate/conflicting choices; generation/write failure; reload; and separate student/agent stopping behavior. Exercise real browser paths after appropriate isolated and Meteor verification, with fresh authorization for each test:ci invocation.

Earlier acceptance evidence below applies only to the initial implementation. It does not verify this revision. New selection failures must remain visible in their selected policy; they must not silently route to the deterministic reference.

Initial instructional primitives

Implement all four composite outputs and include the existing AutoTutor response primitive in the initial set. A composite is one primitive invocation, with shared rendering and generation helpers where appropriate.

Instructional primitive Ordered output Initial fixed assistance guess
Question Question 0.00
Explanation and question Explanation, then question 1.00
Rich content and question Rich content, then question 1.40
Explanation, rich content, and question Explanation, then rich content, then question 1.80
AutoTutor response Existing production-selected AutoTutor response, including its applicable acknowledgement, feedback, scaffolding, and elicitation Per selected move: pump 0, prompt 1, hint 2, assertion 2.4

These numbers describe the initial implementation's provisional hard-coded metadata, not calibrated estimates or claims about relative instructional effectiveness. They are not inputs to its passive probability calculation. For the revised competition policy, assistance instead denotes a real-valued logit effect as specified above; do not treat this table's original 0–1 range or its ordering as calibrated selection parameters. Preserve existing reference behavior while choosing those parameters.

Rich content means material such as a worked example, table, image, or figure. It is not restricted to an image. Use the existing SPARC node/rendering contracts for the selected form and extend them coherently where necessary. A primitive must produce the requested supported form; it cannot silently replace a failed figure or example with unrelated text. Questions come last in the four composites.

The primitive receives the target and instructional context bound by the firing production, including the learner evidence and preceding instruction already available. It returns the corresponding nodes through the existing runtime contract. It does not independently decide whether the student or agent has authority, choose a different target, or run a second instructional controller.

How AutoTutor fits

The existing AutoTutor response belongs beside the four composites. Reuse its existing generation action, move definitions, and node construction. Pump, prompt, hint, assertion, and other existing move distinctions remain production-selected parameters of that response path; this project does not recreate them as a separate tutor engine.

For a student request for an AutoTutor response, the applicable selection production supplies a valid existing AutoTutor move and target from the available facts. For an agent-selected response, the instructional production supplies that decision directly. Both invoke the existing response primitive. Existing action/snapshot checks must support the later selection event while retaining its connection to the original response evidence; do not rescore the answer to manufacture a matching snapshot.

An AutoTutor invocation produces its selected response. Choosing it does not switch the whole lesson into an agent-selected version. At the next applicable choice boundary, the student version offers its menu again. AutoTutor's own response content remains intact; no generic wrapper adds another feedback message or another question to it.

The menu primitive and next-target action are control actions, not additional composite instructional outputs. The menu displays the options supplied by its production and returns the selected option. The next-target action updates the active target through the existing target machinery; subsequent productions determine instruction there.

Selection, feedback, and stopping

The initial student menu exposes the applicable instructional choices above and a next-target choice. The offering production supplies their bindings and order. Availability follows actual prerequisites, such as having a usable target and the context required by an AutoTutor response. Do not introduce a separate policy that silently removes choices according to the passive probability.

Advancing to the next target is a student choice. It is not a question, does not assess knowledge, and does not wait for the current target to satisfy the agent's progression conditions. Reuse existing target identities and graph/order information, but do not reuse an unfinished-only candidate filter for student progression or continued practice. Already completed targets remain usable in the student version.

Situation Student-selected version Agent-selected version
Opening Use existing opening instruction, followed by student selection at the applicable boundary. Use existing opening instruction and agent productions.
A question is answered Complete the node's own response handling and any feedback, then offer the menu when that node finishes. Complete the node's own response handling and any feedback, then allow the applicable selection productions to run.
A drill/test node provides feedback Show its built-in feedback before continuing. The selected instructional output supplies the next question. Show its built-in feedback before the next selected instruction.
A test-only node provides no feedback Proceed directly to the menu. Do not invent a feedback step. Proceed directly to the next production-selected action.
Learner selects next target Advance independently of automatic mastery/progression gates, then continue through the student's productions. Agent progression remains governed by instructional productions.
All expectations are fully done Continue offering usable practice choices. Completion does not terminate the lesson or disable practice. No unfinished target remains selectable, so the instructional loop naturally stops.
Learner leaves Use existing navigation back to the main menu. Use existing navigation.

Feedback belongs to the node that owns the submitted response. Preserve its existing feedback and continuation behavior. There is no universal feedback primitive, extra AI feedback request, or new acknowledgement screen inserted between every answer and the next action. The menu itself is never evaluated as an instructional question.

The agent's natural stop is a valid no-work outcome, not an error, an instruction to retry indefinitely, or an irreversible lesson closure. The student version remains usable after all expectations are fully done and ends when the learner leaves for the main menu. Do not use mastery or an AutoTutor turn limit to lock student response controls. Runtime protection against a faulty production loop remains distinct from pedagogical completion.

Initial implementation flow

SPARC Instructional Cycle Specification — diagram 1

This diagram records the initial implementation's two separate authored versions, not a runtime authority decision. Each node completes its own feedback/continuation behavior before the next selection boundary. In that implementation the passive model has no arrow back to instruction. The approved competitive extension above adds history-derived expectancy to selection and production-driven OET effects; it leaves the deterministic reference and student choice intact. An ordinary exercise without AI expectation updates does not fabricate an AI observation merely to populate the model.

Common description of eligible instruction

An instructional choice consists of a registered primitive, target, and its required arguments/context. Reuse the existing move definitions, instructional decisions, and production action contracts for that description. The student menu is one presentation of production-defined choices; agent production competition is another way to select an invocation.

The common description does not imply identical IF conditions. Agent rules use instructional facts and automatic target preferences. Student selection rules match a current offered option. Student advancement must not inherit the agent's mastery gate. Different target bindings may require different productions; do not add a second registry merely to describe those bindings.

The menu's THEN options bind to permitted primitive invocations or the next-target action. Labels are display text, not executable instructions. Accept a selection only if it matches an option in the currently pending menu; a stale click or modified payload cannot select an arbitrary target or primitive. Reuse existing node/event identity to link the selection to that menu.

Existing instructional.candidate facts describe targets. Keep that meaning; do not reinterpret them as a duplicate catalog of menu options. Use shared production helpers for genuinely common prerequisites, while preserving the intentional differences between the two versions.

Initial passive probability calculation

This section describes the preserved student/fixed-agent observation contract. The competitive policy uses the seeded history contract above; its empty target history starts at 0.2 rather than 0.5.

Keep the current AI expectation-scoring behavior. For each expectation updated by an accepted evaluation, compute the difference between the new and old logits using natural logarithms:

bounded(p) = min(0.9999, max(0.0001, p))
logit(p) = ln(p / (1 - p))
delta = logit(bounded(new)) - logit(bounded(old))

response history stores the delta vector with existing expectation/KC identities
z = sum of the relevant deltas supplied from history
probability = 1 / (1 + exp(-z))

Only the logit calculation uses the bounds. Preserve the original expectation values and their current meaning. Validate the existing numerical input contract; bounding valid endpoint values is not a repair for malformed input.

The existing response history is the source of truth. There is no stored accumulator, independently initialized model state, extra scored-practice event, separate collection, fitted gain, assistance coefficient, or required prediction snapshot. The probability function sums the relevant history using existing learner, model-target, and context scope. An empty sum gives probability 0.5 by calculation.

The history adapter and probability context must expose these deltas for both live and resumed histories. Existing correctness/outcome fields retain their meaning; do not put a logit delta in a correctness field to pass an outcome-only reader. No model term or rule consumes the resulting probability to change instruction in this first implementation.

This initial passive feature is complete when the intended changes are recorded once, reach the probability function, and produce the same calculation from the same history. The approved competition revision now specifies instructional use of its underlying logit sum for the new policy only. Preserve history-derived calculation, the existing AI scoring contract, and unchanged deterministic reference behavior; predictive calibration remains separate work.

Events and durability using existing mechanisms

There are two relevant interaction inputs: an instructional answer and a menu selection. A selection does not cause another assessment of the preceding answer. Output nodes and pending menu state use existing SPARC transitions and replay. These requirements extend those mechanisms; they do not establish separate workflow stages or a general transaction framework.

Existing boundary to extend Required behavior
Response acceptance/history Save accepted expectation changes and their delta vector together. A later menu or content-generation retry must not duplicate that observation.
Page state and replay Retain the current offered options and restore the same menu after reload. Retain accepted generated nodes and restore them without regeneration. Store only context not already recoverable from existing state/history.
Selection acceptance Accept at most one selection from a given pending menu. Repeated clicks and conflicting concurrent selections cannot create two accepted instructional decisions.
Primitive invocation/output Preserve the accepted selection during a failed generation attempt. Retry under the existing decision/event identity. Accept at most one output for that invocation.
Resume Restore the same authored version, current target, pending interaction, and accepted output. Do not re-evaluate a response or silently switch selection versions.
Failure Surface the failure at its existing owner. Do not substitute another primitive, choose for the student, or generate replacement model evidence.

Use existing event/decision/transition identities for duplicate handling, scoped to the learner and attempt. Identical retries return the accepted result; conflicting reuse of the same identity fails explicitly. Client-side button disabling alone is insufficient.

The app-owned history writer currently has worksheet-specific duplicate handling; general SPARC replay does not by itself guarantee these properties. Extend the relevant writer and readers coherently without copying worksheet-only metadata into dialogue records. Reuse current canonical payloads and record an additional field only when an identified durability requirement cannot otherwise be met.

Generated, persisted, and displayed are distinct evidence claims, but that distinction does not require new presentation records or a presentation-tracking subsystem for this project. Use existing rendering/history instrumentation where present. A stored output is not proof that a learner read it.

Where the code changes belong

The following mapping comes from source inspection, not runtime verification. Paths are relative to the MoFaCTS repository; the SPARC filenames in the first column are under learning-components/units/sparcsession/ unless otherwise stated.

Owner Change
sparcProductionRuleEvaluator.ts Preserve the production engine and registered asynchronous action mechanism.
sparcAutoTutorRuleRuntime.ts Remove the assumption that every accepted response must immediately evaluate and generate exactly once. Support a pending menu, a later selection invoking a primitive, and an agent no-work outcome. Keep existing AI evaluation/generation behavior for the existing response path.
sparcProgressiveScaffoldingRules.ts, sparcInstructionalControl.ts, adapter registration Provide the two selection rule sets through existing configuration. Keep target/move decisions in productions. Do not add an authority controller.
sparcInstructionalCandidates.ts and existing target helpers Preserve the agent's unfinished-target logic where applicable. Supply student target bindings that permit advancement and practice of completed targets.
sparcMoveDefinitions.ts, generation helpers, sparcDialogueTurnNodes.ts Reuse AutoTutor generation; implement the four composite primitives through shared component helpers, ordered nodes, and existing prompt/output validation. Put the provisional assistance constant with the owning primitive.
sparcTrialDisplayRuntimeBridge.ts, SparcSessionUnitEngine.ts Distinguish choice input from instructional answers and connect both to the applicable productions. Preserve node-owned feedback and continuation.
sparcControllerDerivedFacts.ts and completion rules Make no-target agent stopping valid and prevent fully-done state from terminating student practice. Trace existing completion consumers before changing stored semantics.
sparcLearnerResponseScoring.ts boundary; canonical response history Derive the delta vector from accepted before/after expectation values without changing AI scoring. Store it with the response.
learning-components/runtime/modelPracticeHistoryExchange.ts, learning-components/models/adaptive-logistic/probabilityCalculation.ts Carry the relevant history deltas into the probability function. No separate accumulated state or model-update event.
sparcStateReplay.ts; app sparcRuntimeState.ts, sparcAutoTutorRuleCommit.ts Reuse transitions/replay to restore pending choices and accepted content; prevent repeated effects on resume.
mofacts/server/methods/analyticsMethods.ts and canonical history validation Extend authorized history acceptance and duplicate/conflict handling where required. Keep pure computation in learning components.
mofacts/client/views/experiment/svelte/components/SparcNode.svelte and existing node contracts Render menu choices and composite content with current UI conventions. Preserve keyboard use, focus, semantic labels, and announcements.
Pre-canonical branches in sparcInstructionalControl.ts and sparcAutoTutorRuleRuntime.ts Remove the agreed obsolete support and dependent tests/docs without deleting stored histories. Retain the current canonical path.

Before introducing a field or identifier, search the owning and adjacent modules and, for authored contracts, C:\dev\mofacts_config. Update app-owned upload validation/schema and dependent content contracts together. The config repository remains passive storage. The existing AutoTutor Confidence Interval lesson is a practical initial fixture; choosing a different reference lesson is not a new architecture prerequisite.

Initial implementation acceptance and verification

These criteria describe the first implementation and its preserved reference behavior. The approved competitive extension has additional acceptance requirements in the revised selection contract above; its explicit use of expectancy supersedes the passive-only restriction for that new policy.

  1. Each of the four composites produces the specified order, with its question last; rich content includes the supported example/table/image/figure forms. AutoTutor uses its existing response primitive without duplicate feedback or an appended generic question.
  2. Equivalent student and agent decisions invoke the same primitive with the same target/context. Each version loads only its own selection productions; no choice driver or authority switch exists.
  3. The menu shows its production's bound options. Selection is never scored as an answer. A student can move to another target before mastering the current one.
  4. A feedback-bearing node completes its built-in feedback before continuation. A test-only node reaches the menu directly. No extra feedback stage is inserted.
  5. With all expectations fully done, the agent has a valid natural stop and the student can continue practice until leaving through existing main-menu navigation.
  6. A change from 0.50 to 0.75 gives approximately +1.098612; the reverse gives -1.098612; unchanged values give zero. Source endpoints use the specified bounds without altering stored expectation values. Empty history yields 0.5.
  7. The probability function receives only the relevant accepted deltas and gives the same result from live and reloaded history. No separately persisted total exists, and instruction never reads this new prediction.
  8. Adding the passive calculation leaves existing AI requests/scoring and agent instructional choices unchanged. Separately verify the explicitly requested progression/stopping changes in the project versions.
  9. Double submission, repeated clicks, stale menus, concurrent choices, uncertain writes, reload, and failed generation produce no duplicated accepted observation or instructional action. Resume restores accepted content and pending choice bindings.
  10. Current canonical histories remain supported. Removal of pre-canonical support fails explicitly for unsupported histories; no destructive data operation is part of the work.

For implementation, run full app typecheck and lint; regenerate and inspect schemas when authored contracts change. Use existing pure component tests for arithmetic, rules, and replay. Persistence and Meteor integration require a supported environment; each npm run test:ci invocation requires fresh explicit authorization. Rendered UI verification must cover the menu and feedback sequences, not just generated data. No Docker build, deployment, or data migration is included.

Review authorization and the security-surface contract if history methods change. Preserve authored/interface language distinctions and menu accessibility. Update concise public authoring docs and this wiki specification as the implementation becomes verified. Report source inspection, tests, rendering, and deployment as distinct evidence levels.

Initial implementation coding plan

Plan provenance: This was the plan for the initial implementation, whose results and open acceptance items are recorded below. The specification was committed and pushed before this plan was added, at wiki commit cd9ab0e6270e39957405474592cb72cd568005b4. The OET/Boltzmann extension is now implemented in the working tree under the final contract above; its verification is tracked separately.

Implement the following five steps in order. Each step must leave its touched contracts coherent and pass its applicable checks before the next step builds on it. The checks in step 5 combine the completed paths; they do not defer unit, persistence, or schema verification from the step that changes them. Commit boundaries should follow working changes, not split a writer from its required reader or publish a lesson before its runtime is available.

Step Deliverable Depends on Completion evidence
1 Passive expectation-logit calculation connected to durable response history Existing AI scoring and canonical history Recorded deltas reach the probability function live and after reload; current scoring and selection are unchanged.
2 Four composite instructional primitives beside the existing AutoTutor response Existing action, generation, and node contracts Each registered primitive produces valid ordered nodes; both selection routes can use the same invocation contract.
3 Complete student-selected and agent-selected instructional cycles Steps 1 and 2 Menu events, node feedback, next-target choice, stopping, persistence, and resume work together.
4 Authored lesson versions, canonical-path cleanup, and documentation Step 3 Both reference versions load through app validation; obsolete support is removed without losing the current canonical path.
5 Integrated acceptance review Steps 1-4 and their passing checks All acceptance scenarios have explicit results, including rendered behavior and supported persistence verification.

Step 1: Connect the passive calculation from response to history to probability

Start with a bounded trace of the actual writer and reader chain. Confirm where the accepted expectation values are available, which existing identities scope a response and its targets, how history reaches the model on submission and resume, and which probability values are consumed by current selection. Resolve concrete field placement in the existing SPARC history extension before editing. Search adjacent code and config contracts for an existing equivalent; do not add a new name for the same concept.

Primary owners: sparcAutoTutorRuleRuntime.ts, sparcLearnerResponseScoring.ts, sparcSessionContracts.ts, sparcStateTransitionHistory.ts, and sparcModelHistoryExchange.ts; learning-components/runtime/historyEnvelope.ts, modelPracticeHistoryExchange.ts, and model identity contracts; learning-components/models/adaptive-logistic/probabilityCalculation.ts; the app commit/history-loading services and mofacts/server/methods/analyticsMethods.ts where acceptance changes are needed.

  1. Derive the bounded logit differences from accepted before/after expectation values. Keep the existing AI request, response interpretation, and expectation updates unchanged. Compute the vector locally in the learning component.
  2. Extend the existing canonical response record with that vector and its existing expectation/KC bindings. Make the history type, validation, serialization, writer, and reader agree. Preserve current records that legitimately predate this optional observation: no fabricated historical deltas and no data backfill.
  3. Trace and extend the history projection end to end. Current dialogue transition records do not automatically qualify as scored practice records. Give their recorded deltas an explicit supported route through existing history/model interfaces without inventing correctness, creating another scored-practice event, or copying records to a second store. A response may update multiple expectations; project each contribution using its own existing target identity, rather than attributing the whole vector to the selected instructional target.
  4. Expose the relevant deltas to the probability function and evaluate the agreed sum-only function on accepted history. Connect both the live and resumed paths. Keep this result passive: do not replace the active probability function, write it into scheduling estimates, or feed it into production conditions. Use existing computation/query interfaces; add no model service or server computation method.
  5. Ensure retries cannot accept the same response contribution twice. Reuse existing scoped source-event/transition identities at the history acceptance boundary. Add only the supporting uniqueness/query changes that this contract requires, and retain authorization and conflicting-write checks. Do not rely solely on an in-memory set or UI disabling.

Verify before moving on: arithmetic including bounds, decreasing inputs, unchanged values, empty history, and invalid values; multiple expectations and exclusion of unrelated learner/target history; one accepted observation across retries; identical live/reloaded results; unchanged AI requests and instructional decisions. Extend the existing history-exchange, SPARC state-transition/runtime, and server history tests as appropriate. Verify the actual probability-function input, not just the helper's numerical output.

Done when: one existing response record carries the required model input, the probability function actually receives it, and the existing instruction path has no dependency on the passive result. No accumulator, additional record stream, or prediction UI exists.

Step 2: Implement the shared instructional primitives

Primary owners: sparcMoveDefinitions.ts, the existing action registration/runtime and utterance request contracts, sparcDialogueTurnNodes.ts, learning-components/trial-displays/sparc/ node contracts, and app sparcControllerDialogueOpenRouter.ts and SparcNode.svelte where generation/rendering need extending.

  1. Map the five instructional entries in this specification onto the existing registry/action contracts. Retain the AutoTutor response action and its move definitions. Register each of the four new composites as one primitive, reusing component helpers rather than duplicating four generation pipelines.
  2. Define each invocation's required target/context and each component's accepted node/output schema. Resolve actual existing types and names here; do not add a second move-description registry. Keep pedagogical composition in learning components and app rendering/external-call ownership in the app.
  3. Implement question, explanation, and rich-content construction using current providers and rendering capabilities. Cover worked examples, tables, images, and figures with supported representations. Preserve existing output sanitization and content validation. Do not install a new dependency or introduce a separate asset-generation service by assumption.
  4. Assemble the four exact component sequences and attach the provisional assistance constant at the owning primitive. Retain the question node's existing answer/feedback behavior. AutoTutor retains its own response content and receives no added generic question or feedback wrapper.
  5. Connect generated content to existing node identities, transitions, and replay. Validate the complete selected output before accepting it as the turn. Keep a generation failure explicit and retain the selected decision for retry; no substitute primitive or partially accepted composite.

Verify before moving on: valid output and deterministic component order for each primitive; required context and malformed-output rejection; representative rendering of all rich-content forms; preservation of AutoTutor output; and shared action invocation for identical move/target/parameters. Extend existing move-definition, dialogue-node, semantic-node, provider-contract, and runtime tests where they own these checks. Use deterministic provider substitutes in tests, not in runtime behavior.

Done when: all five instructional primitives are callable through the existing production action mechanism and have coherent generation, node, and replay contracts. No new authored learner workflow is exposed with unfinished event handling.

Step 3: Connect the two complete selection cycles

This is one integrated feature step because offering a menu without safe selection, feedback continuation, and resume would leave broken wiring. Use focused internal changes as needed, but complete the whole path before treating the student version as usable.

Primary owners: sparcAutoTutorRuleRuntime.ts, sparcProgressiveScaffoldingRules.ts, sparcInstructionalControl.ts, adapter registration, sparcInstructionalCandidates.ts, sparcControllerDerivedFacts.ts, sparcTrialDisplayRuntimeBridge.ts, SparcSessionUnitEngine.ts, and sparcStateReplay.ts; app sparcAutoTutorRuleCommit.ts, sparcRuntimeState.ts, node event/rendering code, and the existing authorized history writer.

  1. Extend event-specific execution results within the existing contracts. A response may complete with a pending menu; a selection may generate instruction without reevaluating the preceding answer; an agent with no unfinished target may complete without generating another move. Retain strict validation of the action/decision/target actually invoked rather than simply relaxing all existing checks.
  2. Implement the menu primitive with production-supplied ordered options. Store its pending state using existing facts, nodes, and transitions. Translate the button event separately from an instructional answer, and bind it to the current offered option.
  3. Register separate student and agent selection rule sets using existing authored configuration. Student selection productions and agent instructional productions call the same primitives. Resolve AutoTutor's selected move through productions using the retained evidence; selecting AutoTutor never changes the loaded version.
  4. Implement the next-target option with existing target identities and graph/order information. Remove automatic mastery gates from the student action and permit continued practice of completed targets. Resolve a choice against the menu's retained binding so a delayed click cannot advance elsewhere. Keep agent target eligibility governed by its own productions.
  5. Connect selection boundaries to the owning node's existing continuation. Feedback-bearing nodes finish their feedback before the next menu/action; test-only nodes continue immediately. Preserve the existing opening and main-menu navigation. Do not score button presses or insert a universal feedback step.
  6. Implement the specified stopping distinction. No selectable unfinished target is a valid agent stop. Student menus remain usable after full completion; do not let completion summaries or read-only response flags disable continued practice. Trace app progress/resume consumers so a changed production is not overridden elsewhere.
  7. Complete menu consumption and output acceptance through the same history owner established in step 1. Competing selections from one menu must contend on one acceptance identity, even when their button event IDs differ. Reuse existing decision/event/transition identity for subsequent output acceptance. Restore pending menus and accepted content on reload, and retry failed generation without another assessment or accepted choice.
  8. Preserve keyboard operation, focus, labels, and announcements. Reject stale or tampered options at the owning boundary, retain server authorization, and update the security-surface contract if the server interface changes. Keep data access bounded and use the required supporting index rather than broad history scans.

Verify before moving on: first menu and every option; both versions invoking the same primitive; early next-target selection; feedback and no-feedback nodes; completed-target practice; agent natural stopping; AutoTutor selection without a version switch; duplicate response, double click, stale menu, concurrent different choices, failed generation, uncertain history write, and reload at each existing acceptance boundary. Include the app service and server boundary in verification, not just the production evaluator.

Done when: both versions execute complete loops with the specified feedback and stopping behavior, and pending choices/accepted outputs survive retries and resume without duplicate effects. No authority evaluator, fixed-sequence driver, second state machine, or compatibility fallback was added.

Step 4: Finish authoring contracts, canonical cleanup, and documentation

Primary owners: app SPARC authoring validation/schema and registry; the two identified pre-canonical support branches and their readers/tests; C:\dev\mofacts_config\AutoTutor Confidence Interval; concise application docs and this wiki page.

  1. Prepare distinct student-selected and agent-selected reference lesson versions using the existing Confidence Interval content and shared targets. Keep the current working lesson available as the regression reference; do not overwrite it with a different selection behavior. Put authored content in the existing config repository, not a new runtime component or manifest system.
  2. Make version registration, authored options, primitive references, node schemas, and app-owned upload validation agree. Regenerate schemas when their source contracts change and inspect the resulting diffs. Validate by exercising MoFaCTS upload/load boundaries; do not turn passive config storage into a validation service.
  3. Remove the agreed pre-canonical branches in sparcInstructionalControl.ts and sparcAutoTutorRuleRuntime.ts, together with obsolete dependent code/tests/docs. Trace their consumers before deletion and perform removal alongside the affected earlier step if that avoids temporarily extending obsolete code. Keep current canonical histories readable; unsupported pre-canonical histories fail explicitly. No destructive migration or historical record rewrite is part of this step.
  4. Document the two authored versions, five instructional primitives, production-bound menu options, next-target behavior, feedback ownership, stopping/resume behavior, and the passive history field. Put concise contributor/authoring contracts in the app docs and detailed explanation here. Update AGENTS.md only if an actual workflow or ownership rule changes.

Verify before moving on: both reference versions load with only their intended selection productions; unknown primitives/options fail at the app boundary; generated schema diffs match intended changes; existing canonical examples replay; obsolete support references are removed; and current AutoTutor regression behavior is retained except for the explicitly scoped new-version behavior.

Done when: the implementation can be exercised from real authored content, its public contracts are documented, and removed legacy support has no hidden remaining callers. App and dependent content changes must be delivered in compatible order; do not publish content requiring unavailable runtime capabilities.

Step 5: Verify the complete instructional cycle and hand off

Use the ten acceptance scenarios above as the final checklist. The implementation results below distinguish isolated contracts from live integration and presentation.

Verification Required evidence and execution boundary
TypeScript and lint Run npm run typecheck and npm run lint from C:\dev\MoFaCTS\mofacts for each completed code step with applicable changes. No per-file typecheck substitute.
Pure SPARC rules/runtime The existing runner is node scripts/sparcAutoTutorRules.test.cjs --include-general-rules from mofacts/. Extend its suite list for relevant pure tests if necessary using the existing loader; it currently covers a subset, not all SPARC tests. Do not add a new test framework.
History/model arithmetic and replay Exercise the appropriate existing pure tests and the complete live/reload adapter path. A numerical helper test alone is insufficient. Ensure added tests are included in an actual runner.
Schema and authored contracts Run npm run generate:schemas when required, inspect generated diffs, and verify both lesson versions through app-owned validation.
Persistence and Meteor integration Use CI or another supported Meteor test environment for authorization, duplicates, competing choices, and resume. Each npm run test:ci invocation needs fresh explicit authorization. Pure tests are not database-concurrency proof.
Rendered learner behavior Exercise both versions, all five primitives, rich-content forms, feedback/no-feedback continuation, early next-target selection, full-completion behavior, keyboard use, and reload. Distinguish generated nodes from observed presentation.
Regression Compare the existing AutoTutor reference before/after the passive-model addition and confirm unchanged AI scoring and instructional selection. Separately check the intentional behavior of the new versions.
Final change review Check diffs for duplicate state/catalogs, unneeded services, silent substitutes, leaked learner data, accidental generated files, and unapproved dependencies. Confirm only intended files changed.

Required failures block staging/commit/push unless the user explicitly accepts the reported failure and risk. If a supported integration or rendered check cannot run, identify it and retain that incomplete status; do not claim complete delivery from source inspection. No production data, deployment, Docker build, or release-confidence claim is needed for this plan.

At handoff, report implemented steps, exact checks and results, any remaining integration or rendering gap, compatibility/documentation impact, and unrelated changes preserved. The present request authorizes committing and pushing this specification and plan; it does not itself execute the coding steps or authorize future code publication/deployment.

The initial catalog, feedback ownership, stopping behavior, and history-derived model remain the baseline. The approved selection revision supersedes the initial assistance-scale and passive-only restrictions for the new competitive policy and specifies production-driven OET changes. Exact field placement and function/rule identifiers are resolved within the owning implementation step using current code. Runtime authority switching and a fixed-sequence driver remain deferred; the deterministic AutoTutor reference remains supported.

Implementation and acceptance evidence

The application changes are uncommitted. The two reference packages are added in the existing config repository, and the original Confidence Interval package is unchanged. No application/content commit, push, deployment, destructive migration, or learner-history rewrite has occurred. The later browser walkthrough uploaded the two reference packages to the local hotfix application and created synthetic test histories there.

Step Implemented contract Evidence and limits
1 Optional sparc.expectationLogitChanges entries use {clusterKC, delta} in accepted response history. The app's live and hydrated history projection calls calculateExpectationProbabilities. No persisted prediction or accumulated state. Bounds, signed differences, empty history, identity scope, duplicate/conflicting observations, and identical app live/hydrated results pass isolated tests. AI scoring/provider regression tests pass.
2 Four component primitives plus the existing AutoTutor response share the move lookup, external provider, and node rendering. Component order and all supported rich forms pass node contracts. Actual provider contract tests cover all four schemas. Unsupported rich elements, active HTML, and invented image assets fail. Rich-HTML sanitizer check passes. Svelte surface compiles without warnings. These are not rendered learner observations.
3 Separate student-selected-v1 and agent-selected-v1 rule sets; production-defined menu; selection events; shared primitives; early next target; covered-target practice; natural agent stop. First menu, all control paths, selected AutoTutor, repeated practice, stale/conflicting choices, same-choice replay, failure/resume, and app commit-service tests pass. Student AutoTutor preserves the offered target; automatic target interruptions belong to the agent set.
3 durability Assessment and delta vector are saved together. All choices, including next target, contend on the same decision identity. Accepted decisions survive generation failure; outputs replay without regeneration. Isolated method tests exercise concurrent duplicate insertion, conflicting selections, and authorization. The Mongo _id uniqueness boundary supplies arbitration; no new index/collection. Live Mongo concurrency remains unverified. Reload restores an uncertain write from durable history; no substitute output or score is fabricated.
3 feedback Composite questions use the current free-response/test-only input; AutoTutor retains its own feedback and elicitation. No generic feedback step is added. Test-only response-to-menu and AutoTutor output-preservation contracts pass. Existing ordinary SPARC drill/test response rules remain unchanged. A rendered drill/test-to-cycle continuation scenario has not been established; this acceptance item remains open.
4 Shared policy-ID validation, two separate authored packages, explicit rejection of pre-canonical instructional focus/scaffold state, public documentation. Both new reference TDF/stimulus pairs pass app-owned upload validation and runtime document loading with the intended rules. Schema generation succeeds with no substantive generated diff. Existing canonical AutoTutor replay tests pass; pre-canonical rejection passes.
5 Isolated app/provider, rule, history, authoring review, Meteor integration, and a provider-backed browser walkthrough completed. Full typecheck, lint, and Meteor integration pass. Browser acceptance is partial; see the dated browser record for observed failures and outstanding cases.

The new packages are AutoTutor Confidence Interval Student Selected and AutoTutor Confidence Interval Agent Selected. Each has its own TDF/page identity and preserves the reference content's expectation/KC identities. The application must support their policy IDs before the packages are uploaded.

Verification on October 9:

  • npm run typecheck: passed.
  • npm run lint: passed; existing vendored ostrio-files warnings remain. Server algorithm boundary, test-version-manifest guard, and the 310-surface security contract pass.
  • node scripts/sparcAutoTutorRules.test.cjs --include-client-contracts: 103 tests passed, including app commit and provider contracts, with synthetic provider/writer dependencies.
  • node scripts/analyticsMethods.test.cjs: 27 method contract tests passed. This simulates database uniqueness; it is not a live Mongo test.
  • npm run generate:schemas: succeeded; no substantive generated changes.
  • npm run check:sparc-rich-html: passed. The modified Svelte surface also compiles with zero compiler warnings.
  • Follow-up regression repair: node scripts/sparcAutoTutorRules.test.cjs --include-general-rules --include-client-contracts passes all 165 tests in 16 suites. The general-rules option now includes semantic/progressive-node coverage. All eight previously reported broader failures and the semantic-node failure are resolved.
  • Confirmed runtime repairs: duplicate rule/binding activations from OR branches are collapsed; fraction and dropdown controls are classified as inputs; malformed cluster attachments are rejected without numeric coercion; semantic regex answers no longer require exact placeholder text. Accepted-value lists now match alternatives, and default feedback excludes both regex and exact-value matches. New in, not-in, and not-regex tests are declared in the authoring catalog and evaluated by the shared production evaluator.
  • Five original assertions were stale: range-validation wording, two submitted-value history expectations, the hint-button derived-rule trace, and LCD model-practice history identity. Updated tests preserve submitted answers, trace records, and canonical response-outcome identity; no history behavior was removed to satisfy these assertions.
  • Follow-up full typecheck, lint, and diff checks pass. Lint retains 28 existing vendored warnings and no errors. Schema regeneration succeeds with no substantive generated schema changes. No content files or learner histories were migrated.
  • Subsequently authorized npm run test:ci on October 9: exit code 0; harness 16 passed; Meteor server 777 passed / 15 pending; Chromium client 1,095 passed / 7 pending; zero server or client failures. The run used the pinned Meteor 3.5 toolchain and an isolated MongoDB replica set with Change Streams. The runner removed test-driver resolutions; the test database/container was removed and test listeners were absent afterward. This is application integration evidence, not a provider-backed SPARC learner walkthrough or proof of the outstanding concurrent-selection acceptance case.
  • Immediately after the integration run, the hotfix server was restored: application health, HMR, client bundle, and Change Streams were ready. Only the signed-out public homepage had been observed at that point. The subsequent authenticated browser evidence is recorded below.

Subsequent authenticated browser walkthrough on October 9 exercised both versions with real provider responses. All five primitives rendered in both versions; student practice continued at 3/3 coverage, while the agent stopped naturally at 3/3. Pending menus, accepted questions, and the stopped agent state survived reload; student Save/Continue restored six turns and an active menu. One rich-content request failed validation and recovered on explicit same-choice retry. Response inputs lacked accessible names. The browser acceptance record records the exact sequences, failures, and remaining coverage gaps. The uploads and synthetic histories are confined to the local hotfix application.

Before calling step 5 complete, resolve the observed rich-output and labeling issues and cover the remaining image/figure, feedback-bearing continuation, live write/concurrency, accessibility, and original-reference regression cases listed in that record. Required verification failures continue to block staging/commit/push unless the user explicitly accepts them after reviewing their relevance and risk.

Competitive implementation verification, October 10, 2026

Working-tree implementation uses the existing production executor, primitives, and canonical history. The executor matches before instantiating the selected THEN; only the selected activation receives utility/probability bindings. The reference continues its existing order. No TDF package rewrite or new dependency is required.

Completed checks: full app TypeScript; lint (warnings, no errors); 173 isolated SPARC/general/client contract tests; 28 isolated analytics method tests; rich HTML contract check. Competitive cases include seed/gain orientation, negative changes, triggered misconceptions, all-target competition, equal ties, numerical stability, probability-scale OET updates, retry after provider failure, compatible attempt replay, account routing, and a 30-turn bounded-history regression.

Browser evidence: the local admin opened the existing Student Selected package under the competitive runtime, received a competitive pump, and displayed theta/assistance/OET/utility/temperature/probability diagnostics. The input is named Response. A development reload preserved the accepted decision. Browser work found an oversized cycle record caused by copied transient execution traces; cycle persistence now saves the existing event and durable writes without duplicating assessment/history assertions.

Meteor verification, October 10: the newly authorized invocation passed with exit code 0: harness 16 passed; server 779 passed, 15 pending, 0 failed; client 1,095 passed, 7 pending, 0 failed. The runner cleaned its test-driver resolutions from .meteor/versions. The completed-lesson launch message is not a test blocker: Practice menu → lesson Settings → Reset test progress is the existing supported route to clear practice and restart a standalone lesson. Reset clears the account’s lesson history and experiment state; the earlier browser pass used the incomplete reference package without clearing it. One uncertainty statement was classified by the existing AI question handler as out-of-scope. The scorer was unchanged during that verification; this observation is not proof of a new selector defect.

The subsequent scoring system prompt revision gives steps 1 and 2 a shared topic boundary: the original problem or the ongoing instructional dialogue, including ideas introduced by the tutor. Confusion and requests for clarification about that material are explicitly on-topic, and learner-question contentFocused uses the same definition. This changes the classification instructions; the routing productions and refusal-generation prompt remain unchanged. The earlier Meteor and browser results predate this prompt revision.

The subsequent package-routing revision enables the two Confidence Interval versions for admin testing: the Agent Selected stimulus page now selects oet-boltzmann-v1; the Student Selected page retains student-selected-v1. The app preserves the student policy during admin delivery and submission. Non-admin delivery remains deterministic, and both new policies require admin authority at history/provider boundaries. The duplicate course-path policy check was removed; the common history-write boundary owns that check for every write. Existing lesson/page identities and learner history are preserved. The student next-target option advances between expectations in the same case.

Verification for this package-routing revision: full app typecheck passed; lint passed with 0 errors and 28 existing warnings; isolated SPARC/client contracts passed 113 tests; isolated analytics methods passed 28 tests. App-level coverage includes menu delivery, next expectation before mastery, resume before selecting a composite, no second assessment on menu choice, and rejection after admin access is lost. Two dated ZIPs in the config repository each contain the source TDF and stimulus file, with archive contents compared to source. These revised ZIPs have not been uploaded. Live AI/browser acceptance and a fresh Meteor integration invocation have not been run for this revision; earlier results do not establish them.

After the persistence repair, the third-turn decision resumed successfully without a new assessment. Its diagnostic showed expectancy logit -0.20 and pre-selection OET logit -0.41 (probability 0.4), retaining the earlier production increment while the intervening scope-control response added none. The browser then reloaded the accepted output.

Post-integration recovery verified: the isolated test MongoDB container was removed; test ports 3010/3011/27018 have no remaining listeners; .meteor/versions has no diff. The canonical hotfix watcher is restored at localhost:3200 with app health, browser client bundle, Rspack HMR, supervisor, and five active MongoDB Change Streams verified. No learner practice reset was needed for the isolated integration run.

Four-move revision verification

Full app typecheck passed; lint passed with 0 errors and 28 existing warnings; 176 isolated SPARC/general/client tests passed. Coverage confirms all four student buttons select exactly the requested native move, including after coverage is complete; obsolete menu options are rejected; the competitive activation set contains only those four moves; prior v1 histories are excluded from v2 attempts; KC switching and retry/resume tests remain passing. The user-authorized upload of both AutoTutorMoves-v2 archives completed in the local hotfix application on October 10. Each updated the existing lesson identity; the refreshed Content page lists both lessons and their stimulus files. No practice reset was performed. This verifies upload, not a new live AI/browser acceptance walkthrough or Meteor integration run.

October 11 compact-figure refinement: Seedream's OpenRouter endpoint advertises automatic aspect ratio. The image request now uses auto at the existing 1K resolution. The figure-planning and image-generation calls share one compact-composition instruction: group related elements closely, place labels near their elements, keep modest outer margins, and avoid excessive gaps unless the spacing itself has instructional meaning. No extra schema field or crop step is introduced. The supported Prompt generation policy is version v2; its output schema remains v1. Admin selection notes reuse the labels encoded in the production menu, displaying Prompt (unsupported) and Prompt (supported) while preserving the internal move and production identities.

Information-based figure display sizing: the supported Prompt planner returns a required integer displayWidth from 240 to 640 CSS pixels, estimating the smallest comfortable space from the required visual elements, label lengths, and relationships. It estimates space, not detailed positions, and requests readable labels at that width. The image model still composes a compact figure at 1K with automatic aspect ratio. The estimate is saved with the private asset and dialogue reference; retries and resume retain the original pairing and size. The conversation clamps the estimated width to its available space while retaining the image aspect ratio. Existing canonical figures without a width keep their previous 640-pixel maximum; no records are rewritten or regenerated. Supported Prompt policy is v3 and generated brief schema is v2. No formula, TDF field, package change, or new dependency is introduced.

Live display-size verification, October 11, 2026: in the agent-selected Compound Interest lesson, a partially correct synthetic answer produced a supported Prompt with a 360-pixel width estimate. The browser rendered the two-panel figure at exactly 360 pixels, preserving its aspect ratio. Reload restored the same tutor text, byte-identical image source, and 360-pixel width. The earlier widthless canonical figure retained its previous maximum-width behavior. The new figure was compact and readable at the tested desktop viewport; some smaller labels were below the requested 14-pixel aim, so the prompt instruction does not guarantee a minimum raster font size. This verifies generation, rendering, and reload for this case, not all subjects or screen sizes.

Shared Sunburst teaching-figure library — October 12, 2026

The user selected GPT Image 2.5 Sunburst. The initial default is Medium quality, one image, automatic aspect ratio, pinned OpenAI routing with provider fallback disabled. High, Xhigh, Max, Low and Auto are available provider quality settings; they are not a separate reasoning-effort control. Sunburst requests use quality and do not send Seedream's resolution parameter. Dialogue-model settings remain account-controlled.

For complete teaching figures, the first sufficiently novel instructional situation generates an image for the current learner and immediately adds it to the shared library. Subsequent situations reuse the nearest figure whose cosine similarity reaches the cutoff. There is no per-retrieval AI critic, suitability-reranking call, or advance human-approval gate. Human review is subsequent library maintenance. Incomplete supported-Prompt figures remain private and outside this teaching-figure index.

The situation embedding includes the selected target type and authored target texts, current target value when available, move assistance, and the planned illustration brief. The shared representation excludes account/session IDs, raw responses, and dialogue history. The existing primary embedding model, google/gemini-embedding-001, is used without switching to another model on failure. An embedding failure fails the selected move clearly.

The initial minimum cosine similarity is 0.90, an experimental default rather than a calibrated correctness probability. A deployment can override it with the numeric Meteor setting sparcFigures.minimumSimilarity, between 0 and 1. The common settings and representation version are in mofacts/common/lib/sparcFigureLibrary.ts. Match scores and source (generated versus semantic reuse) are retained in the private decision ledger. Reuse incurs an embedding request, but no image-generation request; resuming the same decision incurs neither.

The server-only sparc_figure_library collection stores originating situation embeddings and stable image IDs. sparc_figure_requests stores each account/TDF/session/production-event decision and temporary generation leases. DynamicAssets owns canonical image bytes and descriptions. No new TDF fields, learner controls, package changes, dependencies, or historical migration are required. Current SPARC admin-only access remains in force; generic asset routes still deny these images. Existing private assets retain their ownership and original pairing.

Nearest-neighbor search is exact cosine comparison across matching representation/image-model/embedding-model/dimension records, paged internally in batches of 100 with an index and bounded memory. Only candidate vector fields are read during search; the full library is never published to the client. Lookup cost grows with library size; this is not an approximate vector index or a capacity certification. Warm retrievals run concurrently. On a miss, a Mongo lease serializes discovery plus first generation across replicas and repeats the search before generating, so simultaneous close encounters can reuse the newly populated entry. Lease wait is bounded at 180 seconds; the lease expires after 15 minutes to recover from a stopped process and is released only by its owner.

A durable pending entry preserves the original brief and embedding across provider/storage failures. Once the canonical asset is ready, the transient generation payload is removed and the per-learner decision points to that asset. Restart/retry reuses the saved decision even if the originating library entry is later excluded from new reuse. Setting its reusable flag to false removes an entry from future search while retaining its asset and prior learner histories.

Administrators can open Content → Inspect image library to inspect the entire shared teaching-figure repository at /sparcImageLibrary. The link is at the top of Content, rather than in a stimulus editor, because suitable figures can be reused across TDFs. Groups opens a compact grid with one example thumbnail, broad generated label and image count per semantic group. Click the example thumbnail or its label to open that group. Select a group to open a compact thumbnail grid ordered from closest to the center outward. Clicking a thumbnail displays that image and its description, deprecation and replacement controls above the grid; the selected thumbnail is highlighted. The initial group page shows the grid without selecting an image. Show more images appends another bounded page of thumbnails and retains the current selection. Choose All images for the complete collection using the same thumbnail grid and selected-image panel above it. Both views start without a selected image, retain the current selection when more thumbnails are loaded, and place deprecation, replacement and old-version controls on the selected full image card. The gallery includes all completed library entries across systems, image models and representation versions, including figures excluded from future reuse. Each image card shows its saved description, creation date, image model and reuse status; select the image to open it at full size. Incomplete generations and private supported-Prompt images are outside this shared repository.

The gallery uses the active Theme tool's existing typography, density and semantic surface settings. Its main heading uses the same 1.5 * app_font_size_base sizing as the shared app header, with app_heading_font_family and app_page_header_text_color; smaller headings and captions also scale from the base font size. Thumbnail heights and grid widths scale with app_density_scale. Image cards use the configured card/stimulus surfaces, large corner radius, text and border colors; the upload form uses the existing themed form-control styles and small corner radius. Buttons and focus styles continue through the shared theme rules. No new theme properties or server theme changes are required. The scoped gallery heading avoids inheriting the viewport-sized global hero heading rule.

Header comparison covered Content, Courses, Assignments, Data, Admin Control Panel, Backups, Security Audits and Theme templates. These use the shared app header and compact h5/h6 section headings; Theme's h3 is part of the intentional landing-page preview. No common management-header correction was warranted by this review.

listSparcLibraryImages requires the admin role and uses indexed cursors to return up to 24 entries per page. Cluster pages use batched field-limited membership, library metadata and canonical-asset reads; the All images view uses a batched canonical-asset lookup. The browser fetches image pixels as cards enter view, through the existing admin-only getSparcPromptImage reader. Embeddings, learner identifiers, session records and credentials are not returned. Show more images loads the next page. Missing canonical assets cause an explicit error rather than disappearing from the list. Inspection does not generate images. No new TDF/stimulus fields or provenance migration are needed.

Automatic grouping uses deterministic spherical k-means on a sample of at most 128 originating situation embeddings per compatible representation-version/embedding-model/dimension space. A second streaming pass assigns every completed figure, including deprecated figures, to its nearest center. Candidate counts range from 2 through the lesser of 12 and one third of the sample size. Each candidate uses two deterministic initializations and at most 16 iterations; solutions with fewer than two sample members in any cluster are rejected. The smallest candidate within 0.02 of the best cosine silhouette score is selected, provided that best score reaches 0.20. Otherwise the collection stays together as one group. These are initial browsing heuristics, not a claim that a uniquely correct number of pedagogical topics has been discovered. Cluster count has no author or administrator control. Silhouette-based cluster selection reference.

The grouping owner reads vectors internally in pages of 100, retains only the bounded samples and centers, yields between analysis steps and records stage/count progress. It stores derived snapshots and indexed membership documents in the server-only sparc_figure_browse collection. Completed-figure additions and explicit asset deletion invalidate the browsing revision; changing reusable does not change the semantic organization. A separate browsing lease serializes rebuilds without holding the image-generation lease. Publication checks the source revision so incomplete or obsolete builds are not accepted. Current snapshots remain cached, superseded snapshots expire after 30 minutes, and abandoned staging members expire after 24 hours. A stale group page asks the administrator to reopen Groups.

Broad English labels come from the three nearest representative figures' saved descriptions and authored target texts, in batches of at most four groups. Label generation uses the configured administrator OpenRouter key, model and reasoning level, with strict validated JSON and provider fallback disabled. No vectors, accounts, sessions, answers or learning histories are included in the label request. Cached group browsing and image inspection make no provider calls; a rebuild labels the new groups. Missing model/key configuration and provider or label-validation errors fail clearly rather than supplying invented replacement labels. Grouping changes neither instructional similarity retrieval nor saved figure decisions.

Semantic-browsing verification, October 13, 2026: all 237 isolated SPARC contracts passed, along with full-app typecheck and lint (28 existing vendor warnings, no errors). Fixtures covered automatic separation, small/identical collections, bounded sampling, full membership across multiple source pages, compatible-space isolation, cached labels, concurrent builds, invalid labels, revision races, authorization and paged member ordering. A synthetic 128-vector, 3,072-dimension fit selected four separated groups in 296 ms; this is not a production capacity benchmark. Chrome at localhost displayed the generated Confidence Interval Coverage group with two images, opened its center-ordered members and verified deprecation across the group and All images views. The tested flag was restored. Mongo snapshot/index regressions were added but the full Meteor integration suite was not rerun. These are local checks, not deployment or publication.

At the top of each card, Deprecated controls the existing reusable boolean: checked sets it to false, unchecked sets it to true. The admin-only setSparcLibraryImageReusable method requires a completed canonical library figure and a literal boolean, then atomically updates only that field. The control disables while saving, confirms a successful change inline and restores the previous checkbox state on failure. Deprecation removes the figure from subsequent candidate searches across all systems; it remains visible in the gallery and readable by saved lesson decisions. No image, embedding, learner history or saved decision is deleted. A decision already accepted before deprecation retains its original figure.

Human replacement and version history. Each current card offers Replace image. An administrator uploads a PNG, JPEG or WebP image (up to 8 MB), previews it and supplies the replacement's plain-text description before saving. The replacement must serve the same teaching situation; it does not create a new semantic entry or embedding. Old versions (N) expands a paged, newest-first list of earlier images, including the original, with their original descriptions and dates. Old versions stay hidden until opened and do not become separate gallery entries or search candidates. There is no instructional AI replacement action and no image-provider call during a human upload.

The library entry's _id remains its original asset ID and stable semantic identity. The optional currentAssetId and revision point to the active immutable version; before any replacement, the original ID is current and revision is zero. Gallery descriptors explicitly distinguish libraryId from the rendered assetId. Each accepted replacement receives a new asset ID; the server-only sparc_figure_versions collection retains its parent entry, revision, predecessor and private administrator provenance. Original revision zero is admitted into the version history during the first replacement. Old entries require no destructive migration. New semantic selections save the current asset ID, while existing per-learner decisions, lesson figure references, captions and pixels retain the exact version originally selected. Deprecation applies to the semantic entry and is preserved when replacing it.

The existing generation lease serializes upload retries across replicas. Content and the expected-current ID determine an idempotent upload identity; stale edits reject with an instruction to reload. Local/S3 storage must complete before a snapshot/majority Mongo transaction admits the history records and advances the current pointer together. An interrupted upload remains private and unindexed, with a named retry path that completes the same saved asset; it never overwrites an admitted version. Retrying a previously completed upload after a later replacement returns the current image and does not rewind the entry. This uses the existing required Mongo replica-set runtime. The administrative all-content purge remains a separate explicitly destructive operation and cleans version metadata.

Semantic membership continues to use the stable original entry ID, so replacement does not change cluster membership or duplicate a figure. Listings, label-source descriptions and representative thumbnails resolve to the current asset. Cached broad cluster labels remain associated with the unchanged teaching situation. Replacement records are not published, and the history method returns at most 24 safe descriptors per page, without learner identifiers, administrator identifiers, embeddings or raw situations. Generic file downloads retain the existing private-image restrictions.

Replacement verification (October 13): 240 isolated SPARC contracts passed, including current-version semantic selection, original decision/byte/caption preservation, multi-version paging, cached-cluster hydration, concurrent stale editor rejection and interrupted S3-storage retries. Full-app typecheck passed; lint and security-surface checks passed with 28 existing vendor warnings and no errors. Signed-in Chrome exercised the actual administrator file upload, durable save and Mongo transaction, and rendered the preserved original beneath the current replacement through Old versions. The temporary deprecated QA entry, both version records and both raster files were removed afterward; the two pre-existing teaching entries were retained. A Mongo concurrency/transaction regression was added for the supported isolated Meteor suite; that full suite was not run. These are local checks, not production deployment.

Deprecation-control verification, October 13, 2026: all 231 isolated SPARC contracts, full-app typecheck and lint passed. The localhost Chrome test checked the first figure's Deprecated box, reloaded and confirmed its saved checked state, then unchecked it and reloaded to confirm restoration. The test left both existing figures eligible for reuse. Injected method contracts also verified rejection of unauthorized users and invalid inputs, new-generation behavior after exclusion, and unchanged saved decisions and image access. The Mongo regression covers field-only updates and rejection of pending records but was not run in the full Meteor suite.

Repository-inspection verification, October 13, 2026: 229 isolated SPARC contracts and three route-policy checks passed, along with full-app typecheck and lint (28 existing vendor warnings, no errors). In signed-in Chrome at localhost, the Content link opened the gallery and both existing canonical figures rendered with descriptions and reuse status. The full-size link opened an image tab whose title reported the saved raster dimensions. Paging across 25 figures, inclusion of excluded/older-version figures, omission of private state and authorization failures were checked with injected fixtures. The Mongo-specific inspection regression was added but not run in the full Meteor integration suite. This records local verification, not production deployment.

The rich primitive selects or generates its actual support first. Both explanation and isomorphic-question generation then receive the selected figure's pixels and saved description, so they can use its actual case and values. The displayed composite remains one box in explanation/support/question order. The existing worked-example and no-rich paths retain their requested compositions.

Provider comparison: one 16:9 confidence-interval figure per quality level, with the same prompt and streaming off, produced Low $0.00517 / 10.7 seconds; Medium $0.00997 / 13.2 seconds; High $0.03391 / 23.4 seconds; Xhigh $0.05908 / 30.8 seconds; Max $0.13090 / 54.8 seconds; Auto $0.03391 / 24.1 seconds. All six preserved the central long-run-coverage concept. Numeric placement was approximate; no general reliability rate is established by this one case. Recraft V4.1 Pro cost $0.21 / 9.6 seconds and produced substantial counting, geometry, dot-placement, and text errors. Local comparison images, screenshots, prompt, and the HTML gallery are saved under the SPARC working browser-acceptance folder.

Verification, October 12, 2026: all 227 isolated SPARC/rule/client/library contracts passed. Full-app typecheck passed. Lint passed with 28 existing ostrio-files warnings and no errors; the server dependency boundary, Meteor dependency manifest, and 312-surface security contract checks passed. The localhost admin student-selected lesson generated a new Medium Sunburst teaching figure, then reused its byte-identical image for a distinct E2 move after an intervening E3 move. The reused move generated a fresh explanation and isomorphic question from the saved figure. The new E3 question correctly tested definite containment of a fixed mean after an observed E2-target drift was repaired in the question prompt. Previous selected-choice markers remained visible. Cross-account authorization and reuse were verified by injected contracts, not a two-account browser walkthrough. Mongo-specific integration tests have been added but were not run; each full Meteor CI invocation requires fresh explicit authorization under AGENTS.md. No release, commit, or push is claimed.

Asset lifecycle: the existing explicit admin asset-deletion path removes the matching library entry and per-learner decision metadata. Account deletion removes only that account's private figure decisions and preserves shared assets. These teardown callbacks are wired into the existing admin methods; no deletion was performed during this verification.

Authorized Meteor integration verification — October 12, 2026

The user authorized the full Meteor suite and up to three further runs after failures. The first invocation passed 16 harness checks and 795 server tests (15 pending), then exited with Windows process status 0xC0000409 as Chromium client testing started. It reported no failing assertion or completed client result; no source defect was identified from that exit. The second invocation, using the same pinned runner and settings with a fresh disposable CI Mongo replica set, completed successfully: 16 harness checks, 795 server tests (15 pending), and 1,104 client tests (7 pending), with SERVER FAILURES: 0 and CLIENT FAILURES: 0. This includes the new real-Mongo figure-library lease and decision contracts. No further integration retries were used. Test-driver resolutions were cleaned by the supported runner; the disposable test database was removed and the existing localhost watcher was restored. This establishes integration coverage, not deployment or release-image qualification.