Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/admin/registry/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";

// Lifecycle taxonomy from ADR 0001 — see lib/portfolio.ts InterventionStatus.
// Lifecycle taxonomy from ADR 0001 — see lib/portfolio.ts ProjectStatus.
const STATUS_OPTIONS = [
"idea", "approved", "building", "prototype", "piloting",
"production", "maintained", "sunsetting", "archived", "tracked",
Expand Down
12 changes: 6 additions & 6 deletions app/portfolio/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
import {
PUBLIC_STAGE_ORDER,
STAGE_OPERATIONAL_ROLLUP,
isInterventionStatus,
isProjectStatus,
publicStageFromStatus,
} from "@/lib/lifecycle-display";
import type { InterventionStatus, PublicStage } from "@/lib/portfolio";
import type { ProjectStatus, PublicStage } from "@/lib/portfolio";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -82,8 +82,8 @@ export default async function PortfolioPage({
? (params.stage!.trim() as PublicStage)
: null;
const rawStatus = params.status?.trim();
const selectedStatus: InterventionStatus | null =
rawStatus && isInterventionStatus(rawStatus) ? rawStatus : null;
const selectedStatus: ProjectStatus | null =
rawStatus && isProjectStatus(rawStatus) ? rawStatus : null;
const selectedCategory: WorkCategory | null = isWorkCategory(
params.category?.trim()
)
Expand All @@ -98,15 +98,15 @@ export default async function PortfolioPage({
// available to filter by even after they've applied something.
const homeUnitCounts = new Map<string, number>();
const stageCounts = new Map<PublicStage, number>();
const operationalCounts = new Map<InterventionStatus, number>();
const operationalCounts = new Map<ProjectStatus, number>();
const categoryCounts = new Map<WorkCategory, number>();
for (const app of allApps) {
for (const unit of app.homeUnits) {
homeUnitCounts.set(unit, (homeUnitCounts.get(unit) ?? 0) + 1);
}
const stage = publicStageFromStatus(app.status);
stageCounts.set(stage, (stageCounts.get(stage) ?? 0) + 1);
if (isInterventionStatus(app.status)) {
if (isProjectStatus(app.status)) {
operationalCounts.set(
app.status,
(operationalCounts.get(app.status) ?? 0) + 1
Expand Down
4 changes: 2 additions & 2 deletions components/PortfolioCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
OPERATIONAL_LABEL,
PUBLIC_STAGE_CHIP,
PUBLIC_STAGE_LABEL,
isInterventionStatus,
isProjectStatus,
publicStageFromStatus,
} from "@/lib/lifecycle-display";

Expand Down Expand Up @@ -85,7 +85,7 @@ export default function PortfolioCard({
// doesn't apply to externally-owned interventions, so the primary
// stage chip carries the whole signal. (See ADR 0001.)
const showOperationalChip =
isInterventionStatus(app.status) && app.status !== "tracked";
isProjectStatus(app.status) && app.status !== "tracked";

return (
<article className="group relative flex h-full flex-col rounded-xl border border-hairline bg-white p-5 shadow-sm transition-shadow hover:shadow-md">
Expand Down
6 changes: 3 additions & 3 deletions components/PortfolioFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
STAGE_OPERATIONAL_ROLLUP,
publicStageFromStatus,
} from "@/lib/lifecycle-display";
import type { InterventionStatus, PublicStage } from "@/lib/portfolio";
import type { ProjectStatus, PublicStage } from "@/lib/portfolio";

// Pure URL-state filter chip group. The portfolio page builds the option
// lists from the unfiltered data and passes them in; clicking a pill
Expand All @@ -27,7 +27,7 @@ interface StageFilterOption {
}

interface OperationalFilterOption {
status: InterventionStatus;
status: ProjectStatus;
count: number;
}

Expand All @@ -42,7 +42,7 @@ export interface PortfolioFiltersProps {
selected: {
unit: string | null;
stage: PublicStage | null;
status: InterventionStatus | null;
status: ProjectStatus | null;
category: string | null;
blockers: boolean;
sort: "default" | "name" | "blockers";
Expand Down
2 changes: 1 addition & 1 deletion lib/governance/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export interface VocabularyValue {
displayOrder?: number;
description?: string;
// Per-value verification rule (ADR 0001, iids-portfolio domain).
// Currently populated only for InterventionStatus and PublicStage;
// Currently populated only for ProjectStatus and PublicStage;
// other domains/groups leave it unset. The catalog records what the
// rule *is* — implementation lives in lib/portfolio-verification.ts.
verificationRule?: string;
Expand Down
32 changes: 16 additions & 16 deletions lib/governance/vocabularies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,8 +565,8 @@ export const vocabularyGroups: VocabularyGroup[] = [
{
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "InterventionStatus",
"description": "Operational ladder for an intervention — the day-to-day status IIDS tracks. Source of truth: lib/portfolio.ts. Each value's Verification_Rule is enforced by lib/portfolio-verification.ts on every PR.",
"group": "ProjectStatus",
"description": "Operational ladder for a project — the day-to-day status IIDS tracks. Source of truth: lib/portfolio.ts. Each value's Verification_Rule is enforced by lib/portfolio-verification.ts on every PR.",
"values": [
{
"code": "idea",
Expand Down Expand Up @@ -622,7 +622,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"label": "Sunsetting",
"displayOrder": 8,
"description": "Being wound down with a planned successor.",
"verificationRule": "sunsetDate (ISO) set; replacedBy populated — successor intervention slug or the literal 'manual-process'."
"verificationRule": "sunsetDate (ISO) set; replacedBy populated — successor project slug or the literal 'manual-process'."
},
{
"code": "archived",
Expand All @@ -635,7 +635,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"code": "tracked",
"label": "Tracked",
"displayOrder": 10,
"description": "Externally-owned intervention IIDS observes but does not build.",
"description": "Externally-owned project IIDS observes but does not build.",
"verificationRule": "trackingOnly:true; bypasses the operational ladder."
}
]
Expand All @@ -644,56 +644,56 @@ export const vocabularyGroups: VocabularyGroup[] = [
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "PublicStage",
"description": "Stakeholder-facing rollup. Computed deterministically from InterventionStatus by lib/portfolio.ts:computePublicStage. The public surfaces (/portfolio cards primary chip, landing stat strip, /explore tile breakdowns) render this axis; operational status is only shown as a secondary detail on cards.",
"description": "Stakeholder-facing rollup. Computed deterministically from ProjectStatus by lib/portfolio.ts:computePublicStage. The public surfaces (/portfolio cards primary chip, landing stat strip, /explore tile breakdowns) render this axis; operational status is only shown as a secondary detail on cards.",
"values": [
{
"code": "exploring",
"label": "Exploring",
"displayOrder": 1,
"description": "Thinking about it / committed to build.",
"verificationRule": "Rolls up from InterventionStatus values: idea, approved."
"verificationRule": "Rolls up from ProjectStatus values: idea, approved."
},
{
"code": "building",
"label": "Building",
"displayOrder": 2,
"description": "Code exists; not yet for real users.",
"verificationRule": "Rolls up from InterventionStatus values: building, prototype."
"verificationRule": "Rolls up from ProjectStatus values: building, prototype."
},
{
"code": "live",
"label": "Live",
"displayOrder": 3,
"description": "In use today.",
"verificationRule": "Rolls up from InterventionStatus values: piloting, production, maintained."
"verificationRule": "Rolls up from ProjectStatus values: piloting, production, maintained."
},
{
"code": "retired",
"label": "Retired",
"displayOrder": 4,
"description": "Done or winding down.",
"verificationRule": "Rolls up from InterventionStatus values: sunsetting, archived."
"verificationRule": "Rolls up from ProjectStatus values: sunsetting, archived."
},
{
"code": "tracked",
"label": "Tracked",
"displayOrder": 5,
"description": "Not built by IIDS.",
"verificationRule": "Rolls up from InterventionStatus value: tracked. Bypasses the operational ladder."
"verificationRule": "Rolls up from ProjectStatus value: tracked. Bypasses the operational ladder."
}
]
},
{
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "ProductionScope",
"description": "Granularity of production reach. Required on InterventionStatus values production and maintained.",
"description": "Granularity of production reach. Required on ProjectStatus values production and maintained.",
"values": [
{
"code": "home-unit",
"label": "Home Unit",
"displayOrder": 1,
"description": "Accessible to all users in the intervention's home unit."
"description": "Accessible to all users in the project's home unit."
},
{
"code": "institution-wide",
Expand All @@ -713,7 +713,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "Visibility",
"description": "Public-site disclosure level for an intervention's record.",
"description": "Public-site disclosure level for a project's record.",
"values": [
{
"code": "Public",
Expand All @@ -739,7 +739,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "AI4RARelationship",
"description": "How an intervention relates to the AI4RA partnership (UI + Southern Utah University NSF GRANTED).",
"description": "How a project relates to the AI4RA partnership (UI + Southern Utah University NSF GRANTED).",
"values": [
{
"code": "Core",
Expand Down Expand Up @@ -777,7 +777,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"domain": "iids-portfolio",
"application": "IIDS Portfolio",
"group": "WorkCategory",
"description": "By-problem axis for browsing the portfolio. Audience-facing labels written in a Dean's vocabulary (not technical jargon). Source of truth: lib/work-categories.ts. One intervention can sit in 2-3 categories.",
"description": "By-problem axis for browsing the portfolio. Audience-facing labels written in a Dean's vocabulary (not technical jargon). Source of truth: lib/work-categories.ts. One project can sit in 2-3 categories.",
"values": [
{
"code": "documents",
Expand Down Expand Up @@ -825,7 +825,7 @@ export const vocabularyGroups: VocabularyGroup[] = [
"code": "ai-infrastructure",
"label": "AI infrastructure",
"displayOrder": 8,
"description": "LLM gateways, GPU stacks, agent platforms — the plumbing other interventions run on, not a problem on its own."
"description": "LLM gateways, GPU stacks, agent platforms — the plumbing other projects run on, not a problem on its own."
}
]
},
Expand Down
12 changes: 6 additions & 6 deletions lib/lifecycle-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import {
computePublicStage,
type InterventionStatus,
type ProjectStatus,
type PublicStage,
} from "./portfolio";

Expand Down Expand Up @@ -47,7 +47,7 @@ export const PUBLIC_STAGE_ORDER: PublicStage[] = [
"tracked",
];

export const OPERATIONAL_LABEL: Record<InterventionStatus, string> = {
export const OPERATIONAL_LABEL: Record<ProjectStatus, string> = {
idea: "Idea",
approved: "Approved",
building: "Building",
Expand All @@ -63,7 +63,7 @@ export const OPERATIONAL_LABEL: Record<InterventionStatus, string> = {
// Inverse of computePublicStage — for the filter drill-in.
// Lists the 1-N operational states that roll up into each public stage,
// in approximate ladder order.
export const STAGE_OPERATIONAL_ROLLUP: Record<PublicStage, InterventionStatus[]> = {
export const STAGE_OPERATIONAL_ROLLUP: Record<PublicStage, ProjectStatus[]> = {
exploring: ["idea", "approved"],
building: ["building", "prototype"],
live: ["piloting", "production", "maintained"],
Expand All @@ -76,11 +76,11 @@ export const STAGE_OPERATIONAL_ROLLUP: Record<PublicStage, InterventionStatus[]>
// canonical 10-value union (drift, legacy data, etc.), bucket it as
// `exploring` so the UI never crashes.
export function publicStageFromStatus(status: string): PublicStage {
if (isInterventionStatus(status)) return computePublicStage(status);
if (isProjectStatus(status)) return computePublicStage(status);
return "exploring";
}

const STATUSES: ReadonlyArray<InterventionStatus> = [
const STATUSES: ReadonlyArray<ProjectStatus> = [
"idea",
"approved",
"building",
Expand All @@ -93,7 +93,7 @@ const STATUSES: ReadonlyArray<InterventionStatus> = [
"tracked",
];

export function isInterventionStatus(s: string): s is InterventionStatus {
export function isProjectStatus(s: string): s is ProjectStatus {
return (STATUSES as readonly string[]).includes(s);
}

Expand Down
6 changes: 3 additions & 3 deletions lib/portfolio-verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
// (see ADR — "skip gracefully").
// ============================================================

import type { Intervention, InterventionStatus } from "./portfolio";
import type { Intervention, ProjectStatus } from "./portfolio";
import { portfolioMeta } from "./portfolio-meta";

export interface VerificationProblem {
slug: string;
claimedStatus: InterventionStatus;
claimedStatus: ProjectStatus;
problem: string;
rule: string;
severity: "error" | "warning";
Expand Down Expand Up @@ -311,7 +311,7 @@ const verifyUniversal: Verifier = (i) => {
return problems;
};

const verifiers: Record<InterventionStatus, Verifier> = {
const verifiers: Record<ProjectStatus, Verifier> = {
idea: verifyIdea,
approved: verifyApproved,
building: verifyBuilding,
Expand Down
6 changes: 3 additions & 3 deletions lib/portfolio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type Visibility =
// Operational ladder — see docs/adr/0001-product-lifecycle-taxonomy.md.
// 9 lifecycle states + 1 meta state (`tracked`). Verification rules for
// each are spec'd in the ADR; the verifier itself lands in a follow-up PR.
export type InterventionStatus =
export type ProjectStatus =
| "idea"
| "approved"
| "building"
Expand Down Expand Up @@ -78,7 +78,7 @@ export interface Intervention {
buildParticipants: string[];

// Status
status: InterventionStatus;
status: ProjectStatus;
visibility: Visibility;
institutionalReviewStatus?: InstitutionalReviewStatus;

Expand Down Expand Up @@ -541,7 +541,7 @@ export const interventions: Intervention[] = [
// ============================================================

// Operational status → public stage rollup. See ADR 0001.
export function computePublicStage(status: InterventionStatus): PublicStage {
export function computePublicStage(status: ProjectStatus): PublicStage {
switch (status) {
case "idea":
case "approved":
Expand Down
2 changes: 1 addition & 1 deletion vendor/data-governance
Loading