Skip to content

Latest commit

 

History

History
194 lines (148 loc) · 9.8 KB

File metadata and controls

194 lines (148 loc) · 9.8 KB

Architecture

TimetableKit is a pnpm workspace. Its core package owns the timetable contract and deterministic behavior. Other packages add input, UI, transport, and provider boundaries around that core.

Package map

apps/web
  browser boundary, playground, local OCR wiring, schema routes, security headers

packages/core
  input schemas, deterministic parsing, normalization, validation, conflicts,
  assessment, corrections, locale registry, JSON/CSV/iCalendar exporters

packages/agent
  JSON tool definition, capabilities, bounded base64 input, JSONL transport

packages/cli
  local file and stdin input, output files, command-line validation

packages/react
  optional review, correction, agenda, and calendar components

packages/provider-pdfjs
  PDF.js text extraction and scanned-page rendering

packages/provider-tesseract
  local browser OCR for raster images

packages/provider-vercel-ai
  opt-in structured recovery for unresolved fields

examples, fixtures, docs
  consumer examples, synthetic test data, and project guidance

The dependency direction is inward. The core does not import browser, file system, OCR, PDF.js, React, Next.js, Vercel, or model SDK code. Provider and UI packages import the public core package.

Data flow

flowchart LR
  A[Text, CSV, image, or PDF] --> B[Input schema and limits]
  B --> C[Configured extraction provider]
  C --> D[Bounded text document]
  D --> E[Core parser and locale rules]
  E --> F[Normalized events]
  F --> G[Validation and conflict detection]
  G --> H[Versioned parse result]
  H --> I[Review and typed correction]
  I --> J[JSON, CSV, or iCalendar]
  H -. optional unresolved fields .-> K[Consented recovery provider]
  K --> G
Loading

The input boundary accepts only the supported discriminated union. It checks the input schema before provider work. A provider returns an ExtractionArtifact with a source descriptor, pages, text lines, locations, and provider warnings.

The core converts that artifact into candidates, normalizes fields, validates the complete result, detects conflicts, and returns a schema version of 1.0. The result keeps warnings, source evidence, confidence, provider IDs, and stage reports together so a caller can build a review flow without reading parser internals.

Ownership rules

Use this map before you change code.

Change Package or path
Input shapes, locale aliases, date and time recognition, normalization, warnings, validation, corrections, conflicts, or exports packages/core
PDF loading, page rendering, OCR handoff packages/provider-pdfjs
Image OCR worker lifecycle packages/provider-tesseract
Remote recovery request and output validation packages/provider-vercel-ai
Agent schemas, capabilities, JSONL framing, structured errors packages/agent
Local paths, stdin, output files, and CLI messages packages/cli
React review and correction views packages/react
File selection, playground state, browser routes, and local asset wiring apps/web
Public parser behavior fixtures, packages/core/tests, and the generator definitions

Keep parser rules in packages/core. Keep browser, filesystem, OCR, PDF, and remote provider code outside the core package.

Do not import another workspace package through its src directory. Build the core package before you typecheck a provider package. The lint command checks import and re-export syntax in packages, apps, and examples. It permits a package to use its own source, but requires other consumers to use public exports. Type-only imports and literal dynamic imports follow the same rule.

Core boundaries

Input boundary

TimetableInputSchema accepts UTF-8 text and CSV strings, or Uint8Array bytes with an allowed image or PDF MIME type. The core applies byte, pixel, page, timeout, and output limits. It treats all content as data.

The core does not follow URLs found in timetable content. It does not execute commands or instructions found in imported text, OCR output, or PDF text.

Provider boundary

An extraction provider declares support for an input kind and returns a validated artifact. The parser tries configured providers in order. A provider can report progress and must honor the supplied abort signal and limits.

The parser maps provider failures to stable warnings when it can continue. It returns an unusable result when no provider can produce an artifact. A caller abort remains an ABORTED error.

Recovery boundary

Recovery is a separate provider interface. The core collects only unresolved event fields linked to warnings. Recovery is disabled unless the host configures a provider and the parse options set both enabled: true and consent: true.

The provider receives a bounded request and returns schema-checked patches. The core accepts patches only for requested fields, applies them as typed changes, and runs validation and conflict detection again. A failed recovery attempt keeps the deterministic result available.

Transport boundary

The agent package turns JSON requests into core inputs and turns results or failures into JSON-safe responses. The CLI adds local path and stdin handling. Neither package duplicates parser rules. The agent checks cancellation before calling an injected parser and stops waiting when the signal aborts. It does not accept a successful result after cancellation. Custom parsers must still honor the signal to stop their own work.

UI boundary

The web app and React package consume the public result, warning, assessment, and correction APIs. They do not decide a second set of parser rules. The web playground keeps selected content in browser memory and wires local OCR and PDF providers when the user selects binary input. Each input tab owns its draft in memory. Switching tabs changes the active source without discarding other drafts. Reset clears every draft and the current result. The editor renders at most 50 event rows per page. Corrections and exports still use the full result. Paging moves keyboard focus to the table.

Result and state model

The core result is immutable by convention. applyEventCorrection returns a new result when a field changes and recomputes warnings, conflicts, and the deterministic confidence summary. Generated event IDs stay unchanged when unique. If different events collide, normalization sorts their canonical keys and adds suffixes to disambiguate them before attaching warnings. It returns the original result for an unknown event or a no-op correction. React correction callbacks compose edits made before the next parent render. A new result supplied by the parent replaces that pending correction state.

Conflict detection prepares times and exact-date membership once per detector call. The cache is local to that call, so later calls read current input values. Pair traversal and resource limits remain the same.

Assessment is derived state. assessTimetableResult and analyzeTimetableResult check events, warnings, event semantics, term bounds, and bounded conflicts. Assessment is not stored in TimetableParseResult and is not serialized into JSON, CSV, or iCalendar output. The core exports the assessment functions and the ResultAssessment type for callers.

Stage reports keep the public pipeline vocabulary stable. The current deterministic parser performs several row-recognition operations during normalize, while the reports still expose the stages preflight, extract, normalize, segment, recognize, assemble, locale, deduplicate, validate, conflicts, confidence, recovery, and finalize.

Privacy and security constraints

The default path is local and in memory. Do not add logging, persistent upload storage, remote URL fetching, or real user schedules to fixtures. A remote provider must be optional, visible to the host, bounded, cancellation-aware, schema-validated, and covered by a data-retention policy.

See Privacy, Security, and Providers before adding an external service.

Verification

Run the smallest relevant check while developing. Run pnpm validate before a release or after a cross-package change. The full command checks formatting, package metadata, source boundaries, copy, types, tests, coverage, fixtures, builds, browser behavior, local links, secret patterns, and dependencies.

The validation command is local evidence. It does not prove package publication, deployment, hosted CI, OCR accuracy with a real worker, or a third-party provider's retention behavior.