Loading
[ loading ]
Loading
[ loading ]
[ data ]taskflow-calendarsha 7d45d4cmeasured-in-repo
taskflow-calendar is a full-stack TypeScript calendar and task platform. The standout is the smart input: type a sentence and a pipeline of parsers turns it into a date, a priority, and entities in real time, scores each one, and resolves the parsers that claim the same words. The frontend suite runs green at the pinned commit.
the algorithm, made physical
Three parsers claim spans of the same line. The resolver settles every overlap by priority, then confidence, and emits clean text with one weighted score, on the record.
resolveConflicts settles each overlap by parser priority first, per-tag confidence second. The contested tomorrow span is dropped because ChronoDate (10) outranks Compromise (6); the kept tags emit clean text and a priority-weighted 0.842 overall confidence.A user types Meet John tomorrow at 3pm for review #high-priority into one field. I have to pull out the date, the priority, and the people, show confidence-scored highlights as they type, and leave behind clean text for the title. None of that is the hard part.
The hard part is that more than one parser will claim the same words. A date parser reads tomorrow at 3pm as a timestamp. A general NLP parser also sees tomorrow as a bare noun and wants to tag it too. Both are right about the characters; only one can win the span. Without a rule for that, the same text gets double-tagged and the title comes out wrong.
Each parser implements one interface: test, parse, priority. SmartParser runs them in priority order, collects every claimed span, and detects the overlaps. Three ship today: ChronoDate at priority 10, Priority at 8, and Compromise at 6.
The resolver settles each overlap by parser priority first, then by per-tag confidence (SmartParser.ts:152-188). It strips the winning spans out of the input, returns the clean remainder as the task title, and folds the surviving tags into one priority-weighted overall confidence (:223-239). Parsers register and unregister at runtime through addParser and removeParser, so adding a new tag kind is one object, not a rewrite. The figure above traces this on the worked example.
The frontend is React 19 and Vite. Client and UI state live in Zustand; server state lives in TanStack Query with optimistic updates. The NLP pipeline sits in src/components/smart-input/parsers/ and runs entirely in the browser, which is what makes the demo below the real code rather than a mock. The backend is split in two: the serverless lib/ path (api/ Vercel functions over a pure-SQL service layer) and the auth-server path (a separate Express + Prisma server in packages/backend/).
lib/ path is the one that dropped Prisma for raw pg; the dashed packages/backend/ Express + Prisma stack runs alongside it. Both reach one PostgreSQL.The README's Technical Decisions section records two moves I stand behind and one consequence I have to keep stating plainly. Each card names what I chose, what it cost, and why.
Dropped Prisma for raw pg in the serverless layer
Built a custom composable middleware chain instead of Express
Caching is process-local InMemoryCache, not Redis
The honest wrinkle: two backend stacks still ship
The named baseline is Todoist. PriorityParser implements Todoist's p1/p2/p3 syntax on purpose, so the smart input lines up with a tool people already know.
There is no quantitative benchmark against Todoist in the repo, so the comparison stays at the level of the syntax, not a stopwatch. The README also claims indexes give 40-60% faster queries. I checked: there is no benchmark script and no EXPLAIN ANALYZE output anywhere in the repo to back it, so that number is not on this page. What I can show is the verified parser output and the test record.
real parser confidences · PriorityParser
The falsifiable evidence is the parser output. These are the base confidences PriorityParser assigns by pattern specificity, with the explicit Todoist p1/p2/p3 rung at the top, boosted to 0.98.
Source: PriorityParser.ts:16-39, real base confidences before context adjustment. The explicit Todoist p1/p2/p3 rung is boosted to 0.98 in adjustConfidence.
the test record at sha 7d45d4c
The README headline is 738 tests passing. That is the collected count across three configs. Here is what actually runs on a clean checkout, and what needs a database.
So the honest read is 634 plus 22 plus 220 pass on a clean checkout; the integration and e2e suites need docker:up to bring up Postgres before they run.
Six places where the platform does the work that matters: the resolver, the weighted-confidence pass, the pure-SQL service base, the cache, and the composable JWT middleware. Each links into the source at the pinned SHA.
The smart-input pipeline is pure browser TypeScript, so the playground runs the real SmartParser on your own text: parsed tags, per-tag confidence bars, the detected conflicts, and the resolved clean text. Nothing there is fabricated. It runs the project's own code.