generative-ai-e2
TCS Gen AI E2 bootcamp.
the_problem
In an ITSM operation the ticket is born in Freshservice and the work happens in Jira. Moving one to the other is manual, and the link between the two systems exists only as free text somebody typed into a card title.
what_it_does
- Freshservice to Jira: ticket ingestion, routing to the correct squad, idempotent issue creation, traceability and audit.
- An agile workspace (sprint, backlog, drag-and-drop board) projected from Jira at request time rather than cached.
- A local RAG lab over the repository’s own documentation, indexed in SQLite with sqlite-vec and exposed over MCP.
- A conversational assistant with document upload and tree-structured retrieval.
stack
frontend
Next.js (App Router) · React 19 · Tailwind CSS v4 · shadcn/ui on Base UI
backend
Python 3.11+ · FastAPI · SQLAlchemy 2 · Alembic · PostgreSQL 16
other
SQLite + sqlite-vec · sentence-transformers · OpenRouter · Model Context Protocol · GitHub Spec Kit
measured
- Link coverage, manual process
- 72.9%312 of 428 exported cards matched a real ticket
- Official ticket field filled in
- 1 / 428Freshservice ticket field across the historical export
- Classifier accuracy
- 83.33%19-case golden set, measured 2026-07-30
- Prompt-injection vectors that succeeded
- 1 / 3the reason the classifier ships disabled
how_it_was_built
Spec-driven through GitHub Spec Kit: thirteen numbered specifications, each with its specification, plan, research, data model, task list, quickstart, contracts and requirements checklist. A project constitution that prevails over everything else. Architectural decisions recorded as numbered ADRs, 005 through 013.
The problem was measured against real exports rather than estimated. Of 428 cards exported, 368 carried an extractable ticket number in the title and 312 matched a real ticket, so 72.9% link coverage. The official Freshservice ticket field was filled in on exactly one card out of 428. Against the automation, where the identifier lives in a structured issue label rather than depending on anyone typing it, coverage is 100% by construction.
The README spends more space on deliberate limitations than on features, and each one carries its reason and its exit condition. That is the point of the project, not a caveat to it.
known_limitations
- The LLM classifier is implemented, tested and switched off by default. Against a 19-case golden set measured on 2026-07-30: 83.33% accuracy, 37.50% abstention, and one of three prompt-injection vectors succeeded. A ticket’s subject and description are untrusted input written by whoever opens it, so enabling the classifier would hand the choice of destination squad to that person. A closed enum protects against malformed output, not against output that is valid but manipulated.
- The accuracy drop against the previous provider, 100% to 83.33%, is declared as expected rather than reported as a regression: different models, each measured honestly against its own provider. The golden set decides, it does not confirm.
- SLA status does not exist at source. The queue has an SLA column because the requirement asks for one, but no deadline arrives from Freshservice, so the column renders an em dash labelled "no deadline known at source". Deriving a deadline from the retry timestamp would be inventing a number nobody could audit in a presentation.
- The agile workspace does not work offline, by decision: a cached sprint would lie during a live demonstration. Without credentials the screens render a named state (not configured, unauthorised, unavailable, rate limited) rather than an error.
- Freshservice runs against a mock rather than the real tenant, because the client’s administrator never released the API key. The squad enum was made generic, and the test suite runs green with no credentials and no network.
- One dependency was added against the project’s own rule about not adding a dependency where an installed one would do. It is recorded as a conscious decision rather than quietly left in.
tracked coding time
32 hrs 8 mins Source: WakaTime · tracked 2026-03-17 to current