SPB Git

spb/airiskindex

Public

The most methodologically rigorous, fully transparent AI job-exposure index.

chore: add file headers (author, contact, copyright, description) to all source files

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed (Aug 5, 2026) parent c7a1562 Browse files

50 changed files +457 −0

50 changed files
Unified Split
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
Menu

Theme