chore: add file headers (author, contact, copyright, description) to all source files
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
50 changed files +457 −0
modified
apps/etl/src/airiskindex_etl/__init__.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: __init__.py | ||||
| 2 | +# Path: apps/etl/src/airiskindex_etl/__init__.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: ETL package: raw source dumps -> derived artifacts -> Postgres. | ||||
| 9 | + | ||||
| 1 | """AI Risk Index ETL: raw source dumps -> derived artifacts -> Postgres. | 10 | """AI Risk Index ETL: raw source dumps -> derived artifacts -> Postgres. | ||
| 2 | 11 | ||||
| 3 | Raw data is never edited in place (CLAUDE.md §1); every derived artifact gets a | 12 | Raw data is never edited in place (CLAUDE.md §1); every derived artifact gets a | ||
modified
apps/etl/src/airiskindex_etl/download_oews.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: download_oews.py | ||||
| 2 | +# Path: apps/etl/src/airiskindex_etl/download_oews.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: Fetch BLS OEWS national wage data into data/raw/oews/. | ||||
| 9 | + | ||||
| 1 | """Fetch BLS OEWS national wage data (May 2025) into data/raw/oews/. | 10 | """Fetch BLS OEWS national wage data (May 2025) into data/raw/oews/. | ||
| 2 | 11 | ||||
| 3 | BLS blocks non-browser user agents — a descriptive UA with contact info works. | 12 | BLS blocks non-browser user agents — a descriptive UA with contact info works. | ||
modified
apps/etl/src/airiskindex_etl/download_onet.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: download_onet.py | ||||
| 2 | +# Path: apps/etl/src/airiskindex_etl/download_onet.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: Fetch the O*NET database text dump into data/raw/onet/. | ||||
| 9 | + | ||||
| 1 | """Fetch the O*NET database text dump into data/raw/onet/ (immutable). | 10 | """Fetch the O*NET database text dump into data/raw/onet/ (immutable). | ||
| 2 | 11 | ||||
| 3 | O*NET 30.x — CC BY 4.0, attribution required. 30.x renamed | 12 | O*NET 30.x — CC BY 4.0, attribution required. 30.x renamed | ||
modified
apps/etl/src/airiskindex_etl/load.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: load.py | ||||
| 2 | +# Path: apps/etl/src/airiskindex_etl/load.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: Load derived CSVs into Postgres (idempotent upserts). | ||||
| 9 | + | ||||
| 1 | """Load derived O*NET + OEWS CSVs into Postgres (idempotent upserts). | 10 | """Load derived O*NET + OEWS CSVs into Postgres (idempotent upserts). | ||
| 2 | 11 | ||||
| 3 | Occupations are keyed by O*NET-SOC code; wages join by SOC prefix | 12 | Occupations are keyed by O*NET-SOC code; wages join by SOC prefix | ||
modified
apps/etl/src/airiskindex_etl/transform.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: transform.py | ||||
| 2 | +# Path: apps/etl/src/airiskindex_etl/transform.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: Transform raw O*NET + OEWS dumps into derived CSVs with a manifest. | ||||
| 9 | + | ||||
| 1 | """Transform raw O*NET + OEWS dumps into derived CSVs with a manifest. | 10 | """Transform raw O*NET + OEWS dumps into derived CSVs with a manifest. | ||
| 2 | 11 | ||||
| 3 | Raw is never edited in place; derived payloads are gitignored, only the | 12 | Raw is never edited in place; derived payloads are gitignored, only the | ||
modified
apps/etl/tests/test_smoke.py
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +# File: test_smoke.py | ||||
| 2 | +# Path: apps/etl/tests/test_smoke.py | ||||
| 3 | +# Project: AI Risk Index — airiskindex.io | ||||
| 4 | +# Author: Simon-Pierre Boucher | ||||
| 5 | +# Contact: contact@spboucher.ai | ||||
| 6 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +# | ||||
| 8 | +# Description: ETL smoke tests (source configuration). | ||||
| 9 | + | ||||
| 1 | from airiskindex_etl.download_onet import ONET_URL, ONET_VERSION, RAW_DIR | 10 | from airiskindex_etl.download_onet import ONET_URL, ONET_VERSION, RAW_DIR | ||
| 2 | 11 | ||||
| 3 | 12 | ||||
modified
apps/web/app/api/v1/health/route.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: route.ts | ||||
| 2 | +// Path: apps/web/app/api/v1/health/route.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public API: health check with index version. | ||||
| 9 | + | ||||
| 1 | import { INDEX_VERSION } from "@airiskindex/scoring"; | 10 | import { INDEX_VERSION } from "@airiskindex/scoring"; | ||
| 2 | 11 | ||||
| 3 | export const dynamic = "force-dynamic"; | 12 | export const dynamic = "force-dynamic"; | ||
modified
apps/web/app/api/v1/methodology/route.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: route.ts | ||||
| 2 | +// Path: apps/web/app/api/v1/methodology/route.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public API: machine-readable weights and version metadata. | ||||
| 9 | + | ||||
| 1 | import { | 10 | import { | ||
| 2 | DIMENSIONS, | 11 | DIMENSIONS, | ||
| 3 | EXPOSURE_DIMENSIONS, | 12 | EXPOSURE_DIMENSIONS, | ||
modified
apps/web/app/api/v1/occupations/[code]/route.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: route.ts | ||||
| 2 | +// Path: apps/web/app/api/v1/occupations/[code]/route.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public API: full score breakdown for one occupation. | ||||
| 9 | + | ||||
| 1 | import { prisma } from "@airiskindex/db"; | 10 | import { prisma } from "@airiskindex/db"; | ||
| 2 | import { INDEX_VERSION } from "@airiskindex/scoring"; | 11 | import { INDEX_VERSION } from "@airiskindex/scoring"; | ||
| 3 | import type { NextRequest } from "next/server"; | 12 | import type { NextRequest } from "next/server"; | ||
modified
apps/web/app/api/v1/occupations/route.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: route.ts | ||||
| 2 | +// Path: apps/web/app/api/v1/occupations/route.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public API: occupation list/search (paginated). | ||||
| 9 | + | ||||
| 1 | import { prisma } from "@airiskindex/db"; | 10 | import { prisma } from "@airiskindex/db"; | ||
| 2 | import { INDEX_VERSION } from "@airiskindex/scoring"; | 11 | import { INDEX_VERSION } from "@airiskindex/scoring"; | ||
| 3 | import type { NextRequest } from "next/server"; | 12 | import type { NextRequest } from "next/server"; | ||
modified
apps/web/app/globals.css
+11 −0
@@ -1,3 +1,14 @@ | |||||
| 1 | +/* | ||||
| 2 | + File: globals.css | ||||
| 3 | + Path: apps/web/app/globals.css | ||||
| 4 | + Project: AI Risk Index — airiskindex.io | ||||
| 5 | + Author: Simon-Pierre Boucher | ||||
| 6 | + Contact: contact@spboucher.ai | ||||
| 7 | + Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 8 | + | ||||
| 9 | + Description: Design tokens (validated dataviz palette roles), card idiom, hero wash, drawer animation. | ||||
| 10 | +*/ | ||||
| 11 | + | ||||
| 1 | @tailwind base; | 12 | @tailwind base; | ||
| 2 | @tailwind components; | 13 | @tailwind components; | ||
| 3 | @tailwind utilities; | 14 | @tailwind utilities; | ||
modified
apps/web/app/layout.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: layout.tsx | ||||
| 2 | +// Path: apps/web/app/layout.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Root layout: sticky header, mobile drawer menu, preview banner, footer. | ||||
| 9 | + | ||||
| 1 | import type { Metadata, Viewport } from "next"; | 10 | import type { Metadata, Viewport } from "next"; | ||
| 2 | import Link from "next/link"; | 11 | import Link from "next/link"; | ||
| 3 | import type { ReactNode } from "react"; | 12 | import type { ReactNode } from "react"; | ||
modified
apps/web/app/methodology/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/methodology/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Human-readable methodology documentation (weights pulled live from the engine). | ||||
| 9 | + | ||||
| 1 | import Link from "next/link"; | 10 | import Link from "next/link"; | ||
| 2 | import { | 11 | import { | ||
| 3 | DIMENSIONS, | 12 | DIMENSIONS, | ||
modified
apps/web/app/occupations/[code]/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/occupations/[code]/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Occupation detail: sub-score tiles, dimension breakdown, per-task rater audit trail. | ||||
| 9 | + | ||||
| 1 | import Link from "next/link"; | 10 | import Link from "next/link"; | ||
| 2 | import { notFound } from "next/navigation"; | 11 | import { notFound } from "next/navigation"; | ||
| 3 | import { prisma } from "@airiskindex/db"; | 12 | import { prisma } from "@airiskindex/db"; | ||
modified
apps/web/app/occupations/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/occupations/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Browse page: all occupations grouped by SOC major group with score chips. | ||||
| 9 | + | ||||
| 1 | import Link from "next/link"; | 10 | import Link from "next/link"; | ||
| 2 | import { prisma } from "@airiskindex/db"; | 11 | import { prisma } from "@airiskindex/db"; | ||
| 3 | import { SOC_MAJOR_GROUPS } from "@/lib/soc-groups"; | 12 | import { SOC_MAJOR_GROUPS } from "@/lib/soc-groups"; | ||
modified
apps/web/app/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Home page: hero, live search, ranking (most/least exposed), group averages. | ||||
| 9 | + | ||||
| 1 | import Link from "next/link"; | 10 | import Link from "next/link"; | ||
| 2 | import { prisma } from "@airiskindex/db"; | 11 | import { prisma } from "@airiskindex/db"; | ||
| 3 | import { OccupationSearch } from "@/components/occupation-search"; | 12 | import { OccupationSearch } from "@/components/occupation-search"; | ||
modified
apps/web/app/privacy/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/privacy/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Privacy Policy. | ||||
| 9 | + | ||||
| 1 | export const metadata = { | 10 | export const metadata = { | ||
| 2 | title: "Privacy Policy — AI Risk Index", | 11 | title: "Privacy Policy — AI Risk Index", | ||
| 3 | }; | 12 | }; | ||
modified
apps/web/app/terms/page.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: page.tsx | ||||
| 2 | +// Path: apps/web/app/terms/page.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Terms of Service. | ||||
| 9 | + | ||||
| 1 | export const metadata = { | 10 | export const metadata = { | ||
| 2 | title: "Terms of Service — AI Risk Index", | 11 | title: "Terms of Service — AI Risk Index", | ||
| 3 | }; | 12 | }; | ||
modified
apps/web/components/mobile-menu.tsx
+10 −0
@@ -1,5 +1,15 @@ | |||||
| 1 | "use client"; | 1 | "use client"; | ||
| 2 | 2 | ||||
| 3 | +// File: mobile-menu.tsx | ||||
| 4 | +// Path: apps/web/components/mobile-menu.tsx | ||||
| 5 | +// Project: AI Risk Index — airiskindex.io | ||||
| 6 | +// Author: Simon-Pierre Boucher | ||||
| 7 | +// Contact: contact@spboucher.ai | ||||
| 8 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 9 | +// | ||||
| 10 | +// Description: Mobile right-side drawer menu (portal, scroll lock, Escape/overlay close). | ||||
| 11 | + | ||||
| 12 | + | ||||
| 3 | import Link from "next/link"; | 13 | import Link from "next/link"; | ||
| 4 | import { useEffect, useState } from "react"; | 14 | import { useEffect, useState } from "react"; | ||
| 5 | import { createPortal } from "react-dom"; | 15 | import { createPortal } from "react-dom"; | ||
modified
apps/web/components/occupation-search.tsx
+10 −0
@@ -1,5 +1,15 @@ | |||||
| 1 | "use client"; | 1 | "use client"; | ||
| 2 | 2 | ||||
| 3 | +// File: occupation-search.tsx | ||||
| 4 | +// Path: apps/web/components/occupation-search.tsx | ||||
| 5 | +// Project: AI Risk Index — airiskindex.io | ||||
| 6 | +// Author: Simon-Pierre Boucher | ||||
| 7 | +// Contact: contact@spboucher.ai | ||||
| 8 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 9 | +// | ||||
| 10 | +// Description: Debounced live occupation search box (client component). | ||||
| 11 | + | ||||
| 12 | + | ||||
| 3 | import Link from "next/link"; | 13 | import Link from "next/link"; | ||
| 4 | import { useEffect, useRef, useState } from "react"; | 14 | import { useEffect, useRef, useState } from "react"; | ||
| 5 | 15 | ||||
modified
apps/web/components/score-marks.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: score-marks.tsx | ||||
| 2 | +// Path: apps/web/components/score-marks.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Chart marks: score bars with CI whiskers, stat tiles, interval strips, meter. | ||||
| 9 | + | ||||
| 1 | /** | 10 | /** | ||
| 2 | * Chart marks for 0–100 scores with confidence bounds. | 11 | * Chart marks for 0–100 scores with confidence bounds. | ||
| 3 | * Specs per the dataviz skill: thin bars (≤24px) with a 4px rounded data-end | 12 | * Specs per the dataviz skill: thin bars (≤24px) with a 4px rounded data-end | ||
modified
apps/web/lib/soc-groups.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: soc-groups.ts | ||||
| 2 | +// Path: apps/web/lib/soc-groups.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: SOC 2018 major-group names and wage formatting helpers. | ||||
| 9 | + | ||||
| 1 | /** SOC 2018 major groups — first two digits of the O*NET-SOC code. */ | 10 | /** SOC 2018 major groups — first two digits of the O*NET-SOC code. */ | ||
| 2 | export const SOC_MAJOR_GROUPS: Record<string, string> = { | 11 | export const SOC_MAJOR_GROUPS: Record<string, string> = { | ||
| 3 | "11": "Management", | 12 | "11": "Management", | ||
modified
apps/web/next.config.mjs
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: next.config.mjs | ||||
| 2 | +// Path: apps/web/next.config.mjs | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Next.js configuration: workspace package transpilation, standalone output. | ||||
| 9 | + | ||||
| 1 | /** @type {import('next').NextConfig} */ | 10 | /** @type {import('next').NextConfig} */ | ||
| 2 | const nextConfig = { | 11 | const nextConfig = { | ||
| 3 | // Workspace packages ship TypeScript sources directly. | 12 | // Workspace packages ship TypeScript sources directly. | ||
modified
apps/web/postcss.config.mjs
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: postcss.config.mjs | ||||
| 2 | +// Path: apps/web/postcss.config.mjs | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: PostCSS configuration (Tailwind + autoprefixer). | ||||
| 9 | + | ||||
| 1 | export default { | 10 | export default { | ||
| 2 | plugins: { | 11 | plugins: { | ||
| 3 | tailwindcss: {}, | 12 | tailwindcss: {}, | ||
modified
apps/web/tailwind.config.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: tailwind.config.ts | ||||
| 2 | +// Path: apps/web/tailwind.config.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Tailwind configuration (content scan covers app/, components/, lib/, shared ui). | ||||
| 9 | + | ||||
| 1 | import type { Config } from "tailwindcss"; | 10 | import type { Config } from "tailwindcss"; | ||
| 2 | 11 | ||||
| 3 | export default { | 12 | export default { | ||
modified
apps/worker/src/config.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: config.ts | ||||
| 2 | +// Path: apps/worker/src/config.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Worker configuration: rater model panel, prompt version, Redis URL. | ||||
| 9 | + | ||||
| 1 | /** | 10 | /** | ||
| 2 | * Rater model panel — comma-separated model IDs from the environment, never | 11 | * Rater model panel — comma-separated model IDs from the environment, never | ||
| 3 | * hardcoded (CLAUDE.md §6). Multi-model rating is required: single-model | 12 | * hardcoded (CLAUDE.md §6). Multi-model rating is required: single-model | ||
modified
apps/worker/src/index.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: index.ts | ||||
| 2 | +// Path: apps/worker/src/index.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: BullMQ worker: rating batch submit/poll/ingest jobs. | ||||
| 9 | + | ||||
| 1 | import { Queue, Worker } from "bullmq"; | 10 | import { Queue, Worker } from "bullmq"; | ||
| 2 | import IORedis from "ioredis"; | 11 | import IORedis from "ioredis"; | ||
| 3 | import { prisma } from "@airiskindex/db"; | 12 | import { prisma } from "@airiskindex/db"; | ||
modified
apps/worker/src/raters/batch.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: batch.ts | ||||
| 2 | +// Path: apps/worker/src/raters/batch.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Anthropic Message Batches integration: submit, poll, ingest with audit trail. | ||||
| 9 | + | ||||
| 1 | import { readFileSync } from "node:fs"; | 10 | import { readFileSync } from "node:fs"; | ||
| 2 | import Anthropic from "@anthropic-ai/sdk"; | 11 | import Anthropic from "@anthropic-ai/sdk"; | ||
| 3 | import { prisma } from "@airiskindex/db"; | 12 | import { prisma } from "@airiskindex/db"; | ||
modified
apps/worker/src/raters/job-id.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: job-id.ts | ||||
| 2 | +// Path: apps/worker/src/raters/job-id.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Deterministic rating job/custom IDs (idempotent batches). | ||||
| 9 | + | ||||
| 1 | import { createHash } from "node:crypto"; | 10 | import { createHash } from "node:crypto"; | ||
| 2 | 11 | ||||
| 3 | /** | 12 | /** | ||
modified
apps/worker/src/raters/schema.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: schema.ts | ||||
| 2 | +// Path: apps/worker/src/raters/schema.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Rating response schemas (zod parse + structured-output JSON schema). | ||||
| 9 | + | ||||
| 1 | import { z } from "zod"; | 10 | import { z } from "zod"; | ||
| 2 | import { DIMENSIONS } from "@airiskindex/scoring"; | 11 | import { DIMENSIONS } from "@airiskindex/scoring"; | ||
| 3 | 12 | ||||
modified
apps/worker/src/scripts/purge-demo.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: purge-demo.ts | ||||
| 2 | +// Path: apps/worker/src/scripts/purge-demo.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Removes the demonstration dataset once real ratings exist. | ||||
| 9 | + | ||||
| 1 | import { prisma } from "@airiskindex/db"; | 10 | import { prisma } from "@airiskindex/db"; | ||
| 2 | 11 | ||||
| 3 | // Removes the demonstration dataset (synthetic tasks "XX-XXXX.00-Tn", demo | 12 | // Removes the demonstration dataset (synthetic tasks "XX-XXXX.00-Tn", demo | ||
modified
apps/worker/src/scripts/rate.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: rate.ts | ||||
| 2 | +// Path: apps/worker/src/scripts/rate.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: One-shot parallel rating run with per-model resume via state file. | ||||
| 9 | + | ||||
| 1 | import { prisma } from "@airiskindex/db"; | 10 | import { prisma } from "@airiskindex/db"; | ||
| 2 | import { RATER_MODELS, RATER_PROMPT_VERSION } from "../config"; | 11 | import { RATER_MODELS, RATER_PROMPT_VERSION } from "../config"; | ||
| 3 | import { | 12 | import { | ||
modified
apps/worker/src/scripts/recompute.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: recompute.ts | ||||
| 2 | +// Path: apps/worker/src/scripts/recompute.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Full index recomputation: panel bands + overrides -> new immutable score run. | ||||
| 9 | + | ||||
| 1 | import { prisma } from "@airiskindex/db"; | 10 | import { prisma } from "@airiskindex/db"; | ||
| 2 | import { | 11 | import { | ||
| 3 | INDEX_VERSION, | 12 | INDEX_VERSION, | ||
modified
eslint.config.mjs
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: eslint.config.mjs | ||||
| 2 | +// Path: eslint.config.mjs | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: ESLint flat configuration for the monorepo. | ||||
| 9 | + | ||||
| 1 | import js from "@eslint/js"; | 10 | import js from "@eslint/js"; | ||
| 2 | import tseslint from "typescript-eslint"; | 11 | import tseslint from "typescript-eslint"; | ||
| 3 | 12 | ||||
modified
infra/deploy.sh
+10 −0
@@ -1,4 +1,14 @@ | |||||
| 1 | #!/usr/bin/env bash | 1 | #!/usr/bin/env bash | ||
| 2 | + | ||||
| 3 | +# File: deploy.sh | ||||
| 4 | +# Path: infra/deploy.sh | ||||
| 5 | +# Project: AI Risk Index — airiskindex.io | ||||
| 6 | +# Author: Simon-Pierre Boucher | ||||
| 7 | +# Contact: contact@spboucher.ai | ||||
| 8 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 9 | +# | ||||
| 10 | +# Description: Deploy script for the m3u96b node. | ||||
| 11 | + | ||||
| 2 | # Deploy to m3u96b (staging/current prod) — CLAUDE.md §7. Run ON the node. | 12 | # Deploy to m3u96b (staging/current prod) — CLAUDE.md §7. Run ON the node. | ||
| 3 | set -euo pipefail | 13 | set -euo pipefail | ||
| 4 | 14 | ||||
modified
infra/run-ngrok.sh
+10 −0
@@ -1,3 +1,13 @@ | |||||
| 1 | #!/bin/sh | 1 | #!/bin/sh | ||
| 2 | + | ||||
| 3 | +# File: run-ngrok.sh | ||||
| 4 | +# Path: infra/run-ngrok.sh | ||||
| 5 | +# Project: AI Risk Index — airiskindex.io | ||||
| 6 | +# Author: Simon-Pierre Boucher | ||||
| 7 | +# Contact: contact@spboucher.ai | ||||
| 8 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 9 | +# | ||||
| 10 | +# Description: PM2 entry: ngrok tunnel to www.airiskindex.io. | ||||
| 11 | + | ||||
| 2 | # PM2 entry for the airiskindex ngrok tunnel on m3u96b (CLAUDE.md §7). | 12 | # PM2 entry for the airiskindex ngrok tunnel on m3u96b (CLAUDE.md §7). | ||
| 3 | exec /opt/homebrew/bin/ngrok http 3000 --url=https://www.airiskindex.io --log=stdout | 13 | exec /opt/homebrew/bin/ngrok http 3000 --url=https://www.airiskindex.io --log=stdout | ||
modified
infra/run-web.sh
+10 −0
@@ -1,4 +1,14 @@ | |||||
| 1 | #!/bin/sh | 1 | #!/bin/sh | ||
| 2 | + | ||||
| 3 | +# File: run-web.sh | ||||
| 4 | +# Path: infra/run-web.sh | ||||
| 5 | +# Project: AI Risk Index — airiskindex.io | ||||
| 6 | +# Author: Simon-Pierre Boucher | ||||
| 7 | +# Contact: contact@spboucher.ai | ||||
| 8 | +# Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 9 | +# | ||||
| 10 | +# Description: PM2 entry: Next.js web server on port 3000. | ||||
| 11 | + | ||||
| 2 | # PM2 entry for airiskindex-web on m3u96b (CLAUDE.md §7). | 12 | # PM2 entry for airiskindex-web on m3u96b (CLAUDE.md §7). | ||
| 3 | cd "$(dirname "$0")/../apps/web" | 13 | cd "$(dirname "$0")/../apps/web" | ||
| 4 | exec ./node_modules/.bin/next start -p 3000 | 14 | exec ./node_modules/.bin/next start -p 3000 | ||
modified
packages/db/prisma/schema.prisma
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: schema.prisma | ||||
| 2 | +// Path: packages/db/prisma/schema.prisma | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Database schema: occupations, tasks, rating audit trail, immutable score runs. | ||||
| 9 | + | ||||
| 1 | // AI Risk Index — database schema. | 10 | // AI Risk Index — database schema. | ||
| 2 | // Methodology integrity (CLAUDE.md §9): every published score traces to a | 11 | // Methodology integrity (CLAUDE.md §9): every published score traces to a | ||
| 3 | // ScoreRun; runs are immutable — recomputations create new runs. | 12 | // ScoreRun; runs are immutable — recomputations create new runs. | ||
modified
packages/db/prisma/seed.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: seed.ts | ||||
| 2 | +// Path: packages/db/prisma/seed.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Demo dataset seed: 10 occupations with synthetic two-model panel ratings. | ||||
| 9 | + | ||||
| 1 | import { PrismaClient } from "@prisma/client"; | 10 | import { PrismaClient } from "@prisma/client"; | ||
| 2 | 11 | ||||
| 3 | // Demo seed: 10 real O*NET-SOC occupations with plausible hand-authored task | 12 | // Demo seed: 10 real O*NET-SOC occupations with plausible hand-authored task | ||
modified
packages/db/src/index.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: index.ts | ||||
| 2 | +// Path: packages/db/src/index.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Prisma client singleton shared across apps. | ||||
| 9 | + | ||||
| 1 | import { PrismaClient } from "@prisma/client"; | 10 | import { PrismaClient } from "@prisma/client"; | ||
| 2 | 11 | ||||
| 3 | // Singleton to avoid exhausting connections under Next.js dev hot-reload. | 12 | // Singleton to avoid exhausting connections under Next.js dev hot-reload. | ||
modified
packages/scoring/src/composite.test.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: composite.test.ts | ||||
| 2 | +// Path: packages/scoring/src/composite.test.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Snapshot tests against the published methodology worked example. | ||||
| 9 | + | ||||
| 1 | import { readFileSync } from "node:fs"; | 10 | import { readFileSync } from "node:fs"; | ||
| 2 | import { describe, expect, it } from "vitest"; | 11 | import { describe, expect, it } from "vitest"; | ||
| 3 | import { HIGH_EXPOSURE_THRESHOLD, scoreOccupation } from "./index"; | 12 | import { HIGH_EXPOSURE_THRESHOLD, scoreOccupation } from "./index"; | ||
modified
packages/scoring/src/composite.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: composite.ts | ||||
| 2 | +// Path: packages/scoring/src/composite.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Occupation-level aggregation: importance-weighted means and highly-exposed task share. | ||||
| 9 | + | ||||
| 1 | import { scoreTask } from "./task"; | 10 | import { scoreTask } from "./task"; | ||
| 2 | import type { OccupationScores, ScoreBand, TaskInput, TaskScores } from "./types"; | 11 | import type { OccupationScores, ScoreBand, TaskInput, TaskScores } from "./types"; | ||
| 3 | import { INDEX_VERSION } from "./version"; | 12 | import { INDEX_VERSION } from "./version"; | ||
modified
packages/scoring/src/index.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: index.ts | ||||
| 2 | +// Path: packages/scoring/src/index.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public API of the pure, deterministic scoring engine. | ||||
| 9 | + | ||||
| 1 | export { HIGH_EXPOSURE_THRESHOLD, scoreOccupation } from "./composite"; | 10 | export { HIGH_EXPOSURE_THRESHOLD, scoreOccupation } from "./composite"; | ||
| 2 | export { pressure, scoreTask } from "./task"; | 11 | export { pressure, scoreTask } from "./task"; | ||
| 3 | export type { | 12 | export type { | ||
modified
packages/scoring/src/properties.test.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: properties.test.ts | ||||
| 2 | +// Path: packages/scoring/src/properties.test.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Property-based tests (fast-check): bounds, monotonicity, determinism, invariances. | ||||
| 9 | + | ||||
| 1 | import fc from "fast-check"; | 10 | import fc from "fast-check"; | ||
| 2 | import { describe, expect, it } from "vitest"; | 11 | import { describe, expect, it } from "vitest"; | ||
| 3 | import type { RatingBand, TaskInput, TaskRatings } from "./index"; | 12 | import type { RatingBand, TaskInput, TaskRatings } from "./index"; | ||
modified
packages/scoring/src/task.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: task.ts | ||||
| 2 | +// Path: packages/scoring/src/task.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Task-level scoring: rating normalization, orientation, weighted score bands. | ||||
| 9 | + | ||||
| 1 | import type { RatingBand, ScoreBand, TaskInput, TaskScores } from "./types"; | 10 | import type { RatingBand, ScoreBand, TaskInput, TaskScores } from "./types"; | ||
| 2 | import { | 11 | import { | ||
| 3 | DIMENSIONS, | 12 | DIMENSIONS, | ||
modified
packages/scoring/src/types.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: types.ts | ||||
| 2 | +// Path: packages/scoring/src/types.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Typed inputs/outputs of the scoring engine: rating bands, score bands, task/occupation scores. | ||||
| 9 | + | ||||
| 1 | import type { DimensionKey } from "./weights"; | 10 | import type { DimensionKey } from "./weights"; | ||
| 2 | 11 | ||||
| 3 | /** | 12 | /** | ||
modified
packages/scoring/src/version.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: version.ts | ||||
| 2 | +// Path: packages/scoring/src/version.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Index semver version constant (bump on any methodology change). | ||||
| 9 | + | ||||
| 1 | /** | 10 | /** | ||
| 2 | * Index version (semver). Bump on any change to weights, formulas, or rater | 11 | * Index version (semver). Bump on any change to weights, formulas, or rater | ||
| 3 | * prompts, with a docs/methodology/CHANGELOG.md entry — METHODOLOGY.md §7. | 12 | * prompts, with a docs/methodology/CHANGELOG.md entry — METHODOLOGY.md §7. | ||
modified
packages/scoring/src/weights.ts
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: weights.ts | ||||
| 2 | +// Path: packages/scoring/src/weights.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Composite dimension weights and orientation — single source of truth for the methodology. | ||||
| 9 | + | ||||
| 1 | /** | 10 | /** | ||
| 2 | * Composite dimension weights — the single source of truth (CLAUDE.md §1: | 11 | * Composite dimension weights — the single source of truth (CLAUDE.md §1: | ||
| 3 | * never hardcode weights anywhere else). METHODOLOGY.md §4. | 12 | * never hardcode weights anywhere else). METHODOLOGY.md §4. | ||
modified
packages/ui/src/index.ts
+9 −0
@@ -1 +1,10 @@ | |||||
| 1 | +// File: index.ts | ||||
| 2 | +// Path: packages/ui/src/index.ts | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Public exports of the shared UI package. | ||||
| 9 | + | ||||
| 1 | export { ScoreBandPill, type ScoreBandProps } from "./score-band"; | 10 | export { ScoreBandPill, type ScoreBandProps } from "./score-band"; | ||
modified
packages/ui/src/score-band.tsx
+9 −0
@@ -1,3 +1,12 @@ | |||||
| 1 | +// File: score-band.tsx | ||||
| 2 | +// Path: packages/ui/src/score-band.tsx | ||||
| 3 | +// Project: AI Risk Index — airiskindex.io | ||||
| 4 | +// Author: Simon-Pierre Boucher | ||||
| 5 | +// Contact: contact@spboucher.ai | ||||
| 6 | +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved. | ||||
| 7 | +// | ||||
| 8 | +// Description: Shared score-band pill component (score with confidence interval). | ||||
| 9 | + | ||||
| 1 | export interface ScoreBandProps { | 10 | export interface ScoreBandProps { | ||
| 2 | label: string; | 11 | label: string; | ||
| 3 | low: number; | 12 | low: number; | ||
| 4 | 13 | ||||