jtdearmon commited on
Commit
13f1506
·
verified ·
1 Parent(s): f43be2d

Deploy SAT & ACT Learning Lab 1.2.2

Browse files
Files changed (7) hide show
  1. .gitignore +7 -0
  2. DEPLOYMENT_NOTES.md +102 -0
  3. README.md +92 -7
  4. app.py +0 -0
  5. release_manifest.json +97 -0
  6. requirements.txt +18 -0
  7. runtime.txt +2 -0
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.db
4
+ *.db-wal
5
+ *.db-shm
6
+ .gradio/
7
+
DEPLOYMENT_NOTES.md ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment notes — SAT & ACT Learning Lab 1.2.2
2
+
3
+ Target private Space: `DearmonAnalytics/SAT_ACT_Learning_Lab`
4
+
5
+ Turso database: `dearmon-sat-act-learning-lab`
6
+
7
+ Schema namespace: `sat_act_learning_lab_v1`
8
+
9
+ Encrypted-source secret: `SAT_ACT_APP_FERNET_V1_2_2_F48B2CACB56D_C9A0A3E35DD0`
10
+
11
+ ## Runtime contract
12
+
13
+ - Python 3.12 and Gradio 6.24.0 are pinned.
14
+ - The encrypted package is authenticated with Fernet and verified against both
15
+ ciphertext and decrypted-archive SHA-256 hashes.
16
+ - Python source modules load from memory; plaintext source is not extracted to
17
+ the Space filesystem.
18
+ - Turso is required in production. Each process may use its own embedded
19
+ replica at `/tmp/dearmon-sat-act-learning-lab-{pid}.db`.
20
+ - Authentication-sensitive account reads refresh that replica on a bounded
21
+ process-local interval and fail closed if a required refresh cannot complete.
22
+ Live timed-exam state and mutation locks are process-local, so this release
23
+ must run one application process for authoritative simulation/resume. A
24
+ multi-process topology requires a distributed exam lease/generation protocol;
25
+ sticky routing alone does not provide that guarantee.
26
+ - Username accounts map to stable opaque learner IDs and store only salted
27
+ scrypt password records. Five failed sign-ins within 15 minutes lock the
28
+ account for 15 minutes, and authentication-version checks revoke old sessions
29
+ after a password change or recovery.
30
+ - Legacy learner IDs use the same stable server-side HMAC secret; learner PINs
31
+ must not be stored or logged. Conversion requires verified name/class/PIN
32
+ credentials and retains the existing learner ID and mastery history.
33
+ - Email password recovery is optional and uses an eight-digit, 15-minute,
34
+ single-use code with five attempts. Every account also receives a
35
+ one-time-display offline recovery key that is stored only as a keyed digest
36
+ and rotates after use or password change.
37
+ - One-click demos have a 45-minute ordinary-use window and route all seeded/new
38
+ progress and simulation state to bounded process memory—not Turso,
39
+ instructor analytics, exports, deletion, or recovery. A started full
40
+ simulation may reserve blueprint duration plus a 45-minute grace period,
41
+ capped at four hours; sign-out or restart still erases it immediately.
42
+ - Instructor-wide access requires a strong secret with no fallback.
43
+ - Scored questions and answer keys are deterministic and model-independent.
44
+ - Break It Apart is a deterministic, provider-independent, post-miss reasoning
45
+ DAG. It is available after every incorrect practice grade and for every
46
+ missed objective item reviewed after a completed simulation—never before
47
+ grading or during an active form. The topic is the top node; sentence,
48
+ quantity/unit/operation, claim/evidence, or data/variable attributes feed up
49
+ through the answer dependency path. These attributes are explanatory only
50
+ and do not create separate mastery or retention records.
51
+ - The embedded Business Calculus avatar defaults to the male professor and
52
+ offers Oliver (`cedar`, speed `1.02`). Speech and live Simli video are opt-in;
53
+ audio retention is disabled by default. Oliver is presented as an AI teaching
54
+ persona, not as the real person or a source of real-world claims.
55
+ - `SIMLI_API_KEY` and SMTP passwords stay server-side and never enter HTML,
56
+ browser state, public variables, logs, receipts, or health output.
57
+ - `/healthz` reports the release/source digest and boolean configuration status
58
+ without returning credentials, learner identifiers, or answers.
59
+
60
+ ## Configuration
61
+
62
+ Core secrets are `OPENAI_API_KEY`, `TURSO_DATABASE_URL`, `TURSO_AUTH_TOKEN`,
63
+ `LEARNER_ID_HMAC_SECRET`, `INSTRUCTOR_EXPORT_SECRET`, and
64
+ `SAT_ACT_APP_FERNET_V1_2_2_F48B2CACB56D_C9A0A3E35DD0`. Live avatar video additionally uses optional
65
+ `SIMLI_API_KEY`.
66
+
67
+ Email recovery uses `AUTH_RECOVERY_EMAIL_ENABLED`, `AUTH_SMTP_HOST`,
68
+ `AUTH_SMTP_PORT`, `AUTH_SMTP_USERNAME`, `AUTH_SMTP_PASSWORD`,
69
+ `AUTH_SMTP_FROM_EMAIL`, `AUTH_SMTP_STARTTLS`, `AUTH_SMTP_SSL`, and optional
70
+ `AUTH_SMTP_TIMEOUT_SECONDS`. Leave email recovery disabled unless the
71
+ configuration is complete; offline recovery still works.
72
+
73
+ Release runtime defaults include `ACCOUNT_AUTH_ENABLED=1`,
74
+ `AUTH_SESSION_RECHECK_SECONDS=30`, `AUTH_REPLICA_SYNC_SECONDS=5`,
75
+ `SAT_ACT_DEMO_MODE_ENABLED=1`,
76
+ `SAT_ACT_DEMO_SESSION_TTL_SECONDS=2700`,
77
+ `ASK_PROFESSOR_COMPONENT_DEFAULT=1`, `ASK_PROFESSOR_TTS_DEFAULT=0`, and
78
+ `ASK_PROFESSOR_SIMLI_DEFAULT=0`. Face IDs and the pinned Simli client module are
79
+ listed in `environment.example` used to prepare this deployment.
80
+
81
+ ## v1.2.2 upgrade gate
82
+
83
+ Finish or explicitly abandon every active timed simulation from an earlier
84
+ release before installing v1.2.2. Checkpoints are intentionally bound to
85
+ app/source/form versions and cannot be resumed across this release. Back up
86
+ Turso, preserve `LEARNER_ID_HMAC_SECRET`, and retain prior Fernet secrets and
87
+ rollback commits needed through acceptance testing.
88
+
89
+ ## Key lifecycle and rollback
90
+
91
+ The current loader reads only `SAT_ACT_APP_FERNET_V1_2_2_F48B2CACB56D_C9A0A3E35DD0`. A later release must generate a
92
+ new versioned, fingerprinted secret name. The deployer adds that secret before
93
+ the repository commit and retains earlier keys. Roll back by reverting the
94
+ Space repository to the prior commit recorded in `deployment_receipt.json`.
95
+ Do not delete an earlier Fernet key until its rollback revision is retired.
96
+
97
+ ## Legal notice
98
+
99
+ This independent practice lab is not affiliated with or endorsed by College
100
+ Board or ACT, Inc. SAT and ACT are their respective owners' trademarks. The
101
+ lab contains original practice material only; diagnostic results are not
102
+ official scores.
README.md CHANGED
@@ -1,13 +1,98 @@
1
  ---
2
- title: SAT ACT Learning Lab
3
- emoji: 🔥
4
- colorFrom: gray
5
- colorTo: gray
6
  sdk: gradio
7
- sdk_version: 6.26.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: SAT & ACT Learning Lab
3
+ emoji: 🧭
4
+ colorFrom: indigo
5
+ colorTo: yellow
6
  sdk: gradio
7
+ sdk_version: 6.24.0
8
+ python_version: "3.12"
9
  app_file: app.py
10
  pinned: false
11
+ license: other
12
+ short_description: Dynamic SAT/ACT practice, mastery, and reasoning graphs
13
  ---
14
 
15
+ # Dearmon Analytics SAT & ACT Learning Lab
16
+
17
+ Release `1.2.2` provides original dynamic practice for current SAT and
18
+ ACT skill blueprints, a four-level topic graph, individual mastery tracking,
19
+ targeted practice, and test-like diagnostic sessions. It adds username/password
20
+ accounts, secure recovery, an isolated one-click demo, and the embedded teaching
21
+ avatar layer used by the Dearmon Analytics Business Calculus platform. Release
22
+ 1.2.0 introduced deterministic post-miss **Break It Apart** attribute graphs.
23
+
24
+ The question engine and answer keys are deterministic. The optional AI teaching
25
+ assistant can explain concepts and student work but does not create scored
26
+ questions, decide correctness, or alter answer keys.
27
+
28
+ After every incorrectly graded practice question, and for every missed
29
+ objective item reviewed after a completed simulation, Break It Apart constructs
30
+ a directed acyclic reasoning graph with the tested topic at the top. Sentence
31
+ items diagram subjects, verbs, direct objects, complements, modifiers, and
32
+ dependent clauses. Math items build from quantities and units through order of
33
+ operations and intermediate dependencies. Reading and science items connect
34
+ claims, evidence, data, variables, and conclusions. The graph is deterministic,
35
+ makes no model or provider call, and is unavailable before an incorrect grade
36
+ or completed simulation. Its attributes are explanatory scaffolds, not separate
37
+ attribute-level mastery or retention records.
38
+
39
+ ## Service configuration
40
+
41
+ This private Space uses the separate Turso database
42
+ `dearmon-sat-act-learning-lab` and schema namespace
43
+ `sat_act_learning_lab_v1`. Its encrypted application uses the versioned Space
44
+ secret `SAT_ACT_APP_FERNET_V1_2_2_F48B2CACB56D_C9A0A3E35DD0`.
45
+
46
+ Required Space secrets are `OPENAI_API_KEY`, `TURSO_DATABASE_URL`,
47
+ `TURSO_AUTH_TOKEN`, `LEARNER_ID_HMAC_SECRET`, `INSTRUCTOR_EXPORT_SECRET`, and
48
+ the versioned Fernet secret named above. There is no default instructor
49
+ password.
50
+
51
+ `SIMLI_API_KEY` is optional and enables learner-initiated live avatar video.
52
+ The avatar defaults to the male-professor style, Oliver is selectable, and
53
+ Oliver's speech profile uses the `cedar` voice at speed `1.02`. The component is
54
+ shown by default, but speech and live video both default off until the learner
55
+ opts in. Oliver is an AI-generated teaching persona, not the real person or a
56
+ source of real-world claims. The Simli key remains server-side and must never
57
+ appear in HTML, browser state, logs, public variables, or `/healthz`. Text
58
+ tutoring remains available when Simli is absent or unavailable.
59
+
60
+ Username passwords are stored as independently salted scrypt records. Account
61
+ lockouts persist in the database, password changes revoke earlier sessions,
62
+ and verified legacy name/class/PIN profiles can be converted without moving
63
+ their mastery history. Each account receives a one-time-display offline
64
+ recovery key that rotates after use. Email one-time-code recovery is optional;
65
+ configure `AUTH_RECOVERY_EMAIL_ENABLED`, `AUTH_SMTP_HOST`, `AUTH_SMTP_PORT`,
66
+ `AUTH_SMTP_USERNAME`, `AUTH_SMTP_PASSWORD`, `AUTH_SMTP_FROM_EMAIL`,
67
+ `AUTH_SMTP_STARTTLS`, `AUTH_SMTP_SSL`, and optional
68
+ `AUTH_SMTP_TIMEOUT_SECONDS`; keep provider credentials as Space secrets. Email
69
+ codes expire after 15 minutes and are single-use. Without SMTP, offline
70
+ recovery remains available.
71
+
72
+ The one-click demo has a 45-minute ordinary-use window and starts with clearly
73
+ labeled sample progress. Starting a full simulation reserves its blueprint
74
+ duration plus a 45-minute completion grace period, capped at four hours. Demo
75
+ practice and simulation state remain in bounded server memory only: they are
76
+ not written to Turso, included in instructor analytics or exports, or eligible
77
+ for account recovery. Sign-out/reset or process restart removes the session
78
+ immediately; otherwise it disappears at the applicable expiry.
79
+
80
+ Audio/video are opt-in and audio retention is disabled by default. Deployments
81
+ serving minors need appropriate notice, consent, provider review, access
82
+ controls, and retention policies.
83
+
84
+ ## Upgrade note
85
+
86
+ Before replacing any earlier release with v1.2.2, every active timed simulation
87
+ must be finished or explicitly abandoned. Saved forms are bound to the app
88
+ version and encrypted-source fingerprint, so v1.2.2 intentionally rejects older
89
+ checkpoints. Preserve `LEARNER_ID_HMAC_SECRET` and retain every prior versioned
90
+ Fernet secret and rollback commit needed through acceptance testing.
91
+
92
+ ## Independent practice-content notice
93
+
94
+ This is an independent educational practice product. It is not affiliated
95
+ with, endorsed by, or sponsored by College Board or ACT, Inc. SAT is a
96
+ trademark of College Board; ACT is a trademark of ACT, Inc. All practice
97
+ questions, passages, data, explanations, and figures in this lab are original
98
+ content. Practice results are diagnostic and are not official scores.
app.py ADDED
The diff for this file is too large to render. See raw diff
 
release_manifest.json ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "built_utc": "2026-08-29T21:32:04+00:00",
3
+ "database_name": "dearmon-sat-act-learning-lab",
4
+ "encrypted_payload_sha256": "624ee6c73861cb1664781dea08df4acf727f0d93e4e04186947f777520d5fab1",
5
+ "entry_module": "sat_act_lab.app_main",
6
+ "fernet_secret_name": "SAT_ACT_APP_FERNET_V1_2_2_F48B2CACB56D_C9A0A3E35DD0",
7
+ "key_fingerprint_sha256_prefix": "C9A0A3E35DD0",
8
+ "plaintext_archive_sha256": "f48b2cacb56d10f6d361cfdf5e01a4a4c4637f1b6b1ec01aab32bdbede584904",
9
+ "release_version": "1.2.2",
10
+ "schema_namespace": "sat_act_learning_lab_v1",
11
+ "schema_version": "dearmon-sat-act-release-v1",
12
+ "source_members": {
13
+ "sat_act_lab/__init__.py": {
14
+ "bytes": 71,
15
+ "sha256": "31ffa487949f215cc8112867e1a4e0d3f371a63865950dd364a6b5f0fa999877"
16
+ },
17
+ "sat_act_lab/act_english_bank.py": {
18
+ "bytes": 79622,
19
+ "sha256": "f27b4dbc7380b15856a09156e10193e01e9ee986afa307f81e85f8255a4bc42a"
20
+ },
21
+ "sat_act_lab/act_reading_bank.py": {
22
+ "bytes": 62923,
23
+ "sha256": "ab2b3374bd4cf52c85c700f487979a5968a4baa701fda260bc826ace98e18db8"
24
+ },
25
+ "sat_act_lab/act_science_bank.py": {
26
+ "bytes": 43952,
27
+ "sha256": "5959db1e6a007f9384978c2a65af82e9bfd81216db939a1d852a91852badef8e"
28
+ },
29
+ "sat_act_lab/app_main.py": {
30
+ "bytes": 240007,
31
+ "sha256": "ae4c6090cfded3affe6830fe04869d6a85868eaa6f8e54f763aa737134ad8929"
32
+ },
33
+ "sat_act_lab/attribute_graph.py": {
34
+ "bytes": 119752,
35
+ "sha256": "be633962117561ae8ee2f02cf43c1b1612d7faf79916d2af52c5596db1ec8b0a"
36
+ },
37
+ "sat_act_lab/auth.py": {
38
+ "bytes": 52719,
39
+ "sha256": "ca3a1ed2540a3c7a617286e26dedd0901caef39126684b0e3a62f0fa13fe4c67"
40
+ },
41
+ "sat_act_lab/avatar.py": {
42
+ "bytes": 73246,
43
+ "sha256": "1456fe4834dec9636845ee0dd4794c4750abda703a5278079ce41b09d0fbbbff"
44
+ },
45
+ "sat_act_lab/blueprints.py": {
46
+ "bytes": 49657,
47
+ "sha256": "7c9cf2c1532818203b7a52de24d61031aeb65d31ccd7f6be627c0bb2c99ecf93"
48
+ },
49
+ "sat_act_lab/curriculum.py": {
50
+ "bytes": 34704,
51
+ "sha256": "0ace42ff71e3eee09b7b0828807cda7ecad2ea86caeda9cb67c0b941ab70c960"
52
+ },
53
+ "sat_act_lab/demo_sessions.py": {
54
+ "bytes": 37662,
55
+ "sha256": "544b2163c3d39259108847468d8f9bb027ae65d3b13ee934a8f6d9a43d167943"
56
+ },
57
+ "sat_act_lab/exam_engine.py": {
58
+ "bytes": 100384,
59
+ "sha256": "2abb720cd5a0a5a459cbcdc7ec1a8919ea50d7203cc809adccdefed4317e3a7f"
60
+ },
61
+ "sat_act_lab/question_engine.py": {
62
+ "bytes": 221287,
63
+ "sha256": "929d8e424bbb845e69cab76f6e591f9bfb1f825c00733cd90efce089ea1a89a2"
64
+ },
65
+ "sat_act_lab/tracking.py": {
66
+ "bytes": 139074,
67
+ "sha256": "c814032247eac63b59d7c619aa172af6340840bc2d1cd5e2b9e5294862231d82"
68
+ }
69
+ },
70
+ "space_file_hashes": {
71
+ ".gitignore": {
72
+ "bytes": 56,
73
+ "sha256": "3b1fdd8eb2e17dc4edae8387f1bc9a18a8072a8d6fae3a71041f00f0b9b04103"
74
+ },
75
+ "DEPLOYMENT_NOTES.md": {
76
+ "bytes": 5663,
77
+ "sha256": "75c5b9f2879c7d8c3edf341a9193651d35fc803480cb03082ab94e09bd495057"
78
+ },
79
+ "README.md": {
80
+ "bytes": 5113,
81
+ "sha256": "834bcec62692addb45ba46e4936455adf94b202cc5ff9fce0c046b5474684e4e"
82
+ },
83
+ "app.py": {
84
+ "bytes": 556664,
85
+ "sha256": "22acd56b8e17e47ab11c2eeea2ba2fc5f20e6a24db71f1d069f7fdc54f23e8f8"
86
+ },
87
+ "requirements.txt": {
88
+ "bytes": 287,
89
+ "sha256": "1cfe1a2b7efb8ba2372a283d5897316f691a693b23b53e0169888569060d1776"
90
+ },
91
+ "runtime.txt": {
92
+ "bytes": 13,
93
+ "sha256": "3c06f1fa700cc89985a58f039c6e5b4a973fc52e2c50b4fb092c0f89eb532f3a"
94
+ }
95
+ },
96
+ "target_space": "DearmonAnalytics/SAT_ACT_Learning_Lab"
97
+ }
requirements.txt ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio==6.24.0
2
+ gradio-client==2.6.0
3
+ huggingface-hub==1.27.0
4
+ fastapi==0.141.1
5
+ starlette==1.6.0
6
+ jinja2==3.1.6
7
+ uvicorn==0.41.0
8
+ numpy==2.5.2
9
+ pandas==3.0.5
10
+ matplotlib==3.10.8
11
+ sympy==1.14.0
12
+ requests==2.34.2
13
+ pillow==12.1.1
14
+ python-docx==1.2.0
15
+ libsql==0.1.11
16
+ openai==2.54.0
17
+ cryptography==46.0.7
18
+
runtime.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ python-3.12
2
+