chore: add file headers (author, contact, copyright, description) to all source files
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 50 changed files with +457 and −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 | 10 | """AI Risk Index ETL: raw source dumps -> derived artifacts -> Postgres. |
| 2 | 11 | |
| 3 | 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 | 10 | """Fetch BLS OEWS national wage data (May 2025) into data/raw/oews/. |
| 2 | 11 | |
| 3 | 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 | 10 | """Fetch the O*NET database text dump into data/raw/onet/ (immutable). |
| 2 | 11 | |
| 3 | 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 | 10 | """Load derived O*NET + OEWS CSVs into Postgres (idempotent upserts). |
| 2 | 11 | |
| 3 | 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 | 10 | """Transform raw O*NET + OEWS dumps into derived CSVs with a manifest. |
| 2 | 11 | |
| 3 | 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 | 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 | 10 | import { INDEX_VERSION } from "@airiskindex/scoring"; |
| 2 | 11 | |
| 3 | 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 | 10 | import { |
| 2 | 11 | DIMENSIONS, |
| 3 | 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 | 10 | import { prisma } from "@airiskindex/db"; |
| 2 | 11 | import { INDEX_VERSION } from "@airiskindex/scoring"; |
| 3 | 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 | 10 | import { prisma } from "@airiskindex/db"; |
| 2 | 11 | import { INDEX_VERSION } from "@airiskindex/scoring"; |
| 3 | 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 | 12 | @tailwind base; |
| 2 | 13 | @tailwind components; |
| 3 | 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 | 10 | import type { Metadata, Viewport } from "next"; |
| 2 | 11 | import Link from "next/link"; |
| 3 | 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 | 10 | import Link from "next/link"; |
| 2 | 11 | import { |
| 3 | 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 | 10 | import Link from "next/link"; |
| 2 | 11 | import { notFound } from "next/navigation"; |
| 3 | 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 | 10 | import Link from "next/link"; |
| 2 | 11 | import { prisma } from "@airiskindex/db"; |
| 3 | 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 | 10 | import Link from "next/link"; |
| 2 | 11 | import { prisma } from "@airiskindex/db"; |
| 3 | 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 | 10 | export const metadata = { |
| 2 | 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 | 10 | export const metadata = { |
| 2 | 11 | title: "Terms of Service — AI Risk Index", |
| 3 | 12 | }; |
modified
apps/web/components/mobile-menu.tsx
+10 −0
@@ -1,5 +1,15 @@ | ||
| 1 | 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 | 13 | import Link from "next/link"; |
| 4 | 14 | import { useEffect, useState } from "react"; |
| 5 | 15 | import { createPortal } from "react-dom"; |
modified
apps/web/components/occupation-search.tsx
+10 −0
@@ -1,5 +1,15 @@ | ||
| 1 | 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 | 13 | import Link from "next/link"; |
| 4 | 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 | 11 | * Chart marks for 0–100 scores with confidence bounds. |
| 3 | 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 | 10 | /** SOC 2018 major groups — first two digits of the O*NET-SOC code. */ |
| 2 | 11 | export const SOC_MAJOR_GROUPS: Record<string, string> = { |
| 3 | 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 | 10 | /** @type {import('next').NextConfig} */ |
| 2 | 11 | const nextConfig = { |
| 3 | 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 | 10 | export default { |
| 2 | 11 | plugins: { |
| 3 | 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 | 10 | import type { Config } from "tailwindcss"; |
| 2 | 11 | |
| 3 | 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 | 11 | * Rater model panel — comma-separated model IDs from the environment, never |
| 3 | 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 | 10 | import { Queue, Worker } from "bullmq"; |
| 2 | 11 | import IORedis from "ioredis"; |
| 3 | 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 | 10 | import { readFileSync } from "node:fs"; |
| 2 | 11 | import Anthropic from "@anthropic-ai/sdk"; |
| 3 | 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 | 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 | 10 | import { z } from "zod"; |
| 2 | 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 | 10 | import { prisma } from "@airiskindex/db"; |
| 2 | 11 | |
| 3 | 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 | 10 | import { prisma } from "@airiskindex/db"; |
| 2 | 11 | import { RATER_MODELS, RATER_PROMPT_VERSION } from "../config"; |
| 3 | 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 | 10 | import { prisma } from "@airiskindex/db"; |
| 2 | 11 | import { |
| 3 | 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 | 10 | import js from "@eslint/js"; |
| 2 | 11 | import tseslint from "typescript-eslint"; |
| 3 | 12 | |
modified
infra/deploy.sh
+10 −0
@@ -1,4 +1,14 @@ | ||
| 1 | 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 | 12 | # Deploy to m3u96b (staging/current prod) — CLAUDE.md §7. Run ON the node. |
| 3 | 13 | set -euo pipefail |
| 4 | 14 | |
modified
infra/run-ngrok.sh
+10 −0
@@ -1,3 +1,13 @@ | ||
| 1 | 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 | 12 | # PM2 entry for the airiskindex ngrok tunnel on m3u96b (CLAUDE.md §7). |
| 3 | 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 | 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 | 12 | # PM2 entry for airiskindex-web on m3u96b (CLAUDE.md §7). |
| 3 | 13 | cd "$(dirname "$0")/../apps/web" |
| 4 | 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 | 10 | // AI Risk Index — database schema. |
| 2 | 11 | // Methodology integrity (CLAUDE.md §9): every published score traces to a |
| 3 | 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 | 10 | import { PrismaClient } from "@prisma/client"; |
| 2 | 11 | |
| 3 | 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 | 10 | import { PrismaClient } from "@prisma/client"; |
| 2 | 11 | |
| 3 | 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 | 10 | import { readFileSync } from "node:fs"; |
| 2 | 11 | import { describe, expect, it } from "vitest"; |
| 3 | 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 | 10 | import { scoreTask } from "./task"; |
| 2 | 11 | import type { OccupationScores, ScoreBand, TaskInput, TaskScores } from "./types"; |
| 3 | 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 | 10 | export { HIGH_EXPOSURE_THRESHOLD, scoreOccupation } from "./composite"; |
| 2 | 11 | export { pressure, scoreTask } from "./task"; |
| 3 | 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 | 10 | import fc from "fast-check"; |
| 2 | 11 | import { describe, expect, it } from "vitest"; |
| 3 | 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 | 10 | import type { RatingBand, ScoreBand, TaskInput, TaskScores } from "./types"; |
| 2 | 11 | import { |
| 3 | 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 | 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 | 11 | * Index version (semver). Bump on any change to weights, formulas, or rater |
| 3 | 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 | 11 | * Composite dimension weights — the single source of truth (CLAUDE.md §1: |
| 3 | 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 | 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 | 10 | export interface ScoreBandProps { |
| 2 | 11 | label: string; |
| 3 | 12 | low: number; |
| 4 | 13 | |