dorsaltegmentum/lt-suite
v0.2.4AGPL-3.0-or-later
Unofficial tools to capture, draft, diagram, fill and export Lt learning modules.
Changelog
lt-suite records notable changes using Keep a Changelog 1.1.0. Versions follow Semantic Versioning 2.0.0.
[Unreleased]
Changed
- Update fonttools to 4.68.0 in
uv.lockand the skill requirements.
Fixed
- Accept Dependabot's sign-off in the pull-request DCO check, only on pull requests that Dependabot opened.
[0.2.4] - 2026-11-02
Added
- Report blocked mutator rebinds in script receipts as
guard_rebinds_blocked. - Name the commit mutators that got the start-up placeholder in
LtGuard.status().late_define_blockedand in script receipts asguard_late_define_blocked. - Count replies read only in part (past 32 levels or 50,000 values) as
resp_truncatedinnet_diag. - Add
binding: "unbound-legacy"to a fill report item's receipt when the receipt carries nosource_payload. - Add
fill-notes.schema.json, a template thatemit_fill.py payloadwrites, andmake_fill_report.py --check-notes, which lists every problem at once and writes nothing. - Add
emit_fill.py repin, which moves a payload'sanswers.jsonpin after a change that leaves every written draft identical, checks the question digest, and never writesanswers.json. - Add
run_notesto fill notes and reports, andsource_check_planto reports. - Print
MANUAL MODEpages,held for approvalcounts and each single-attempt item's captured state ("answered, not submitted") inplan_fill.py. - Optional loopback body server (
browser.body_server, off by default): on a page-cache miss the loader fetches the body by SHA-256 from the host and checks it before running it. tools/install_body_server.pycopies the server into a host-only folder after checkingpackaging/host-files.sha256, and writes a systemd user unit it never enables.ltjs.py render cache_statusreports which page scripts the origin's cache holds, without running them.- Add
browser.devtools_socketso lt-chrome reaches a DevTools port through a Unix socket from a sandbox with its own network. - Report the socket's state and the chosen route in doctor.
Changed
- Hold single-attempt drafts without an approval in the plan; the report lists them skipped, "yours to check and submit", with no note needed.
- Refuse a stale
page-kinds.jsonat payload time with or without a RAT candidate page; the report applies the same rule. - Default
started_atto the earliest bound payload'sgenerated_atandended_atto the last receipt; a notes time that differs needstimes_reason. - Replace
fill-report.jsononly after the validator passes the new report; a rejected report goes tofill-report.rejected.json. - Rename the capture summary field
table_author_gridstotable_given_grids; the capture skill reads either name in stored receipts. - Return 16-hex
source_payload_sha16and uploadsha16values in browser receipts in place of full sha256 values. - Refuse
record --supersedeon a stored row withoutverify_receipt_sha256, and archive the fields that changed. - Every
need:'payload'reply names itsreason. - The page cache keeps entries in least-recently-used order within 524,288 characters; a hit refreshes its entry.
- Cached bodies no longer carry the lt-suite version, so a release keeps unchanged scripts cached.
- With a body server, loaders name a plan policy longer than 256 characters by SHA-256 instead of carrying it.
Fixed
- Record each page's real Lt route in captures. A Background page gets
/run/backgroundand flow page N after it gets/run/page/N-1. Capture takes each number from the page'sdataKey, checks it against the tab's URL and painted page, and leavesurlnull when they disagree. New captures carryroute_source. - Refuse page routes from every capture without
route_source, whatever its titles or boundaries. Nothing else in it reliably marks a Background page, after which its URLs were one page late and could pass a live Checkpoint.check-urland the guard reportrecapture-needed, and media, fill and check plans drop those URLs. Export and answer drafting still read such a capture. - Refuse a plan without the
route_sourcekey, which was built before measured routes and holds no titles or source URL to check. Media, fill and check plans always write the key,nullallowed. - Map
/run/backgroundonly through a captured url, never by default to flow page 1. - Reject plans in which two pages claim one route or a URL number exceeds the pages before it.
- Accept Background pages, unconfirmed routes and
route_sourcein the module schema and validator, and check that URLs matchpage_no. - Let Lt's start-up call
removeCommittedCheckpointsandremovePagesAfterUncommittedCheckpointsbefore it paints a page. The guard locks both once a page paints orrender_wait_msruns out, and runs no script body before then. - Give
commitClickedorsetCheckpointCommitState, when Lt has not defined it yet, a non-configurable placeholder accessor on$rootfrom the moment the guard installs. A raw call throws at once. Lt's plain assignment lands without throwing and never becomes callable. Lt'sObject.definePropertyon the name throws inside Lt, so a late definition can no longer replace the accessor and run before the next check. The two page-list mutators Lt has not defined lock on$rootwhen start-up ends. - Check the route again after the guard's wait, so the page Lt painted meanwhile decides.
- Wait up to
render_wait_msfor a painted page before the fill location rail andfetch_mediareadcurrent(). Refuse withlt-not-paintedwhen none paints; the fill receipt carriesguard_last. - Identify Lt's run-data
PUTby typedpanelKey,dataKeyoruuidfields, so 3- and 4-digit panel keys can be acknowledged. - Never acknowledge a run-data save on a bare 2xx: require a per-key success or a top-level
"success": truereply. - Fail keys whose single-key reply is HTTP 200 with
{"success": false}. - Leave every run-data key pending when a success reply carries a failure marker at any depth, such as
{"success": true, "data": {"success": false}}or a nestedstatus: "failed". - Fail a reply item (an object with an identity field) when a failure marker sits anywhere inside it, whatever its own
successsays, so{"results": [{"panelKey": 209, "success": true, "result": {"success": false}}]}fails panel 209. Sibling items keep their own outcomes. - Confirm no key of a request whose reply carries a failure marker outside every item, lists a failed value that names no key of the request, or runs past 32 levels or 50,000 values. Inspection used to stop at 8 levels and accept the rest.
- Leave a generic single-key save unconfirmed when its reply carries any failure marker, such as
{"success": true, "data": {"success": false}}. - Sign the Lt client build by the URLs, query strings included, of the core bundles loaded before
DOMContentLoaded, so page chunks loaded later no longer drop calibration and/core.js?v=2no longer keeps a calibration made on/core.js?v=1. - Drop save records bound to the old
c1-script signature once, with the reason in the calibration history. - Keep the save record when a fill page shows no build marker.
- Record
keys_weak,net_matchedandsave_key_sourcein fill receipts, andkeys_weakandnet_matchedin saved waits. - Compute
save_diagmodel_syncper request row, and add run-data identity counts tosave_diag. - Name the hash each browser receipt bound by, and the local payload file check, in report items.
- Name every
--payloadpath thatrecordcannot use, and a payload path outside the run in report binding refusals. - Print each stored receipt row that
recordkeeps because only its binding differs. - Treat any
[BLOCKED:value in a receipt's full payload hash as redacted. - Reject a fill report in a run folder whose
fill-js/check-plan.jsonit predates. - Rebuild every job of a payload from the current
answers.jsonbeforemake_fill_report.pytrusts ananswers-repin.jsonrecord, and refuse on any difference.repinrecords the--anchorsand--approvalsit used. - Compare rebuilt and written jobs in
repinand in the report by sha256 of their content (page, panel, text, each table cell's row and column, selections and placements). The 32-bit receipt hash used before let a text with a colliding hash, or a table cell moved to another row, re-pin and verify. - Report an ordinary item
filled-unverified, neverfilled, when its latest receipt carries nosource_payload: such a receipt is tied to no executed payload and not to today's draft. Only a receipt bound to an executed payload whose jobs match today's draft verifies. - Start the default run window at the earliest bound payload's
generated_at. When no receipt binds a payload it starts at the earliest payload in the run folder, and at the first receipt only when the run folder holds none. Refuse a receipt observed before its own payload was built. - Name a body server miss only from a fixed set of reasons, so reply text never reaches a receipt.
- Accept
/run/backgroundin the fill location rail and the panel probe for the plan's Background page, placed bycurrent(). - List
fill-notes.schema.jsonandreferences/fill-notes.mdin the release allowlist, so release archives build. - Read a
Signed-off-bywritten below a---line, as Dependabot writes it, in the public history check. - Warn in doctor when the stable lt-chrome launcher is missing and the config serves lt-chrome tools.
[0.2.3] - 2026-10-26
Changed
- Inline fill calls reuse one cached runner with current frozen arguments and guard policies.
- Download handoffs use paced groups of 8 and report missing media keys by page.
- Media calls use a configurable 20 second budget and return pending keys for resumed downloads.
Fixed
- Show local citation paths by file name in exported notes and PDFs.
- Name each failed receipt binding check and reserve the RAT prefix for RAT receipts.
- Preserve hyphens at wrapped line ends when checking PDF content.
- Accept bounded save request diagnostics in fill reports and export validation.
- Use a neutral receipt binding message for ordinary fill receipts.
- Keep payload discovery inside each run and resolve manifest paths from their containing folders.
- Bind fill records to the executed payload, including payloads generated in sibling folders.
- Refuse conflicting receipt hashes and archive corrected rows with
record --supersede. - Refuse draft status text in answer segments and payload HTML through configurable patterns.
- Check the answer file capture path and hash binding before generating fill payloads.
- Wait for the Lt view model and refuse calls while commit guards remain unlocked.
- Include compact request diagnostics in fallback save receipts and saved wait records.
- Measure table occupancy over target cells while reporting other filled cells separately.
- Name stale page classifications and the command that refreshes them before checking receipt bindings.
- Add short payload hashes for browser tools that redact full hashes and bind unique matches.
[0.2.2] - 2026-10-26
Changed
- Inline browser tools receive gzip compressed page scripts with SHA-256 verification.
- Page cache loaders reuse verified code with current frozen arguments and guard policies.
- Chunked payload snippets verify numbered transfers before the stub assembles its body.
[0.2.1] - 2026-10-26
Added
- Opt-in
export.citations.transcript_page_from_filenamelinks recording citations to notes pages named after recording files.
Fixed
- Table cells no longer repeat the answer's citations when cell provenance references are absent.
0.2.0 - 2026-10-25
Added
- Separate fonts for page PDFs, diagrams and micrograph labels, with Noto and system fallback chains.
- Palette-matched micrograph copies bound to their upload and captured media for PDF and notes exports.
- Configurable Chromium selection, profile folders and loopback DevTools attachment through lt-chrome.
- Setup questions and doctor checks for output fonts, browser attachment, RAT sheets and Check Answer.
- Quarantined RAT answer-sheet folders, matching and shared page classification for permitted sheet entry.
- Opt-in Check Answer retries for eligible multi-attempt items, with attempt records and reconciled exports.
Changed
- Exported SVGs and interactive diagram pages carry font fallback stacks for other machines.
- RAT filling and Check Answer share current page classifications; Check Answer refuses RAT pages.
Fixed
- Windows text encoding, line endings, interpreter pinning and path handling.
- Check Answer refuses changed live classification inputs and requires recapture and reclassification.
- lt-chrome rejects unknown browser keys and nested paths before selecting startup defaults.
- Font discovery handles system filenames and checks every rendered face before font modification.
- Micrograph exports reject malformed, stale or edited palette-copy manifests.
- Fill receipts retain the executed sheet identity and reject changed classification bindings.
- Unread Check Answer verdicts require a fresh document before further checks.
Security
- Font embedding and modification respect licence metadata and embedding restrictions.
- lt-chrome validates loopback addresses and isolates npm startup from workspace configuration.
- RAT sheets and Check Answer feedback stay outside cited research and curriculum reads.
0.1.0 - 2026-10-24
Added
- Six skills:
lt-suite-setup,lt-module-capture,lt-module-answer,lt-module-fill,lt-module-export, andmechanistic-diagram. - Accessible defaults with Noto Sans and Noto Sans Mono, measured palette selection, and configurable alternatives.
- Event-driven save waits that observe acknowledgements and retain a bounded fallback.
- Automatic per-origin calibration after a verified first page, followed by a verified two-page trial.
- Batches of up to five pages after calibration; missing saves restore single-page operation.
- Multi-agent packaging for supported plugin clients and standalone skill archives.
- Synthetic examples, privacy checks, licence notices, and a Developer Certificate of Origin policy for pull requests after release.
Changed
- Browser navigation waits for save evidence and verifies writes after a fresh reload.
- Institution settings, output paths, palettes, and fonts use configuration.
Removed
- The permission gate and its configuration, scripts, and call sites.