Files
krow_talent_app/README.md
Aravind e676d259b2
Some checks failed
CI / check (push) Failing after 5m5s
docs: finalize TypeScript migration documentation
The migration is done and the documentation had not caught up. Two files,
no source changes.

README.md. Twenty-seven references still named modules by their old
extension — `main.jsx`, `krowHooks.js`, `AuthContext.jsx` and the rest.
Every one was checked to resolve under its new extension before being
touched. `store.js` is deliberately NOT among them: that file does not
exist under any extension, having been deleted when the transport moved
to HTTP, so "correcting" it to `.ts` would have replaced a visibly stale
reference with a plausible-looking false one. It stays as it is, with the
rest of that architecture section, for a separate pass.

Also: the assertion count 1691 -> 1693, since recapturing the baselines
replaced one check with three; and the Owliver skill count 18 -> 19,
which had been wrong since `create-employee-role` was added.

The "Known-failing checks" section is now "Check status", and the
rewrite is the part worth reading. It claimed two failures that no longer
exist, and my first attempt at replacing it merged two unrelated
histories into one sentence. They are now separate, because they are:

  - The 834/835 suite failure was `the seeded overtime climb is found`.
    It asserted against the live calendar — the oldest week in the window
    thinned as the week wore on and inflated the baseline every later
    week was compared against — so the climb was reported Sunday through
    Thursday and vanished on Friday and Saturday. That is a product
    defect, not a flaky assertion, and it was fixed in
    `src/lib/attendance.ts` at `88c412f` by dropping a leading week
    rostered well below the usual, only from the front so that a genuine
    collapse in the middle is still a finding.
  - The 59 type errors were resolved by this migration.
  - `the backend fixture is in step with this seed` failed for its own
    reasons and is recorded because it is easy to confuse with the first.
    Fixed at `3ddacf2` by teaching the generator to emit the `users`
    array the Go seeder reads, rather than by overwriting the fixture.

All three pass. The heading is kept rather than deleted so the absence of
failures is stated rather than merely implied.

MIGRATION_BASELINE.md is appended to, never edited: 68 lines added, zero
removed, and its first 141 lines are byte-identical to the previous
commit. The 2026-09-11 measurements — 71 errors, 1641/1642, 302 files
linted — are the thing the migration was checked against, so bringing
them up to date would destroy the comparison rather than update it. The
new dated entry is the other end of it, and records how the three items
that document left open were each closed.

  typecheck   0 errors
  lint        exit 0, 0 errors, 289 warnings
  npm test    1693/1693
  build       exit 0, bundle 74d17e2d… unchanged
  seed:check  in step
  owliver     matches the baseline

No file under `src/` changed, which is why the bundle hash cannot move.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HBG1wnuRfJKCstGB8Fekr8
2026-09-20 15:52:12 +05:30

235 lines
11 KiB
Markdown

# KROW Demo
AI-powered hiring for event and hospitality staffing — a standalone demo build of KROW Forge.
Runs with no backend, no API keys and no real login. `npm install && npm run dev` and the app is fully
populated.
```bash
npm install
npm run dev # http://localhost:5173 — opens on /admin/login
```
## Stack
Vite 6 · React 19 · React Router 6 · React Query 5 · Tailwind + shadcn/ui · Framer Motion ·
Recharts + MUI X Charts · react-hot-toast.
## Structure
```
src/
main.tsx entry — mounts <App/>, imports index.css
App.tsx providers + the entire route table
index.css design tokens (HSL CSS variables) + utility layers
api/ the backend seam — see below
base44Client.ts the contract the production app talks to
store.js in-memory entity store, mirrored to localStorage
aiEngine.ts local, deterministic InvokeLLM
seed.ts demo dataset
attendanceSeed.ts shift/attendance dataset
lib/ domain logic and data hooks
krowHooks.ts React Query hooks over the entity store
krowAi.ts AI workflows
krowScore.ts score engine
AuthContext.tsx auth provider
admin/ admin session, permissions, position insights
skills/ the Owliver skill system (registry, resolver, flows)
agents/ the agent system (registry, runtime, lifecycle)
skills/ *.md skill definitions — loaded by import.meta.glob
agents/ *.md agent definitions — loaded by import.meta.glob
components/
ui/ 23 shadcn primitives
ds/ 30 design-system components (the app's real vocabulary)
admin/ admin page shell + role glyphs
krow/ domain components (+ talent/, proving/)
charts/ MUI X Charts wrappers and theme
agents/ agent configure / canvas / test panel
forge/ KROW Forge skill + challenge components
skills/ skill authoring surfaces
ai-assistant/ Owliver — panel, routing, capabilities, history
layouts/ AdminLayout — header nav, ⌘K search, assistant panel
pages/ route components (admin/ holds the live product)
hooks/ shared hooks
assets/ brand asset references
```
## Routes
The app opens on **`/admin/login`**. Everything else lives under `/admin/*` behind two guards:
`ProtectedRoute` (auth) and `AdminRoute` (admin session), rendered inside `AdminLayout`.
| Path | Page |
| --- | --- |
| `/admin/login` | Admin sign-in — outside the protected boundary |
| `/admin` | Control Center |
| `/admin/positions`, `positions/new`, `positions/:id` | Positions, Create, Detail |
| `/admin/candidates`, `candidates/:id` | Candidates, Candidate Intelligence profile |
| `/admin/hired` · `/admin/talent-pool` | Hired History, Talent Pool |
| `/admin/university`, `university/:id` | KROW Forge, challenge detail |
| `/admin/analytics` · `/admin/activity` | Analytics, Activity |
| `/admin/profile` · `/admin/settings` | Profile, Settings |
| `/admin/workspace` | Workspace hub |
| `/admin/workspace/agents`, `agents/new`, `agents/:id` | Agent list, agent editor |
| `/admin/workspace/skills`, `skills/new`, `skills/:id` | UI skill list and editor |
| `/admin/workspace/skills/owliver/new`, `owliver/:id` | Owliver skill editor |
| `/admin/workspace/skill-development` | Skill Development |
| `*` | `lib/PageNotFound.tsx` |
Legacy top-level paths (`/overview`, `/positions`, `/candidates`, `/hired`, `/talent-pool`,
`/university`, `/analytics`, `/activity`, `/tracking`) all `Navigate` into their `/admin/*`
equivalent, id preserved. Static route segments are declared before dynamic ones so
`workspace/agents/new` cannot be read as an agent whose id is `"new"`.
> **Note.** `App.tsx` still imports a set of pre-redesign Employer/Talent pages
> (`Overview`, `Apply`, `WorkerProfile`, `KrowIdentity`, `EmployeeDashboard`, `DesignSystem`, …)
> and `layouts/Layout.tsx`. None of them are mounted on a route — they are unreachable at runtime
> and retained pending a decision on whether to re-route or remove them.
## The backend seam
The production app talks to a Base44 backend through `src/api/base44Client.ts`. This demo keeps that
module path, export name and full method contract, and swaps only the transport:
| Contract | Demo implementation |
| --- | --- |
| `base44.entities.<Name>.list/filter/get/create/update/delete` | `api/store.js` — in-memory records, mirrored to `localStorage` |
| `base44.integrations.Core.InvokeLLM` | `api/aiEngine.ts` — local, deterministic |
| `base44.integrations.Core.UploadFile` | blob URLs, session-scoped |
| `base44.auth.*` | seeded employer/admin user, always signed in |
Because the seam did not move, everything above it — `lib/krowHooks.ts`, `lib/krowAi.ts`,
`lib/krowScore.ts`, every page and component — is unchanged from the reference implementation.
## The AI engine
Every AI workflow funnels through one call, `InvokeLLM({ prompt, response_json_schema })`.
`api/aiEngine.ts` reimplements it locally: it recognises each workflow by the phrase its prompt opens
with, reads the structured fields the prompt already carries (`Years Experience: 6`,
`Required Certifications: …`, the talent-pool JSON block) and scores them deterministically.
Nine workflows are implemented: candidate screening, job-description generation, résumé building,
interview questions, interview evaluation, talent matching, Owliver's conversation, Career DNA
building and Proving Ground evaluation. Results respond to the data rather than being canned — the
same input always returns the same output.
## Skills and agents
Two registries discover their definitions from markdown at build time:
| Registry | Glob | Files |
| --- | --- | --- |
| `lib/skills/registry.ts` | `import.meta.glob('/src/skills/**/*.md')` | 19 Owliver skills, 5 workforce training skills |
| `lib/agents/registry.ts` | `import.meta.glob('/src/agents/**/*.md')` | 9 agent definitions |
**These globs are absolute paths.** Moving or renaming `src/skills/` or `src/agents/` makes the
registry silently return nothing — no build error, no import failure, just an empty registry. Add
definitions by dropping a new `.md` file into the right folder; nothing else needs to change.
## Demo data
Seeded in `src/api/seed.ts` — positions, applicants, AI-scored candidates, interviews, hires,
talent-pool profiles, Proving Ground courses and an activity log; shift data in
`src/api/attendanceSeed.ts`.
Edits persist to `localStorage`. To restore the shipped dataset:
```js
// in the browser console
localStorage.removeItem('krow_demo_db'); location.reload();
```
Bumping `STORAGE_VERSION` in `src/api/store.js` (currently `8`) invalidates saved snapshots
automatically, so changing the seed does not require a manual clear.
## Design system
Tokens live in `src/index.css` as HSL CSS variables consumed by `tailwind.config.js`.
| Token | Value |
| --- | --- |
| Primary — KROW Blue | `#0A39DF` |
| Accent — KROW Yellow | `#F9E547` |
| Pale Yellow | `#F8E08E` |
| Dark Navy | `#333F48` |
| Mint | `#D1E0D7` |
| Radius | `0.75rem` |
| Headings | Sora |
| Body | Inter |
`src/components/ds/` is the vocabulary the app actually writes in — `Surface`, `KpiCard`,
`DataTable`, `PageHeader`, `Modal`, `toast` and the rest, exported through `ds/index.ts`.
`src/components/ui/` holds the shadcn primitives those are built on. Surfaces use `glass` and
`glass-card`; the page background is the `gradient-mesh` utility.
Toasts go through `ds/toast` (a wrapper over `react-hot-toast`), rendered by `<HotToaster>` in
`App.tsx`.
## Scripts
| Command | Purpose |
| --- | --- |
| `npm run dev` | Dev server (honors `PORT`, default 5173) |
| `npm run build` | Production build |
| `npm run preview` | Serve the build |
| `npm run lint` | ESLint — currently clean |
| `npm run lint:fix` | ESLint with `--fix` |
| `npm test` | `scripts/skill-check.mjs` — 1693 assertions over the skill and agent systems |
| `npm run typecheck` | `tsc -p ./tsconfig.json` — 0 errors across 321 TypeScript files |
### The test harness
`npm test` boots a real Vite dev server in middleware mode and `ssrLoadModule`s the actual
application modules, so it exercises the real `@/` alias and `import.meta.glob` pipeline rather than
mocks. It also diffs Owliver's behaviour across eleven page contexts against a committed snapshot,
`scripts/__baseline__/owliver-baseline.json`; regenerate that deliberately with
`node scripts/owliver-baseline.mjs --write`, never to turn a red check green.
Because it loads modules by absolute path, the harness pins the locations of `src/api/`, `src/lib/`,
`src/lib/skills/`, `src/lib/agents/`, `src/components/ai-assistant/`, `src/App.tsx`,
`src/layouts/AdminLayout.tsx` and a handful of agent files. Move any of them and update
`scripts/owliver-capture.mjs` and `scripts/skill-check.mjs` in the same change.
### Check status
Everything above passes on a clean checkout: `npm test` is 1693/1693 and
`npm run typecheck` reports no errors.
This section used to list two known failures — 834/835 on the suite, and 59 type
errors across `lib/krowAi`, `lib/skills/*` and `lib/positionModel`. Both are
gone, and they were unrelated to each other.
The suite failure was `the seeded overtime climb is found`. It asserted against
the live calendar: the shifts are generated by counting back from the day the
suite runs, so the oldest week in the window thinned as the week wore on and
inflated the baseline every later week was compared against. The climb was
reported Sunday through Thursday and vanished on Friday and Saturday. That was a
product defect rather than a flaky assertion, and it was fixed in
`src/lib/attendance.ts` (commit `88c412f`) by dropping a leading week rostered
well below the usual — only from the front, so a genuine collapse in the middle
is still a finding. `the seeded overtime climb is detectable on every day of the
week` re-runs the detector against 28 consecutive anchors and is what keeps it
fixed.
The type errors were resolved by the TypeScript migration.
A third check, `the backend fixture is in step with this seed`, failed for its
own reasons and is recorded here because it is easily confused with the above:
`seed.json` in the sibling backend had drifted from this seed module. Fixed in
commit `3ddacf2` by teaching the generator to emit the `users` array the Go
seeder reads, rather than by overwriting the fixture. All three pass.
The heading is kept rather than deleted so that the absence of failures is
stated rather than merely implied.
## Deployment
`Dockerfile` builds with `node:22-alpine` (capped at 1 GB heap for small hosts) and serves the
static `dist/` from `nginx:alpine` using `nginx.conf` — gzip, immutable `/assets/` caching and an
SPA fallback to `index.html` so client-side routes resolve on refresh.