The artifact was reworked after real incidents: a week of lost data, a
student taught out of order, and spelling diagnoses the model invented.
This takes the new export in verbatim; the port catches up in the
commits that follow.
Copied byte-identical from the bundle:
lib/ lexicon.js and sync.js are new; gate.js gains enforcement,
hangul.js letter-level marking, srs.js recall evidence,
conjugation.js deconjugate(); blocks.js now takes the last
block, closes gloss at "=", and parses recall, ::result and
::confirmed
data/ curriculum.json v5 — six 다지기 phase reviews; the 371
roadmap words are unchanged and no band moves
prompt/ English-only rule, recall, LETTER-LEVEL CHECK, marking
audit-gate.mjs, run-checks.sh, fixtures/ — the word gate measured
against 54 real tutor messages
CI runs run-checks.sh in place of validate.mjs alone, and `npm run check`
gains the audit. Baselines: validate PASS 0/0; audit 7 of 41 and 2 of 13.
types/lib/ declares the new API, and test/lib/ pins it: letterCheck on
the prompt's own 짧다/빫다 case, deconjugation, the roadmap-first order
that keeps 마셔 out of Phase 1, sync's three gates, and recall evidence —
including the two ways lib's evidence is looser than PORT.md, pinned as
they are so the call site that tightens them is visibly needed.
TaskHost gains a plain recall renderer so the tree typechecks against the
wider Task union.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
41 lines
1.2 KiB
JSON
41 lines
1.2 KiB
JSON
{
|
|
"name": "hankan",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"description": "Hankan \u2014 a Korean reading tutor for manhwa. Offline-first, web + Android from one codebase.",
|
|
"workspaces": [
|
|
"app",
|
|
"server"
|
|
],
|
|
"engines": {
|
|
"node": ">=22"
|
|
},
|
|
"scripts": {
|
|
"validate": "node validate.mjs",
|
|
"audit": "node audit-gate.mjs",
|
|
"dict:fetch": "node tools/dict/fetch.mjs",
|
|
"dict:build": "node tools/dict/build.mjs",
|
|
"dict:assert": "node tools/dict/assert-roadmap.mjs",
|
|
"typecheck": "tsc -b --pretty",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"lint": "eslint . --max-warnings 0",
|
|
"dev": "npm run dev -w app",
|
|
"build": "npm run build -w app",
|
|
"preview": "npm run preview -w app",
|
|
"cap:sync": "npm run cap:sync -w app",
|
|
"check": "npm run validate && npm run audit && npm run typecheck && npm run test && npm run dict:assert"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "^9.17.0",
|
|
"@types/node": "^22.10.2",
|
|
"eslint": "^9.17.0",
|
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
"typescript": "^5.7.2",
|
|
"typescript-eslint": "^8.18.1",
|
|
"vite": "^6.4.3",
|
|
"vitest": "^3.2.4"
|
|
}
|
|
}
|