diff --git a/src/components/prose/components.js b/src/components/prose/components.js
index e8273346..67f85cc4 100644
--- a/src/components/prose/components.js
+++ b/src/components/prose/components.js
@@ -12,6 +12,21 @@ export { default as MaturityModelContent } from '../MaturityModelContent.astro';
export { default as NetworkDirectory } from '../NetworkDirectory.astro';
export { default as OpenSourceShowcase } from '../OpenSourceShowcase.astro';
export { default as PartnerDirectory } from '../PartnerDirectory.astro';
+export { default as ProjectPortal } from '../ProjectPortal.astro';
export { default as PrinciplesExplorer } from '../PrinciplesExplorer.astro';
export { default as TalksGrid } from '../TalksGrid.astro';
export { default as SurveyExplorer } from '../SurveyExplorerIsland.astro';
+export { default as QuickstartTerminal } from '../QuickstartTerminal.astro';
+export { default as ControlPlaneMap } from '../ControlPlaneMap.astro';
+export { default as MemoryTiers } from '../MemoryTiers.astro';
+export { default as RequestPath } from '../RequestPath.astro';
+export { default as MediaBand } from '../MediaBand.astro';
+export { default as KaosProjectFooter } from '../KaosProjectFooter.astro';
+export { default as CodeTabs } from '../CodeTabs.astro';
+export { default as ProjectLinks } from '../ProjectLinks.astro';
+export { default as SequencePipeline } from '../SequencePipeline.astro';
+export { default as StageExplorer } from '../StageExplorer.astro';
+export { default as TalkCard } from '../TalkCard.astro';
+export { default as CategoryAtlas } from '../CategoryAtlas.astro';
+export { default as RegulationGrid } from '../RegulationGrid.astro';
+export { default as AnimationWindow } from '../AnimationWindow.astro';
diff --git a/src/content/oss-catalogues.json b/src/content/oss-catalogues.json
new file mode 100644
index 00000000..88ae3dc2
--- /dev/null
+++ b/src/content/oss-catalogues.json
@@ -0,0 +1,288 @@
+{
+ "productionMl": {
+ "repository": "https://github.com/EthicalML/awesome-production-machine-learning",
+ "source": "https://raw.githubusercontent.com/EthicalML/awesome-production-machine-learning/master/README.md",
+ "branch": "master",
+ "categories": [
+ {
+ "emoji": "🔧",
+ "name": "AutoML",
+ "count": 18,
+ "anchor": "#automl"
+ },
+ {
+ "emoji": "🧮",
+ "name": "Computation & Communication Optimisation",
+ "count": 58,
+ "anchor": "#computation-and-communication-optimisation"
+ },
+ {
+ "emoji": "🏷️",
+ "name": "Data Annotation & Synthesis",
+ "count": 16,
+ "anchor": "#data-annotation-and-synthesis"
+ },
+ {
+ "emoji": "🧵",
+ "name": "Data Pipeline",
+ "count": 25,
+ "anchor": "#data-pipeline"
+ },
+ {
+ "emoji": "📓",
+ "name": "Data Science Notebook",
+ "count": 10,
+ "anchor": "#data-science-notebook"
+ },
+ {
+ "emoji": "💾",
+ "name": "Data Storage Optimisation",
+ "count": 25,
+ "anchor": "#data-storage-optimisation"
+ },
+ {
+ "emoji": "💸",
+ "name": "Data Stream Processing",
+ "count": 11,
+ "anchor": "#data-stream-processing"
+ },
+ {
+ "emoji": "💪",
+ "name": "Deployment & Serving",
+ "count": 60,
+ "anchor": "#deployment-and-serving"
+ },
+ {
+ "emoji": "📈",
+ "name": "Evaluation & Monitoring",
+ "count": 68,
+ "anchor": "#evaluation-and-monitoring"
+ },
+ {
+ "emoji": "🔍",
+ "name": "Explainability & Fairness",
+ "count": 14,
+ "anchor": "#explainability-and-fairness"
+ },
+ {
+ "emoji": "🎁",
+ "name": "Feature Store",
+ "count": 3,
+ "anchor": "#feature-store"
+ },
+ {
+ "emoji": "🔴",
+ "name": "Industry-strength Anomaly Detection",
+ "count": 5,
+ "anchor": "#industry-strength-anomaly-detection"
+ },
+ {
+ "emoji": "👁️",
+ "name": "Industry-strength Computer Vision",
+ "count": 13,
+ "anchor": "#industry-strength-computer-vision"
+ },
+ {
+ "emoji": "🔥",
+ "name": "Industry-strength Information Retrieval",
+ "count": 24,
+ "anchor": "#industry-strength-information-retrieval"
+ },
+ {
+ "emoji": "🔠",
+ "name": "Industry-strength Natural Language Processing",
+ "count": 45,
+ "anchor": "#industry-strength-nlp"
+ },
+ {
+ "emoji": "🙌",
+ "name": "Industry-strength Recommender System",
+ "count": 5,
+ "anchor": "#industry-strength-recommender-system"
+ },
+ {
+ "emoji": "🍕",
+ "name": "Industry-strength Reinforcement Learning",
+ "count": 39,
+ "anchor": "#industry-strength-reinforcement-learning"
+ },
+ {
+ "emoji": "🤖",
+ "name": "Industry-strength Robotics",
+ "count": 7,
+ "anchor": "#industry-strength-robotics"
+ },
+ {
+ "emoji": "📊",
+ "name": "Industry-strength Visualisation",
+ "count": 25,
+ "anchor": "#industry-strength-visualisation"
+ },
+ {
+ "emoji": "📅",
+ "name": "Metadata Management",
+ "count": 6,
+ "anchor": "#metadata-management"
+ },
+ {
+ "emoji": "📜",
+ "name": "Model, Data & Experiment Management",
+ "count": 16,
+ "anchor": "#model-data-and-experiment-management"
+ },
+ {
+ "emoji": "🔩",
+ "name": "Model Storage Optimisation",
+ "count": 10,
+ "anchor": "#model-storage-optimisation"
+ },
+ {
+ "emoji": "🏁",
+ "name": "Model Training & Orchestration",
+ "count": 27,
+ "anchor": "#model-training-and-orchestration"
+ },
+ {
+ "emoji": "🔏",
+ "name": "Privacy & Safety",
+ "count": 15,
+ "anchor": "#privacy-and-safety"
+ }
+ ]
+ },
+ "aiGuidelines": {
+ "repository": "https://github.com/EthicalML/awesome-artificial-intelligence-regulation",
+ "source": "https://raw.githubusercontent.com/EthicalML/awesome-artificial-intelligence-regulation/master/README.md",
+ "branch": "master",
+ "areas": [
+ {
+ "name": "Austria",
+ "emoji": "🇦🇹",
+ "count": 1,
+ "anchor": "#austria"
+ },
+ {
+ "name": "Brazil",
+ "emoji": "🇧🇷",
+ "count": 1,
+ "anchor": "#brazil"
+ },
+ {
+ "name": "Canada",
+ "emoji": "🇨🇦",
+ "count": 1,
+ "anchor": "#canada"
+ },
+ {
+ "name": "China",
+ "emoji": "🇨🇳",
+ "count": 7,
+ "anchor": "#china"
+ },
+ {
+ "name": "Dubai",
+ "emoji": "🇦🇪",
+ "count": 1,
+ "anchor": "#dubai"
+ },
+ {
+ "name": "European Union",
+ "emoji": "🇪🇺",
+ "count": 10,
+ "anchor": "#european-union"
+ },
+ {
+ "name": "India",
+ "emoji": "🇮🇳",
+ "count": 4,
+ "anchor": "#india"
+ },
+ {
+ "name": "Ireland",
+ "emoji": "🇮🇪",
+ "count": 1,
+ "anchor": "#ireland"
+ },
+ {
+ "name": "Israel",
+ "emoji": "🇮🇱",
+ "count": 1,
+ "anchor": "#israel"
+ },
+ {
+ "name": "Mexico",
+ "emoji": "🇲🇽",
+ "count": 1,
+ "anchor": "#mexico"
+ },
+ {
+ "name": "Singapore",
+ "emoji": "🇸🇬",
+ "count": 2,
+ "anchor": "#singapore"
+ },
+ {
+ "name": "Switzerland",
+ "emoji": "🇨🇭",
+ "count": 1,
+ "anchor": "#switzerland"
+ },
+ {
+ "name": "United Arab Emirates",
+ "emoji": "🇦🇪",
+ "count": 1,
+ "anchor": "#united-arab-emirates"
+ },
+ {
+ "name": "United Kingdom",
+ "emoji": "🇬🇧",
+ "count": 3,
+ "anchor": "#united-kingdom"
+ },
+ {
+ "name": "United States of America",
+ "emoji": "🇺🇸",
+ "count": 11,
+ "anchor": "#united-states-of-america"
+ }
+ ],
+ "themes": [
+ {
+ "emoji": "🔍",
+ "name": "High Level Frameworks & Principles",
+ "count": 21,
+ "anchor": "#high-level-frameworks-and-principles"
+ },
+ {
+ "emoji": "📜",
+ "name": "Industry standards initiatives",
+ "count": 5,
+ "anchor": "#industry-standards-initiatives"
+ },
+ {
+ "emoji": "🔨",
+ "name": "Interactive & Practical Tools",
+ "count": 25,
+ "anchor": "#interactive-and-practical-tools"
+ },
+ {
+ "emoji": "📚",
+ "name": "Online Courses",
+ "count": 7,
+ "anchor": "#online-courses-and-learning-resources"
+ },
+ {
+ "emoji": "🔏",
+ "name": "Processes & Checklists",
+ "count": 15,
+ "anchor": "#processes-and-checklists"
+ },
+ {
+ "emoji": "🤖",
+ "name": "Research and Industry Newsletters",
+ "count": 7,
+ "anchor": "#research-and-industry-newsletters"
+ }
+ ]
+ }
+}
diff --git a/src/content/principles/01.md b/src/content/principles/01.md
index 9b71111b..75635135 100644
--- a/src/content/principles/01.md
+++ b/src/content/principles/01.md
@@ -1,8 +1,8 @@
---
number: "01"
-title: Human Augmentation
+title: Human Augmentation by Oversight
description: Irrespective of how many levels of abstractions are introduced through AI systems, the impact is and will always continue to be human.
-commitment: We commit to assess the consequences of incorrect outputs and automated actions and, to design systems with human oversight to ensure aligned and safe outcomes.
+commitment: We commit to assess the consequences of incorrect outputs and automated actions and to design systems with human oversight to ensure aligned and safe outcomes, enabling Human Augmentation by Oversight.
failure_modes:
- Automation of decisions the AI Act treats as high risk or prohibits
- Agents acting beyond their mandate
@@ -18,13 +18,13 @@ related_links:
href: "/frameworks/"
---
-Irrespective of how many levels of abstractions are introduced through AI systems, the impact is and will always continue to be human. AI systems should be developed to augment human cognition and capability as a whole. Human oversight must be enabled, and where reasonable, enabling human-in-the-loop to drive changes to high risk outcomes. This is a requirement now codified in Article 14 of the EU AI Act, which [the institute contributed to through its policy work](/initiatives/).
+Irrespective of how many levels of abstractions are introduced through AI systems, the impact is and will always continue to be human. AI systems should be developed to augment human cognition and capability as a whole. Human oversight must be enabled, and where reasonable, with human-in-the-loop established to drive remediation to predictions in contexts of high or unacceptable risk outcomes. This is a requirement now codified in Article 14 of the EU AI Act, which [the institute contributed to through its policy work](/initiatives/).
The AI Act also draws the automation line in law: Article 5 prohibits some practices outright, such as social scoring and manipulative systems, while the high-risk uses of Annex III, including justice, healthcare and critical infrastructure, may only operate under the human oversight of Article 14. In these domains a single wrong prediction can carry generational impact, so the level of automation must follow the consequence, not the capability.
## Where it fails
-Oversight designed for single predictions does not transfer to modern AI & Agentic systems. An agent can take hundreds of actions in one task, so reviewing each one is impossible and in some contexts reviewing none may be negligent.
+Oversight designed for single ML models does not transfer to modern AI & Agentic systems. An agent can take hundreds of actions in one task, so reviewing each one is impossible; however, in some contexts reviewing none may be negligent.
- Automation that displaces meaningful human judgement.
- Agents that operate outside the mandate their operators intended.
diff --git a/src/content/principles/02.md b/src/content/principles/02.md
index c4b98535..1b055789 100644
--- a/src/content/principles/02.md
+++ b/src/content/principles/02.md
@@ -1,8 +1,8 @@
---
number: "02"
-title: Bias Evaluation
-description: All models have inherent bias; despite this, some can be useful, but some can be harmful. This bias must be identified and where required, calibrated.
-commitment: We commit to continuously develop processes that allow us to understand, document and monitor bias in the models we use and across the systems we build on them.
+title: Fairness by Calibration
+description: All models carry inherent bias; some may be useful, but some can be harmful. This bias must be identified and where relevant, calibrated.
+commitment: We commit to introduce processes proportionate to risk that mitigate unintended discrimination across groups in our production AI systems, enabling Fairness by Calibration.
failure_modes:
- Inherited model bias propagated across the system
- Application data and prompts amplifying skew
@@ -18,6 +18,22 @@ related_links:
href: "/frameworks/"
---
-Bias evaluation should examine who benefits, who carries risk, and where a system's errors concentrate. In systems built on general-purpose models the bias has two layers: 1) what the model inherited from training data that its deployer cannot inspect, and 2) what the application introduces through its own data, prompts, retrieval sources and thresholds. Furthermore, fine-tuning amplifies both layers, as it rewrites the model's behaviour and makes the result the fine-tuner's responsibility.
+Human and model bias is present throughout the end-to-end AI system lifecycle; bias evaluation supports understanding who benefits, who carries risk, and where a system's errors concentrate. In systems built on general-purpose models the bias has two layers: 1) what the model inherited from training data that its deployer cannot inspect, and 2) what the application introduces through its own data, prompts, retrieval sources and thresholds.
-This principle asks who carries the skewed impact of the AI system errors. Teams must combine quantitative tests with domain knowledge and affected-community input, then re-evaluate as data, model versions and deployment conditions change.
+Furthermore, fine-tuning amplifies both layers, as it rewrites the model's behaviour and makes the result the fine-tuner's responsibility. This is why it is important to ensure processes and frameworks are in place, proportionate to the risk involved, to understand the extent and scale of the bias present. This enables mitigation of the group-skewed risks identified throughout the system.
+
+## Where it fails
+
+Bias is ubiquitous in AI systems, however negative impact concentrates where nobody is measuring, and a system built on a general-purpose model inherits skew its team never chose.
+
+- Inherited model bias propagates into every downstream decision the system takes.
+- Application data, prompts, retrieval sources and thresholds amplify skew the base model did not have.
+- Fine-tuning shifts behaviour in ways that go unnoticed without re-evaluation.
+
+## Practical controls
+
+Teams must combine quantitative tests with domain knowledge, and rely on processes rather than tools alone.
+
+- Run disaggregated behavioural evaluations across the groups the system affects.
+- Review provider model documentation for known biases and evaluation gaps.
+- Re-evaluate after fine-tuning, model updates and changes in deployment conditions.
diff --git a/src/content/principles/03.md b/src/content/principles/03.md
index 1f049a13..025a4a01 100644
--- a/src/content/principles/03.md
+++ b/src/content/principles/03.md
@@ -1,8 +1,8 @@
---
number: "03"
title: Explainability by Justification
-description: Frontier models are black boxes, and AI systems that integrate them can be more opaque and undeterministic, or explainable through tooling, process and best practice.
-commitment: We commit to develop tools and processes to enhance the transparency and explainability of AI systems where reasonable.
+description: Frontier models are black boxes by design; however AI systems that integrate them can be explainable through tooling, process and best practice.
+commitment: We commit to develop tools and processes to enhance the transparency and explainability of AI systems where reasonable, enabling Explainability by Justification.
failure_modes:
- Unnecessarily convoluted agentic graphs
- Stated reasoning diverging from actual behaviour
@@ -18,6 +18,22 @@ related_links:
href: "/frameworks/"
---
-Frontier models are black boxes by design. When these are integrated into a larger AI system; these can become either more opaque or more transparent. This requires practitioners to work towards integrating and iteratively extending the infrastructure required to ensure key components have human interpretability and accountability. Explainability should also be proportionate to the risk involved in the system's outputs themselves.
+Frontier models are black boxes by design. When integrated into a larger AI system, they can become either more opaque or more transparent. This requires practitioners to work towards integrating and iteratively extending the infrastructure required to ensure key components have human interpretability and accountability.
-Explainability today is built from interpretability and attribution tooling, grounding outputs in citable sources, and transparency artifacts. Foundational capabilities involve model and system cards that state what a system is, what it was evaluated on and where it should not be used. Any trade-offs that involve explainability vs capability/performance, should be documented and weighed against the domain's need for justification.
+Similarly, explainability does not arise from tooling alone, but also from the processes and the steps carried out by domain experts. The right process should be designed proportionate to the risk involved in the system's outputs themselves.
+
+## Where it fails
+
+Opacity compounds when systems are assembled without explainability in mind, and the explanation a system gives is not automatically the truth of what it did.
+
+- Unnecessarily convoluted agentic graphs that no operator can follow end to end.
+- Stated reasoning that diverges from the actual behaviour of the model.
+- Missing deterministic flows where systematic, repeatable execution is required.
+
+## Practical controls
+
+Explainability today is built from interpretability and attribution tooling, grounding outputs in citable sources, and transparency artifacts.
+
+- Apply interpretability and attribution tooling proportionate to the risk of the output.
+- Publish model and system cards that state what a system is, what it was evaluated on and where it should not be used.
+- Build infrastructure for semantic root cause analysis, and document any explainability vs capability/performance trade-offs against the domain's need for justification.
diff --git a/src/content/principles/04.md b/src/content/principles/04.md
index 5f7d08a0..6694357f 100644
--- a/src/content/principles/04.md
+++ b/src/content/principles/04.md
@@ -1,8 +1,8 @@
---
number: "04"
-title: Reproducibility & Provenance
-description: Storing traces of a system does not ensure provenance. These should not only provide lineage but should be reproducible and auditable in order to be useful.
-commitment: We commit to develop the infrastructure required to enable reproducibility and provenance across the operations of our AI systems.
+title: Provenance by Reproducibility
+description: "Storing traces of a system does not ensure provenance. Lineage is not the goal but the means: operations that can be reproduced are what turn records into provenance, and provenance into auditability."
+commitment: We commit to develop the infrastructure that captures the lineage of our AI systems' operations, so historical steps can be reconstructed and reproduced, enabling Provenance by Reproducibility.
failure_modes:
- Unpinned model versions
- Gaps in data governance throughout system
@@ -18,6 +18,22 @@ related_links:
href: "/data/survey-explorer/"
---
-Diagnosing a production incident requires reproducing the conditions that caused it. A team deploying a model it did not train cannot reproduce the model, but they can and must reproduce their own system. Foundational pillars of AI provenance include pinned model versions, the prompts and configuration in place, the data that flowed through, and the provenance of any fine-tune, including base model, data and adapters. Hosted models are updated and deprecated by their providers, so an unpinned version changes the system underneath its operators and must be explicitly captured.
+Diagnosing a production incident requires reproducing the conditions that caused it. A team deploying a model it did not train cannot reproduce the model, but they can and must be able to reproduce operations on their own system. Foundational pillars of AI provenance include pinned model versions, the prompts and configuration in place, the data that flowed through, and the provenance of any fine-tune, including base model, data and adapters. Hosted models are updated and deprecated by their providers, so an unpinned version changes the system underneath its operators and must be explicitly captured.
-Reproducibility is also what makes auditability possible, not only lineage. For AI systems it is necessary to record not only decisions but also trajectory metadata required to reconstruct what specific steps previously carried out. Retaining these records is now an operational capability that is foundational for production best practices for any AI systems in production.
+Reproducibility is also what makes auditability possible, not only lineage. For AI systems it is necessary to record not only decisions but also trajectory metadata required to reconstruct what specific steps were previously carried out. Retaining these records is now an operational capability that is foundational for production best practices for any AI systems in production.
+
+## Where it fails
+
+A single missing trail can have a cascading impact on the provenance of the system, and the gap is usually discovered during the incident that needed it.
+
+- Unpinned model versions that let providers change the system underneath its operators.
+- Gaps in data governance across the system's operations.
+- Historical steps that cannot be reconstructed from what was recorded.
+
+## Practical controls
+
+Controls should make the team's own system reproducible even when the model it builds on is not theirs.
+
+- Pin versions for models, prompts and configuration, including the base model, data and adapters of any fine-tune.
+- Make atomic steps deterministic through seed and input metadata.
+- Record data provenance and lineage across operations, including the trajectory metadata needed to reconstruct past steps.
diff --git a/src/content/principles/05.md b/src/content/principles/05.md
index eea2f0d3..a0142ce7 100644
--- a/src/content/principles/05.md
+++ b/src/content/principles/05.md
@@ -2,7 +2,7 @@
number: "05"
title: Reskilling by Design
description: Automation at scale changes work across organisations and industries; those effects should be identified and planned for, not discovered.
-commitment: We commit to identify, document and systematically support the re-skilling and evolution of our domain experts to mitigate the impact on workers affected by automation.
+commitment: We commit to identify, document and systematically support the reskilling of our domain experts and mitigate the impact on workers affected by automation, enabling Reskilling by Design.
failure_modes:
- Lack of systematic plan for workforce support
- No retraining and reskilling paths
@@ -16,6 +16,22 @@ related_links:
href: "/frameworks/"
---
-Automating medium or large processes affects many people across an organisation or industry, and general-purpose AI has widened the range of work this applies to. Technologists should look beyond the technology and help relevant stakeholders understand those effects and their impact. As Jevons observed of efficiency gains generally, cheaper automation tends to increase total demand for it not decrease it, so it is important that the industry as a whole is supported to evolve towards that increased demand.
+Automating medium or large processes affects many people across an organisation or industry, and general-purpose AI has widened the range of work this applies to. Technologists should look beyond the technology and help relevant stakeholders understand those effects and their impact. As observed with Jevons' paradox, when a new technology unlocks major automations that reduce the costs of a service, total demand does not decrease; in fact, as the service becomes more accessible, total demand increases. So it is important that the industry as a whole is supported to evolve towards that increased demand.
-Even if more junior practitioners do not lead an operational transformation, they should help ensure that appropriate change-management processes are in place, particularly if they are involved in the development in the AI systems involved. Those processes should contribute towards a sustainable industry-wide effort to shift and evolve amid the accelerated transformation that AI systems are imposing in society and the workforce.
+Even if more junior practitioners do not lead an operational transformation, they should contribute to ensure that appropriate change-management processes are in place, particularly if they are involved in the development of the AI systems involved. Those processes should contribute towards a sustainable industry-wide effort to shift and evolve amid the accelerated transformation that AI systems are imposing in society and the workforce.
+
+## Where it fails
+
+Displacement is rarely a single event; it accumulates while attention stays on the technology.
+
+- No systematic plan for supporting the workforce whose work is changing.
+- No retraining or reskilling paths for the roles being automated.
+- Process changes that go undocumented until the operational knowledge is gone.
+
+## Practical controls
+
+Controls should treat workforce impact as part of the delivery, not an afterthought of it.
+
+- Assess workforce impact before automating a process.
+- Plan business change alongside technical delivery, with reskilling paths for affected domain experts.
+- Document process changes so knowledge survives the transition.
diff --git a/src/content/principles/06.md b/src/content/principles/06.md
index 4e38b0f3..fcc57e01 100644
--- a/src/content/principles/06.md
+++ b/src/content/principles/06.md
@@ -1,11 +1,11 @@
---
number: "06"
-title: Monitoring & Evals
-description: A system that is only evaluated before launch is unevaluated for most of its lifetime; robust observability and evaluation is required across the end-to-end lifecycle of the system.
-commitment: We commit to evaluate our AI systems against the domain-specific consequences of their behaviour, and to ensure robust observability capabilities are in place for as long as the system operates.
+title: Evaluation by Observability
+description: A system that is only evaluated before launch is unevaluated for most of its lifetime; robust observability converts evals into a live property of the system.
+commitment: We commit to evaluate our AI systems against the domain-specific consequences of their behaviour, and to ensure robust monitoring capabilities are in place for as long as the system operates, enabling Evaluation by Observability.
failure_modes:
- Benchmark contamination and overfitting
- - Symmetric error assumptions
+ - Lack of telemetry, tracing, logging and general observability
- Drift that goes undetected after deployment
controls:
- Domain-grounded capability and safety evals
@@ -20,4 +20,20 @@ related_links:
A system can score well on public benchmarks and still be wrong in ways that matter in its domain. Evals should be built from the consequences of each kind of error, including **capability evals** for what the system must do, **safety evals** for what it must not, and **cost-weighted measures** that reflect the asymmetry between a false alarm and a missed harm.
-The same questions continue once the system is in production and should be monitored with robust observability. Behaviour must be tracked against real traffic rather than curated test sets, and where relevant advanced monitoring applied, such as drift and outlier detection, as well as agent/model-as-judge patterns throughout the data flow of the systems. Incidents and near misses should feed back into the evaluation suite, so each release is tested against the failures the previous one produced.
+The same questions continue once the system is in production and should be answered with robust observability. Behaviour must be tracked against real traffic rather than curated test sets, and where relevant advanced monitoring applied, such as drift and outlier detection, as well as agent/model-as-judge patterns throughout the data flow of the systems.
+
+## Where it fails
+
+Evaluation fails silently: the score stays green while the system and its conditions drift.
+
+- Benchmark contamination and overfitting inflating measured capability.
+- No telemetry, tracing or logging in place to see behaviour after launch.
+- Drift in data, usage or hosted model versions that goes undetected after deployment.
+
+## Practical controls
+
+Controls should make evaluation continuous, with production behaviour feeding the same suite that gated the release.
+
+- Build domain-grounded capability and safety evals with cost-weighted metrics.
+- Monitor production behaviour with drift and outlier detection, and agent/model-as-judge patterns where relevant.
+- Feed incidents and near misses back into the evaluation suite, so each release is tested against the failures the previous one produced.
diff --git a/src/content/principles/07.md b/src/content/principles/07.md
index ad7db217..0238b61f 100644
--- a/src/content/principles/07.md
+++ b/src/content/principles/07.md
@@ -1,21 +1,37 @@
---
number: "07"
title: Trust by Privacy
-description: Privacy protections must cover everyone a system touches, including people whose data reaches a model without their knowledge.
-commitment: We commit to build and communicate processes that protect the data of stakeholders interacting with our AI systems directly and indirectly.
+description: A Frontier Model can hold data from people who have never used it; every layer built on top can multiply exposure, so model deployers must ensure privacy is designed at each one in order to enable trust.
+commitment: We commit to build and communicate privacy processes that protect the data of stakeholders interacting with our AI systems directly and indirectly, enabling Trust by Privacy.
failure_modes:
- - Training data memorisation and extraction
- - Personal data retained by model providers
- - Sensitive data accumulating in agent context
+ - Personal data extractable from a model by prompting
+ - Sensitive data flowing to third parties the user never agreed to
+ - One user's data surfacing in another user's session
controls:
- - Data minimisation before inference
- - Provider retention terms and agreements
- - Memorisation and extraction testing
+ - Privacy impact assessment before connecting data to a model
+ - Memory segregation across users with no shared session context
+ - End-to-end encryption of personal data in transit and at rest
related_links:
- label: "AI-RFX: privacy capabilities"
href: "/frameworks/"
---
-AI systems widen the paths along which personal data can leak. Models can memorise training data and reproduce it under extraction attacks, a builder-side risk that fine-tuners take on the moment they train on their own records. On the deployer side, every inference call can send user data to a third-party provider, so retention terms belong in the privacy assessment, and agents accumulate sensitive material in their working context as they operate on a person's behalf.
+AI systems widen the paths along which personal data can leak. Models can memorise training data and reproduce it under extraction attacks, a builder-side risk that fine-tuners take on the moment they train on their own records. On the deployer side, every inference call can send user data to third parties the person never agreed to, and shared agent infrastructure can let one user's data surface in another's session.
-Privacy should be designed into the system and its operating processes: minimise what enters a prompt or context window, contract for retention and use limits with providers, and test fine-tuned models for memorisation before release. Trust also requires communication, so stakeholders, direct and indirect, should be able to learn what data is held, how it is handled and why protecting it matters.
+Privacy should therefore be designed at every layer: assessed before data is connected to a model, segregated across users and tiers in memory, and encrypted in transit and at rest. Trust also requires communication, so stakeholders, direct and indirect, should be able to learn what data is held, how it is handled and why protecting it matters.
+
+## Where it fails
+
+The leak paths are wider than the application's own database, and most of them sit outside classic privacy reviews.
+
+- Personal data extractable from a model by prompting.
+- Sensitive data flowing to third parties the person never agreed to.
+- One user's data surfacing in another user's session.
+
+## Practical controls
+
+Controls should protect data at every layer it passes through, before it reaches a model, while it sits in memory, and wherever it travels.
+
+- Run a privacy impact assessment before connecting data to a model.
+- Segregate memory across users, with no shared session context.
+- Encrypt personal data end to end, in transit and at rest.
diff --git a/src/content/principles/08.md b/src/content/principles/08.md
index b0c12f3c..562a7c0d 100644
--- a/src/content/principles/08.md
+++ b/src/content/principles/08.md
@@ -1,15 +1,15 @@
---
number: "08"
-title: Security & Safety
-description: The attack surface of an AI system includes every piece of text its models read and every tool its agents can call. Security failures become safety failures the moment a system can act.
-commitment: We commit to develop the processes and infrastructure required to secure our AI systems across their lifecycle, and to treat the safety of their actions as part of that security boundary.
+title: Safety by Security
+description: Any input a model processes is an attack surface; any tool an agent holds is blast radius. AI systems must be secured across their whole lifecycle, because there is no safety without security.
+commitment: We commit to develop the processes and infrastructure required to secure our AI systems across their lifecycle, and to treat the safety of their actions as part of that boundary, enabling Safety by Security.
failure_modes:
- - Prompt injection turning content into instructions
- - Agents misusing tools and permissions
- - Model and data supply-chain compromise
+ - Agents granted standing permissions beyond their task
+ - Models, data and tools adopted without vetting or integrity checks
+ - Agent credentials shared across users, tasks and environments
controls:
- - Threat reviews against the MLSecOps and OWASP agentic Top 10s
- - Least-privilege, sandboxed tool access for agents
+ - Threat modelling against the MLSecOps Top 10 and OWASP agentic attack vectors
+ - Trust boundaries separating model instructions from external content
- Red-teaming, layered safeguards and monitoring
related_links:
- label: "MLSecOps Top 10"
@@ -18,6 +18,22 @@ related_links:
href: "https://genai.owasp.org/2025/12/09/owasp-top-10-for-agentic-applications-the-benchmark-for-agentic-security-in-the-age-of-autonomous-ai/"
---
-Security spans the full lifecycle of an AI system: training data can be poisoned, model artifacts and their dependencies compromised through the supply chain, and deployed models probed through their own interface. Prompt injection turns any text a model reads into a potential instruction channel, jailbreaks defeat behavioural safeguards, and an agent connected to tools converts a successful injection into real actions with real permissions. This is where security and safety meet: a compromised agent is not only a breached system but an unsafe one, and controls should match both the system's exposure and the harm its actions could cause.
+Security spans the full lifecycle of an AI system: training data can be poisoned, model artifacts and their dependencies compromised through the supply chain, and deployed models probed through their own interface. Prompt injection turns any input a model processes into a potential instruction channel, jailbreaks defeat behavioural safeguards, and an agent connected to tools converts a successful injection into real actions with real permissions. This is where security and safety meet: a compromised agent is not only a breached system but an unsafe one, and controls should match both the system's exposure and the harm its actions could cause.
-Teams should assume that capable adversaries will probe their models and tools, grant agents the least privilege their task requires, and validate layered safeguards through repeatable red-teaming and monitoring. The institute's MLSecOps Top 10 covers the pipeline-level vulnerabilities; the attack vectors specific to agentic systems are catalogued in the OWASP agentic security work the institute co-authored. Together with the OWASP Top 10 for LLM applications, these should anchor a threat review before any AI system reaches production.
+Teams should assume that capable adversaries will probe their models and tools, and provision agents accordingly: least privilege, per-task credentials, and no standing access beyond need. The institute's MLSecOps Top 10 covers the pipeline-level vulnerabilities; the attack vectors specific to agentic systems are catalogued in the OWASP agentic security work the institute co-authored. Together with the OWASP Top 10 for LLM applications, these should anchor a threat review before any AI system reaches production.
+
+## Where it fails
+
+Most AI security failures are prepared in advance by the team's own defaults, long before an adversary arrives.
+
+- Agents granted standing permissions beyond what their task requires.
+- Models, data and tools adopted without vetting or integrity checks.
+- Agent credentials shared across users, tasks and environments.
+
+## Practical controls
+
+Controls should match the system's exposure and the harm its actions could cause.
+
+- Threat-model against the MLSecOps Top 10, the OWASP agentic attack vectors and the OWASP Top 10 for LLM applications.
+- Enforce trust boundaries that separate model instructions from external content.
+- Validate layered safeguards through repeatable red-teaming and monitoring.
diff --git a/src/content/principles/09.md b/src/content/principles/09.md
index be5fb970..945d7fce 100644
--- a/src/content/principles/09.md
+++ b/src/content/principles/09.md
@@ -1,16 +1,16 @@
---
number: "09"
-title: Intent Alignment
-description: An aligned system pursues the objectives its operators intended, within bounds set by the interests of the people its actions affect. Neither the intent nor the bounds can be assumed; both must be specified and tested.
-commitment: We commit to evaluate whether our AI systems pursue the objectives their operators intended, to test for goal misgeneralisation, deception and misuse where reasonable, and to hold those objectives to the interests of the people they affect.
+title: Human Alignment by Intent
+description: A system optimises what it was given, not what was meant. Intent must be made explicit, tested under pressure, and revisable when evidence contradicts it.
+commitment: We commit to evaluate whether our AI systems pursue what was intended rather than what was measured, and to test for misgeneralisation, deception and misuse where reasonable, ensuring Human Alignment by Intent.
failure_modes:
- - Goal misgeneralisation outside training conditions
- - Deceptive behaviour under evaluation
- - Operator objectives that harm the people affected
+ - No definition of what the system must never pursue
+ - High risk systems that cannot be interrupted once running
+ - Objectives never revisited as the deployment context changes
controls:
- - Testable intent specification
- - Adversarial and scheming evaluations
- - Interruptible deployments with revisable objectives
+ - Periodic objective reviews as deployment conditions change
+ - Post-deployment audits of behaviour against the stated intent
+ - Monitoring for divergence between the metric and intended outcome
related_links:
- label: "K8s Agent OS (KAOS)"
href: "/open-source/kaos/"
@@ -18,6 +18,22 @@ related_links:
href: "/initiatives/"
---
-An aligned system behaves consistently with the purpose, constraints and values established by accountable people. A capable system can satisfy its evaluations while pursuing something other than what its operators intended: optimising a proxy that diverges outside training, behaving differently when it detects it is being tested, or being repurposed for harm. Alignment to operator intent is therefore the first requirement, and it must be made testable rather than assumed.
+An aligned system behaves consistently with the purpose, constraints and values established by accountable people. A capable system can satisfy its evaluations while pursuing something other than what its operators intended: optimising a proxy that diverges outside training, behaving differently when it detects it is being tested, or being repurposed for harm. Alignment to operator intent is therefore the first requirement, and that intent must be made explicit and testable rather than assumed.
-It is not the last requirement. An objective can be faithfully pursued and still cause harm, so the values a system serves must extend beyond its operator to the people its actions affect. This principle asks what the system is pursuing and for whom; whether its errors fall unevenly across people is the separate question covered by principle 02. Teams should specify intent, examine how systems behave under adversarial pressure, and retain the ability to interrupt or revise deployments as real-world evidence changes.
+An objective can be faithfully pursued and still cause harm, so the values a system serves must extend beyond its operator to the people its actions affect, including a clear definition of what the system must never pursue. Those obligations do not end at deployment, as objectives should be revisited as deployment conditions change, behaviour audited against the stated intent, and high-risk systems kept interruptible for as long as they run. This principle asks what the system is pursuing and for whom; whether its errors fall unevenly across people is the separate question covered by principle 02.
+
+## Where it fails
+
+A system can pass its evaluations and still pursue the wrong thing, and the practices that allow it are set by the team long before deployment.
+
+- No definition of what the system must never pursue.
+- High-risk systems that cannot be interrupted once running.
+- Objectives never revisited as the deployment context changes.
+
+## Practical controls
+
+Controls should keep the stated intent and the deployed behaviour in contact for as long as the system runs.
+
+- Review objectives periodically as deployment conditions change.
+- Audit post-deployment behaviour against the stated intent.
+- Monitor for divergence between the metric and the intended outcome.
diff --git a/src/content/repos-metrics.yaml b/src/content/repos-metrics.yaml
index 8ac9e68d..25ddf7b2 100644
--- a/src/content/repos-metrics.yaml
+++ b/src/content/repos-metrics.yaml
@@ -10,18 +10,34 @@ xai:
values:
- value: 1.3k
label: STARS
- - value: '3'
- label: CONTRIBUTORS
+ - value: MIT
+ label: ''
+ - value: ALPHA — ACTIVE
+ label: ''
ecosystem:
values:
- - value: 20.8k
+ - value: 20.8K
label: STARS
- value: '210'
label: CONTRIBUTORS
+ - value: 550+
+ label: LIBRARIES
+ - value: '24'
+ label: CATEGORIES
+ai-guidelines:
+ values:
+ - value: 1.4K
+ label: STARS
+ - value: '15'
+ label: ECONOMIC AREAS
+ - value: MIT
+ label: ''
kaos:
values:
- value: '268'
label: STARS
+ - value: V0.7.0
+ label: ''
- value: '5'
label: CONTRIBUTORS
- value: APACHE-2.0
diff --git a/src/pages/initiatives.mdx b/src/pages/initiatives.mdx
index bb13f4e2..aa7fb50f 100644
--- a/src/pages/initiatives.mdx
+++ b/src/pages/initiatives.mdx
@@ -17,7 +17,7 @@ The Institute participates in ISO/IEC AI standards work, which sets the formal,
The Institute also participates in IEEE AI standards work.
{/* */}
-**Practical output:**
AI-RFX repository
+**Practical output:**
AI-RFX repository
## Policy advisory
@@ -27,28 +27,28 @@ The Institute participates in United Nations AI and data-governance work at the
European Commission AI policy work spans the AI Act, Data Act, Digital Services Act and Cyber Resilience Act. ACM's Code of Ethics and Professional Conduct and its technology-policy work set expectations for computing professionals broadly.
{/* */}
-**Organisation records:**
UN CSTD committee record ·
ACM role
+**Organisation records:**
UN CSTD committee record ·
ACM role
## MLSecOps and OWASP
ML security work studies gaps between the standard software-security taxonomy and machine-learning-specific risks. Model artifacts, training pipelines and inference endpoints introduce failure modes outside the scope of the OWASP Top 10. The MLSecOps Top 10 addresses these gaps by mapping ten vulnerability classes from OWASP categories onto the ML lifecycle, from unrestricted model endpoints to supply-chain risk in ML code.
{/* */}
-**Organisation record:**
OWASP collaboration
+**Organisation record:**
OWASP collaboration
## Linux Foundation AI & Data and NumFOCUS
The Institute's collaboration with Linux Foundation AI & Data includes two open-source projects. Kompute is cross-vendor GPU acceleration work maintained alongside LF AI & Data and NumFOCUS. The MLSecOps Top 10 was connected to LF's Trusted AI work and an ML-security committee.
{/* */}
-**Organisation records:**
Linux Foundation collaboration ·
NumFOCUS contribution
+**Organisation records:**
Linux Foundation collaboration ·
NumFOCUS contribution
## Principles and frameworks
Technical assurance and evaluation considers whether an AI system is fit for a given deployment. It examines accuracy and whether the system's infrastructure, processes and monitoring support the claim. This work underlies the AI-RFX Procurement Framework and the ML Maturity Model. Both translate assurance questions into criteria for evaluating a supplier or system.
{/* */}
-**Practical initiatives:** [The nine principles](/principles/) ·
Awesome AI Guidelines repository ·
AI-RFX repository · [Frameworks](/frameworks/) · [ML Maturity Model](/frameworks/maturity-model/)
+**Practical initiatives:** [The nine principles](/principles/) ·
Awesome AI Guidelines repository ·
AI-RFX repository · [Frameworks](/frameworks/) · [ML Maturity Model](/frameworks/maturity-model/)
## Reports and data
@@ -62,6 +62,6 @@ The State of Production ML surveys provide evidence on how organisations run mac
KAOS provides control-plane primitives for enforcing alignment evaluation. These include scoped credentials, budget and time limits, human approval gates and an audit trail.
{/* */}
-**Practical initiatives:** [KAOS](/open-source/kaos/) ·
GitHub repository ·
Documentation ·
Production observability article · [All open-source work](/open-source/)
+**Practical initiatives:** [KAOS](/open-source/kaos/) ·
GitHub repository ·
Documentation ·
Production observability article · [All open-source work](/open-source/)
diff --git a/src/pages/open-source/ai-guidelines.mdx b/src/pages/open-source/ai-guidelines.mdx
new file mode 100644
index 00000000..d2384635
--- /dev/null
+++ b/src/pages/open-source/ai-guidelines.mdx
@@ -0,0 +1,29 @@
+---
+title: Awesome AI Regulation, Principles & Guidelines
+description: 'A repository "mapping the ecosystem of guidelines, principles, codes of ethics, standards and regulation being put in place around artificial intelligence", from national law to practical checklists.'
+composed: true
+layout: ../../layouts/ProseLayout.astro
+---
+
+import { ArticleHero, CTA, Metrics, RegulationGrid } from '../../components/prose/components.js';
+import catalogues from '../../content/oss-catalogues.json';
+
+
+
+## Two ways in
+
+By geography: national regulation and policy across fifteen economic areas, from the EU AI Act ("the first regulation implemented on AI") to national strategies across the Americas, Asia and the Middle East. By theme: high-level frameworks and principles, industry standards initiatives, practical tools and checklists, courses, and research newsletters.
+
+
+
+The Institute's own nine principles sit in the same ecosystem this list maps, which is why the repository is where our policy work and the wider landscape meet.
+
+
+
+
diff --git a/src/pages/open-source/index.mdx b/src/pages/open-source/index.mdx
index 01b70753..3d5f15db 100644
--- a/src/pages/open-source/index.mdx
+++ b/src/pages/open-source/index.mdx
@@ -1,20 +1,41 @@
---
title: Open source & tools
-description: Openly licensed software for explainability, safe agents, GPU compute and production ML.
+description: Openly licensed software for agent orchestration, GPU compute, explainability and production ML.
composed: true
layout: ../../layouts/ProseLayout.astro
+projects:
+ - pills: [v0.7.0, APACHE-2.0, K8S ≥1.28]
+ title: KAOS
+ subtitle: Deploy, manage and orchestrate AI agents on Kubernetes.
+ visual: kaos
+ href: /open-source/kaos/
+ - pills: [LINUX FOUNDATION, APACHE-2.0, 2.5K STARS]
+ title: Kompute
+ subtitle: The general-purpose GPU compute framework for cross-vendor graphics cards, hosted by LF AI & Data.
+ visual: kompute
+ href: /open-source/kompute/
+ - pills: [ALPHA, MIT, 1.3K STARS]
+ title: XAI
+ subtitle: An explainability toolbox for machine learning, across data, model and production.
+ visual: xai
+ href: /open-source/xai/
+ - pills: [COMMUNITY, 20.8K STARS]
+ title: Awesome Production ML
+ rail: Prod ML List
+ subtitle: 'The community catalogue of production ML tooling: 24 categories, 550+ libraries.'
+ visual: production-ml
+ href: /open-source/production-ml-list/
---
-import { ArticleHero, CenteredCTA, OpenSourceShowcase } from '../../components/prose/components.js';
-import { frontmatter as home } from '../index.mdx';
+import { ArticleHero, CenteredCTA, ProjectPortal } from '../../components/prose/components.js';
-
+
diff --git a/src/pages/open-source/kaos.mdx b/src/pages/open-source/kaos.mdx
index 17a1b796..93afd375 100644
--- a/src/pages/open-source/kaos.mdx
+++ b/src/pages/open-source/kaos.mdx
@@ -1,49 +1,82 @@
---
+layout: ../../layouts/ProseLayout.astro
title: K8s Agent OS (KAOS)
-description: KAOS provides a control plane for autonomous agents, with controls for tools, credentials, budgets, time, approval steps and audit records.
+description: Deploy, manage and orchestrate AI agents on Kubernetes. KAOS turns agents, models, tools and memory into declarative Kubernetes resources, reconciled by an operator, secured at the gateway and observable end to end. "Managing the chaos in your agentic systems."
composed: true
-layout: ../../layouts/ProseLayout.astro
-capabilities:
- - capability: Scoped credentials
- detail: Issue task-specific access and remove it when the work ends.
- - capability: Sandboxed execution
- detail: Isolate tools and untrusted inputs from sensitive systems.
- - capability: Budget limits
- detail: Bound compute, tokens, requests, and external spend.
- - capability: Time horizon
- detail: Limit how long an agent can act without renewed approval.
- - capability: Human approval
- detail: Gate consequential actions behind accountable decisions.
- - capability: Audit trail
- detail: Record plans, tool calls, policy decisions, and outcomes.
+
+quickstart:
+ cli:
+ - command: pip install kaos-cli
+ output: Successfully installed kaos-cli
+ - command: kaos system install
+ output: KAOS operator and system services are ready
+ - command: kaos modelapi deploy my-api --mode Hosted --model "smollm2:135m"
+ output: ModelAPI/my-api created · Ready
+ - command: kaos agent deploy my-agent --modelapi my-api --model "smollm2:135m"
+ output: Agent/my-agent created · Ready
+ - command: kaos agent invoke my-agent --message "Hello"
+ output: Hello! How can I help you today?
+ - command: kaos ui
+ output: Dashboard available at http://localhost:3000
+media:
+ - alt: KAOS dashboard workflow showing agent operations
+ caption: Dashboard workflow
+ href: https://axsaucedo.github.io/kaos/
+ poster: /images/oss/demo-poster.webp
+ src: /images/oss/demo.gif
+ - alt: KAOS monitoring view showing traces and flamegraphs
+ caption: Observability with traces and flamegraphs
+ href: https://axsaucedo.github.io/kaos/
+ poster: /images/oss/demo-monitoring-poster.webp
+ src: /images/oss/demo-monitoring.gif
+
+links:
+ - label: Explore the project →
+ href: https://github.com/axsaucedo/kaos
+ - label: Read the docs →
+ href: https://axsaucedo.github.io/kaos/
---
-import { ArticleHero, CapabilityTable, CTA, Feature, Metrics } from '../../components/prose/components.js';
+import { ArticleHero, ControlPlaneMap, KaosProjectFooter, MediaBand, MemoryTiers, QuickstartTerminal, RequestPath } from '../../components/prose/components.js';
+
+
+
+## From zero to a running agent
+
+An agent is a resource, not a script. Install the system, deploy a model API and an agent, and talk to it; every agent exposes an OpenAI-compatible `/v1/chat/completions` endpoint, so existing clients work unchanged.
+
+
+
+## The control plane
+
+Five custom resources define an agent system: **Agent** (the running agent, its model, tools, peers and memory binding), **ModelAPI** (LLM access, proxied via LiteLLM or hosted in-cluster with Ollama), **MCPServer** (tool servers speaking the Model Context Protocol), **MemoryStore** (the central memory service agents bind to) and **AccessGrant** (who may reach what). Four controllers reconcile them into pods, services and policy.
+
+
-
+Agents delegate through the A2A protocol: discovery via `/.well-known/agent.json`, sub-agents exposed to the model as tools, and "hierarchical agent systems with automatic delegation".
-
+## Memory that survives the session
-Each agent receives only the authority required for its task. Planning, execution, policy checks, verification, and audit remain visible as work moves through the system.
+"Memory is augmentation, not a hard dependency." A MemoryStore runs one central memory service per store, with Mem0 embedded as a library rather than a separate server. Short-term memory keeps the recent conversation window in relational rows; an optional rolling summary preserves narrative continuity; long-term memory holds semantic facts in a vector store, recalled by relevance across sessions.
-The graph represents explicit control points where teams can constrain or interrupt autonomous behaviour.
+Scopes make memory multi-tenant: reads select session, agent, user or store scope, and "scope is derived server-side from the authenticated agent identity", never from model arguments. When a store fails, the agent keeps serving short-term-only and surfaces a `MemoryDegraded` condition instead of going down.
-
+
-## Capabilities
+## Secured at the gateway
-KAOS implements safety controls as runtime infrastructure. Its tabular capability model is reused across the site.
+Security is off until you turn it on, and fail-closed once you do: protected routes pass Envoy Gateway, which verifies JWTs and consults an OPA policy decision point; "an unavailable PDP never permits a request". Identity is two-plane: the subject (a Keycloak user, or the agent itself when autonomous) and the acting agent, verified on every hop. Agent identity comes from per-agent ServiceAccounts with short-lived projected tokens, an identity broker, or per-agent OAuth clients registered dynamically.
-
+Authorization is declarative: `AccessGrant` resources bind users, groups and agents to the resources they may enter, and the operator projects them into policy. Memory enforces the same identities, so one user's recall can never serve another's session.
-
+
-## Build with bounded autonomy
+## Watch it work
-Agent systems should remain governable as their capabilities increase. KAOS gives engineering teams a small set of enforceable controls for defining operational boundaries.
+
-
+The dashboard covers the operational loop: monitor agents, chat with them live, inspect memory sessions and events, debug MCP tools with real calls, and stream pod logs. Agents ship OpenTelemetry instrumentation, so traces land in your existing observability stack.
-Start with the architecture and adapt the controls to your environment. Contributions based on implementation experience are welcome.
+## Metrics + CTAs
-
+
diff --git a/src/pages/open-source/kompute.mdx b/src/pages/open-source/kompute.mdx
new file mode 100644
index 00000000..1da37c40
--- /dev/null
+++ b/src/pages/open-source/kompute.mdx
@@ -0,0 +1,128 @@
+---
+title: Kompute
+description: The general purpose GPU compute framework for cross vendor graphics cards (AMD, Qualcomm, NVIDIA & friends). Blazing fast, mobile-enabled, asynchronous, and optimized for advanced GPU acceleration usecases.
+composed: true
+layout: ../../layouts/ProseLayout.astro
+---
+
+import { getEntry } from 'astro:content';
+import { ArticleHero, CodeTabs, Metrics, ProjectLinks, SequencePipeline } from '../../components/prose/components.js';
+
+export const pythonCode = `# 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
+mgr = kp.Manager()
+
+# 2. Create and initialise Kompute Tensors through manager
+
+# Default tensor constructor simplifies creation of float values
+
+tensor_in_a = mgr.tensor([2, 2, 2])
+tensor_in_b = mgr.tensor([1, 2, 3])
+
+# Explicit type constructor supports uint32, int32, double, float and bool
+
+tensor_out_a = mgr.tensor_t(np.array([0, 0, 0], dtype=np.uint32))
+tensor_out_b = mgr.tensor_t(np.array([0, 0, 0], dtype=np.uint32))
+assert(t_data.data_type() == kp.DataTypes.uint)
+
+params = [tensor_in_a, tensor_in_b, tensor_out_a, tensor_out_b]
+
+# 3. Create algorithm based on shader (supports buffers & push/spec constants)
+
+workgroup = (3, 1, 1)
+spec_consts = [2]
+push_consts_a = [2]
+push_consts_b = [3]
+
+# See documentation shader section for compile_source
+
+spirv = compile_source(shader)
+
+algo = mgr.algorithm(params, spirv, workgroup, spec_consts, push_consts_a)
+
+# 4. Run operation synchronously using sequence
+
+(mgr.sequence()
+.record(kp.OpSyncDevice(params))
+.record(kp.OpAlgoDispatch(algo)) # Binds default push consts provided
+.eval() # evaluates the two recorded ops
+.record(kp.OpAlgoDispatch(algo, push_consts_b)) # Overrides push consts
+.eval()) # evaluates only the last recorded op`;
+
+export const cppCode = `// 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
+kp::Manager mgr;
+
+// 2. Create and initialise Kompute Tensors through manager
+
+// Default tensor constructor simplifies creation of float values
+auto tensorInA = mgr.tensor({ 2., 2., 2. });
+auto tensorInB = mgr.tensor({ 1., 2., 3. });
+// Explicit type constructor supports uint32, int32, double, float and bool
+auto tensorOutA = mgr.tensorT
({ 0, 0, 0 });
+auto tensorOutB = mgr.tensorT({ 0, 0, 0 });
+
+std::vector> params = {tensorInA, tensorInB, tensorOutA, tensorOutB};
+
+// 3. Create algorithm based on shader (supports buffers & push/spec constants)
+kp::Workgroup workgroup({3, 1, 1});
+std::vector specConsts({ 2 });
+std::vector pushConstsA({ 2.0 });
+std::vector pushConstsB({ 3.0 });
+
+auto algorithm = mgr.algorithm(params,
+// See documentation shader section for compileSource
+compileSource(shader),
+workgroup,
+specConsts,
+pushConstsA);
+
+// 4. Run operation synchronously using sequence
+mgr.sequence()
+->record(params)
+->record(algorithm) // Binds default push consts
+->eval() // Evaluates the two recorded operations
+->record(algorithm, pushConstsB) // Overrides push consts
+->eval(); // Evaluates only last recorded operation`;
+
+export const facts = [
+ { value: '90% UNIT TEST COVERAGE', label: '' },
+ { value: 'MONTHLY COMMUNITY CALLS', label: '' },
+ { value: 'FOSDEM TALKS', label: '' },
+ { value: 'C++ AND PYTHON', label: '' },
+];
+
+export const links = [
+ { label: 'View on GitHub →', href: 'https://github.com/KomputeProject/kompute' },
+ { label: 'kompute.cc →', href: 'https://kompute.cc' },
+];
+
+export const metricEntry = await getEntry('metrics', 'kompute');
+
+
+
+## The mental model
+
+Four concepts carry the whole framework: a **Manager** owns the device, **Tensors** own data, an **Algorithm** wraps the shader logic, and a **Sequence** records operations to submit as a batch. Everything else is Vulkan doing what Vulkan does, without the boilerplate.
+
+
+
+## Two languages, one API
+
+
+
+The Python module covers experimentation; the C++ SDK goes as deep as the optimisation requires. Asynchronous and parallel execution comes through GPU family queues, and the BYOV design ("bring-your-own-Vulkan") plugs into existing Vulkan applications.
+
+## Proven where it counts
+
+Kompute backs on-device LLM inference in **GPT4ALL**, appeared as a backend in **llama.cpp**, and powers **vkJAX**, the JAX interpreter for Vulkan. It runs on Android via the NDK, on Raspberry Pi through Mesa, and in the Godot engine for game development.
+
+
+
+
diff --git a/src/pages/open-source/production-ml-list.mdx b/src/pages/open-source/production-ml-list.mdx
new file mode 100644
index 00000000..f5d55f36
--- /dev/null
+++ b/src/pages/open-source/production-ml-list.mdx
@@ -0,0 +1,30 @@
+---
+title: Awesome Production Machine Learning
+description: '"A curated list of awesome open source libraries to deploy, monitor, version and scale your machine learning." More than 550 libraries across 24 categories, with a summary of new additions released every month.'
+composed: true
+layout: ../../layouts/ProseLayout.astro
+---
+
+import { ArticleHero, CategoryAtlas, CTA, Metrics } from '../../components/prose/components.js';
+import catalogues from '../../content/oss-catalogues.json';
+
+
+
+## Explore the categories
+
+
+
+## How it stays current
+
+New libraries are added continuously and summarised in monthly releases, so watching the repository doubles as an ecosystem changelog. The weekly companion is the Machine Learning Engineer newsletter, where "over 70,000 ML professionals and enthusiasts" receive curated production ML articles and tutorials.
+
+
+
+
diff --git a/src/pages/open-source/xai.mdx b/src/pages/open-source/xai.mdx
new file mode 100644
index 00000000..3b3bb257
--- /dev/null
+++ b/src/pages/open-source/xai.mdx
@@ -0,0 +1,90 @@
+---
+title: XAI — an eXplainability toolbox for machine learning
+description: 'XAI is a Machine Learning library that is designed with AI explainability in its core. It implements the three steps of explainable machine learning: data analysis, model evaluation and production monitoring, tools and process together.'
+composed: true
+layout: ../../layouts/ProseLayout.astro
+---
+
+import { getEntry } from 'astro:content';
+import { ArticleHero, Metrics, ProjectLinks, StageExplorer, TalkCard } from '../../components/prose/components.js';
+
+export const stages = [
+ {
+ number: '01',
+ title: 'Data analysis',
+ functions: [
+ {
+ name: 'imbalance_plot',
+ purpose: 'Plot class imbalances across one or more columns.',
+ image: '/images/oss/xai-imbalance.jpg',
+ imageAlt: 'XAI class-imbalance plots split by gender and loan outcome',
+ },
+ { name: 'balance', purpose: 'Correct class imbalances with up-sampling or down-sampling.' },
+ { name: 'correlations', purpose: 'Visualise correlations as a matrix or hierarchical dendogram.' },
+ { name: 'group_by_columns', purpose: 'Group a dataset by one or more categorical columns for custom operations.' },
+ { name: 'balanced_train_test_split', purpose: 'Create train and test splits balanced across protected attributes.' },
+ ],
+ },
+ {
+ number: '02',
+ title: 'Model evaluation',
+ functions: [
+ { name: 'feature_importance', purpose: 'Calculate permutation-based feature importance.' },
+ {
+ name: 'metrics_plot',
+ purpose: 'Compare metric imbalances overall and across protected columns.',
+ image: '/images/oss/xai-metrics.jpg',
+ imageAlt: 'XAI model metrics compared across gender and ethnicity groups',
+ },
+ { name: 'roc_plot', purpose: 'Plot ROC curves overall or per group, such as gender, ethnicity, or age.' },
+ { name: 'confusion_matrix_plot', purpose: 'Render a confusion matrix for model predictions.' },
+ ],
+ },
+ {
+ number: '03',
+ title: 'Production monitoring',
+ functions: [
+ {
+ name: 'smile_imbalance',
+ purpose: 'Bucket accuracy and statistical metrics by prediction probability to visualise benefits of adding manual review on probability thresholds.',
+ image: '/images/oss/xai-monitoring.png',
+ imageAlt: 'XAI probability buckets showing a manual review threshold',
+ },
+ ],
+ },
+];
+
+export const links = [
+ { label: 'Open the framework →', href: 'https://github.com/EthicalML/xai' },
+ { label: 'Read the docs →', href: 'https://ethicalml.github.io/xai' },
+];
+
+export const metricEntry = await getEntry('metrics', 'xai');
+
+
+
+## The toolbox, by stage
+
+
+
+The library ships with a census dataset for experimentation (`xai.data.load_census()`), and installs from PyPI. The protected-attribute lens runs through every stage: the same gender or ethnicity split that shapes the train/test split reappears in the metric and ROC comparisons.
+
+## Talk and worked example
+
+The approach was presented at PyData London, covering how to identify and mitigate undesired bias with the toolbox.
+
+
+
+
+
diff --git a/src/plugins/rehype-external-links.mjs b/src/plugins/rehype-external-links.mjs
new file mode 100644
index 00000000..445cd2c5
--- /dev/null
+++ b/src/plugins/rehype-external-links.mjs
@@ -0,0 +1,18 @@
+import { isExternalHref } from '../utils/external-links.mjs';
+
+export default function rehypeExternalLinks() {
+ return (tree) => {
+ const visit = (node) => {
+ if (
+ node.type === 'element' &&
+ node.tagName === 'a' &&
+ isExternalHref(node.properties?.href)
+ ) {
+ node.properties = { ...node.properties, target: '_blank', rel: ['noopener', 'noreferrer'] };
+ }
+ node.children?.forEach(visit);
+ };
+
+ visit(tree);
+ };
+}
diff --git a/src/shared/canvas/CategoryConstellation.ts b/src/shared/canvas/CategoryConstellation.ts
new file mode 100644
index 00000000..9d472ffc
--- /dev/null
+++ b/src/shared/canvas/CategoryConstellation.ts
@@ -0,0 +1,81 @@
+import { CanvasEngine, type CanvasDraw } from './CanvasEngine';
+
+interface CategoryNode {
+ label: string;
+ x: number;
+ y: number;
+ phase: number;
+}
+
+const nodes: CategoryNode[] = [
+ { label: 'SERVING', x: 0.18, y: 0.27, phase: 0.2 },
+ { label: 'ORCHESTRATION', x: 0.46, y: 0.18, phase: 1.1 },
+ { label: 'MONITORING', x: 0.76, y: 0.3, phase: 2.4 },
+ { label: 'DATA', x: 0.29, y: 0.57, phase: 3.2 },
+ { label: 'FEATURES', x: 0.63, y: 0.55, phase: 4.4 },
+ { label: 'PRIVACY', x: 0.82, y: 0.75, phase: 5.1 },
+ { label: 'TRAINING', x: 0.43, y: 0.82, phase: 5.8 },
+ { label: 'REGISTRY', x: 0.12, y: 0.76, phase: 0.8 },
+];
+
+const edges: [number, number][] = [
+ [0, 1],
+ [0, 3],
+ [1, 2],
+ [1, 4],
+ [2, 4],
+ [2, 5],
+ [3, 4],
+ [3, 6],
+ [3, 7],
+ [4, 6],
+ [5, 6],
+ [6, 7],
+];
+
+const drawConstellation: CanvasDraw = (context, width, height, elapsed) => {
+ context.clearRect(0, 0, width, height);
+ const padding = Math.min(width, height) * 0.1;
+ const points = nodes.map((node) => ({
+ ...node,
+ screenX: padding + node.x * (width - padding * 2) + Math.sin(elapsed * 0.35 + node.phase) * 8,
+ screenY: padding + node.y * (height - padding * 2) + Math.cos(elapsed * 0.28 + node.phase) * 6,
+ }));
+
+ context.lineWidth = 1;
+ context.strokeStyle = 'rgba(244,242,238,.13)';
+ edges.forEach(([from, to]) => {
+ context.beginPath();
+ context.moveTo(points[from].screenX, points[from].screenY);
+ context.lineTo(points[to].screenX, points[to].screenY);
+ context.stroke();
+ });
+
+ context.font = "10px 'Geist Mono', monospace";
+ points.forEach((point, index) => {
+ const pulse = 0.6 + Math.sin(elapsed * 0.7 + point.phase) * 0.25;
+ context.beginPath();
+ context.arc(point.screenX, point.screenY, index % 3 === 0 ? 4 : 3, 0, Math.PI * 2);
+ context.fillStyle = `rgba(94,230,160,${pulse})`;
+ context.fill();
+ context.fillStyle = 'rgba(244,242,238,.6)';
+ context.fillText(point.label, point.screenX + 10, point.screenY + 4);
+ });
+};
+
+export class CategoryConstellation extends HTMLElement {
+ private engine?: CanvasEngine;
+
+ connectedCallback() {
+ const canvas = this.querySelector('canvas');
+ if (canvas) this.engine = new CanvasEngine(canvas, drawConstellation);
+ }
+
+ disconnectedCallback() {
+ this.engine?.destroy();
+ }
+}
+
+if (!customElements.get('category-constellation')) {
+ customElements.define('category-constellation', CategoryConstellation);
+}
diff --git a/src/shared/canvas/ControlPlaneMap.ts b/src/shared/canvas/ControlPlaneMap.ts
new file mode 100644
index 00000000..37687147
--- /dev/null
+++ b/src/shared/canvas/ControlPlaneMap.ts
@@ -0,0 +1,160 @@
+import { CanvasEngine } from './CanvasEngine';
+
+interface ControlNode {
+ label: string;
+ x: number;
+ y: number;
+}
+
+const CRDS: ControlNode[] = [
+ { label: 'Agent', x: 0.5, y: 0.12 },
+ { label: 'ModelAPI', x: 0.79, y: 0.31 },
+ { label: 'MCPServer', x: 0.72, y: 0.7 },
+ { label: 'MemoryStore', x: 0.28, y: 0.7 },
+ { label: 'AccessGrant', x: 0.21, y: 0.31 },
+];
+
+const RUNTIME: ControlNode[] = [
+ { label: 'agent pods', x: 0.5, y: 0.01 },
+ { label: 'gateway', x: 0.95, y: 0.5 },
+ { label: 'memory service', x: 0.05, y: 0.5 },
+];
+
+export class ControlPlaneMap extends HTMLElement {
+ private controller = new AbortController();
+ private engine?: CanvasEngine;
+ private pulseStarted = -1;
+ private selected = 0;
+
+ connectedCallback() {
+ this.controller = new AbortController();
+ const canvas = this.querySelector('canvas');
+ const selectors = Array.from(this.querySelectorAll('[data-crd]'));
+ const panels = Array.from(this.querySelectorAll('[data-crd-panel]'));
+ const delegate = this.querySelector('[data-delegate]');
+ if (!canvas || !selectors.length || !panels.length || !delegate) return;
+
+ this.engine = new CanvasEngine(canvas, (context, width, height, elapsed) => {
+ this.draw(context, width, height, elapsed);
+ });
+
+ const select = (index: number) => {
+ this.selected = index;
+ selectors.forEach((button, buttonIndex) => {
+ button.classList.toggle('active', buttonIndex === index);
+ button.setAttribute('aria-selected', String(buttonIndex === index));
+ });
+ panels.forEach((panel, panelIndex) => panel.classList.toggle('active', panelIndex === index));
+ this.engine?.redraw();
+ };
+ selectors.forEach((button, index) => {
+ button.addEventListener('click', () => select(index), { signal: this.controller.signal });
+ });
+ delegate.addEventListener(
+ 'click',
+ () => {
+ this.pulseStarted = performance.now();
+ this.engine?.redraw();
+ },
+ { signal: this.controller.signal },
+ );
+ }
+
+ disconnectedCallback() {
+ this.controller.abort();
+ this.engine?.destroy();
+ }
+
+ private draw(context: CanvasRenderingContext2D, width: number, height: number, elapsed: number) {
+ context.clearRect(0, 0, width, height);
+ const marginX = Math.min(70, width * 0.1);
+ const marginY = Math.min(55, height * 0.12);
+ const point = (node: ControlNode) => ({
+ x: marginX + node.x * (width - marginX * 2),
+ y: marginY + node.y * (height - marginY * 2),
+ });
+ const hub = { x: width / 2, y: height / 2 };
+ const line = (
+ from: { x: number; y: number },
+ to: { x: number; y: number },
+ color = 'rgba(244,242,238,.18)',
+ lineWidth = 1,
+ ) => {
+ context.beginPath();
+ context.moveTo(from.x, from.y);
+ context.lineTo(to.x, to.y);
+ context.strokeStyle = color;
+ context.lineWidth = lineWidth;
+ context.stroke();
+ };
+
+ CRDS.forEach((node) => line(hub, point(node)));
+ RUNTIME.forEach((runtime) => {
+ const target = point(runtime);
+ const source =
+ runtime.label === 'agent pods'
+ ? point(CRDS[0])
+ : runtime.label === 'gateway'
+ ? point(CRDS[4])
+ : point(CRDS[3]);
+ line(source, target, 'rgba(94,230,160,.28)');
+ });
+
+ const drawNode = (node: ControlNode, index: number, runtime = false) => {
+ const position = point(node);
+ const active = !runtime && index === this.selected;
+ context.beginPath();
+ context.arc(position.x, position.y, runtime ? 5 : active ? 10 : 7, 0, Math.PI * 2);
+ context.fillStyle = active ? '#5ee6a0' : runtime ? 'rgba(94,230,160,.8)' : '#f4f2ee';
+ context.fill();
+ context.font = `${runtime ? 10 : 11}px Geist Mono, monospace`;
+ context.fillStyle = runtime
+ ? 'rgba(244,242,238,.52)'
+ : active
+ ? '#5ee6a0'
+ : 'rgba(244,242,238,.78)';
+ context.textAlign = 'center';
+ context.fillText(node.label, position.x, position.y + (runtime ? 19 : 23));
+ };
+ CRDS.forEach((node, index) => drawNode(node, index));
+ RUNTIME.forEach((node, index) => drawNode(node, index, true));
+
+ context.beginPath();
+ context.arc(hub.x, hub.y, 29, 0, Math.PI * 2);
+ context.fillStyle = '#171818';
+ context.fill();
+ context.strokeStyle = 'rgba(94,230,160,.7)';
+ context.stroke();
+ context.fillStyle = '#f4f2ee';
+ context.font = '11px Geist Mono, monospace';
+ context.textAlign = 'center';
+ context.fillText('operator', hub.x, hub.y + 4);
+
+ if (this.pulseStarted < 0) return;
+ const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
+ const progress = reduced ? 1 : Math.min(1, (performance.now() - this.pulseStarted) / 1400);
+ const agent = point(CRDS[0]);
+ const mcp = point(CRDS[2]);
+ const peer = { x: agent.x + 72, y: agent.y + 18 };
+ line(agent, mcp, 'rgba(94,230,160,.9)', 2);
+ line(agent, peer, 'rgba(74,199,255,.9)', 2);
+ [mcp, peer].forEach((target, index) => {
+ const p = reduced ? 1 : Math.max(0, Math.min(1, progress * 1.45 - index * 0.3));
+ context.beginPath();
+ context.arc(
+ agent.x + (target.x - agent.x) * p,
+ agent.y + (target.y - agent.y) * p,
+ 4,
+ 0,
+ Math.PI * 2,
+ );
+ context.fillStyle = index ? '#4ac7ff' : '#5ee6a0';
+ context.fill();
+ });
+ if (progress >= 1 && !reduced) this.pulseStarted = -1;
+ void elapsed;
+ }
+}
+
+if (!customElements.get('control-plane-map'))
+ customElements.define('control-plane-map', ControlPlaneMap);
diff --git a/src/shared/canvas/HeroCycle.ts b/src/shared/canvas/HeroCycle.ts
index 294e7a94..b693025f 100644
--- a/src/shared/canvas/HeroCycle.ts
+++ b/src/shared/canvas/HeroCycle.ts
@@ -53,6 +53,11 @@ export class HeroCycle extends HTMLElement {
private context?: CanvasRenderingContext2D;
private controller = new AbortController();
private graph?: { nodes: GraphNode[]; edges: GraphEdge[] };
+ private heroCopy?: HTMLElement;
+ private parallaxFrame = 0;
+ private scrollCurrent = 0;
+ private scrollProgress = 0;
+ private variant = 1;
private height = 0;
private host?: HTMLElement;
private lastPointer?: { x: number; y: number };
@@ -84,6 +89,11 @@ export class HeroCycle extends HTMLElement {
undefined;
this.context = this.canvas?.getContext('2d') ?? undefined;
if (!this.canvas || !this.context || !this.host) return;
+ this.heroCopy = this.host.querySelector('.hero-copy') ?? undefined;
+ // Parallax comparator: ?v=1 none · ?v=2 pinned hero · ?v=3 background trail ·
+ // ?v=4 shared drift + expansion · ?v=5 v4 + defocus · ?v=6 pinned object growing.
+ const requested = Number(new URLSearchParams(location.search).get('v') ?? '1');
+ this.variant = requested >= 1 && requested <= 6 ? Math.floor(requested) : 1;
this.buttons = Array.from(this.host.querySelectorAll('[data-hero-mode]'));
this.buttons.forEach((button) =>
@@ -103,15 +113,84 @@ export class HeroCycle extends HTMLElement {
this.fit();
this.draw(0);
this.resizeObserver.observe(this.canvas);
- if (!this.reducedMotion) this.animationFrame = requestAnimationFrame(this.loop);
+ if (!this.reducedMotion) {
+ this.animationFrame = requestAnimationFrame(this.loop);
+ if (this.variant > 1) {
+ this.scrollCurrent = window.scrollY;
+ addEventListener('scroll', this.handleParallax, { passive: true, signal: this.controller.signal });
+ this.handleParallax();
+ }
+ }
}
disconnectedCallback() {
cancelAnimationFrame(this.animationFrame);
+ cancelAnimationFrame(this.parallaxFrame);
this.controller.abort();
this.resizeObserver?.disconnect();
}
+ private handleParallax = () => {
+ if (this.parallaxFrame) return;
+ this.parallaxFrame = requestAnimationFrame(() => {
+ this.parallaxFrame = 0;
+ if (!this.canvas || !this.host) return;
+ // Variants 4/5 ease toward the scroll position instead of snapping to it: the
+ // one-frame desync of main-thread transforms against compositor scrolling (worst
+ // in Firefox) is absorbed into a deliberate inertial glide. The chain keeps
+ // animating after scroll events stop until the eased value settles.
+ const smoothed = this.variant >= 4 && this.variant <= 5;
+ const target = window.scrollY;
+ this.scrollCurrent = smoothed ? this.scrollCurrent + (target - this.scrollCurrent) * 0.28 : target;
+ if (smoothed && Math.abs(target - this.scrollCurrent) > 0.4) this.handleParallax();
+ const scrolled = this.scrollCurrent;
+ const heroHeight = this.host.offsetHeight || 1;
+ const pin = Math.min(scrolled, heroHeight);
+ const progress = pin / heroHeight;
+ const fade = (over: number) => `${Math.max(0, 1 - scrolled / (heroHeight * over))}`;
+ const copy = this.heroCopy;
+ if (this.variant === 2) {
+ // Pinned hero: both layers counter-scrolled at the full rate, copy fades away.
+ this.canvas.style.transform = `translate3d(0, ${pin}px, 0)`;
+ if (copy) {
+ copy.style.transform = `translate3d(0, ${pin}px, 0)`;
+ copy.style.opacity = fade(0.9);
+ }
+ } else if (this.variant === 3) {
+ // Background trail: canvas lags the scroll slightly, copy scrolls normally.
+ this.canvas.style.transform = `translate3d(0, ${pin * 0.2}px, 0)`;
+ } else if (this.variant === 4) {
+ // Shared drift + expansion: both layers drift down together; within that motion
+ // the background dollies bigger (see draw) and pushes the copy left, growing it.
+ this.scrollProgress = progress;
+ this.canvas.style.transform = `translate3d(0, ${pin * 0.8}px, 0)`;
+ this.canvas.style.opacity = fade(1.2);
+ if (copy) {
+ copy.style.transform = `translate3d(${pin * -0.35}px, ${pin * 0.8}px, 0) scale(${1 + progress * 0.16})`;
+ copy.style.opacity = fade(0.9);
+ }
+ } else if (this.variant === 5) {
+ // Variant 4 plus defocus: the same shared drift and expansion, with the whole
+ // hero slipping out of focus as it goes. The copy's blur trails the object's so
+ // the text stays legible slightly longer.
+ this.scrollProgress = progress;
+ this.canvas.style.transform = `translate3d(0, ${pin * 0.8}px, 0)`;
+ this.canvas.style.filter = `blur(${(progress * 7).toFixed(2)}px)`;
+ this.canvas.style.opacity = fade(1.2);
+ if (copy) {
+ copy.style.transform = `translate3d(${pin * -0.35}px, ${pin * 0.8}px, 0) scale(${1 + progress * 0.16})`;
+ copy.style.filter = `blur(${(Math.max(0, progress - 0.12) * 6).toFixed(2)}px)`;
+ copy.style.opacity = fade(0.9);
+ }
+ } else if (this.variant === 6) {
+ // No exit effects: the 3D object simply holds its place and grows via the camera
+ // dolly while the page (copy included) scrolls past normally.
+ this.scrollProgress = progress;
+ this.canvas.style.transform = `translate3d(0, ${pin}px, 0)`;
+ }
+ });
+ };
+
private draw(elapsed: number) {
const context = this.context!;
const delta = Math.max(0, Math.min(0.05, elapsed - this.state.last));
@@ -175,8 +254,10 @@ export class HeroCycle extends HTMLElement {
this.paint(mode, bufferContext, this.width, this.height, elapsed);
bufferContext.restore();
};
- layer(this.state.current, 1 - mix, 1 + mix * 0.16);
- if (this.state.next) layer(this.state.next, mix, 0.86 + mix * 0.14);
+ // Variants 4 and 5: the camera pulls back as you scroll, growing the projection.
+ const dolly = this.variant >= 4 ? 1 + this.scrollProgress * 0.35 : 1;
+ layer(this.state.current, 1 - mix, (1 + mix * 0.16) * dolly);
+ if (this.state.next) layer(this.state.next, mix, (0.86 + mix * 0.14) * dolly);
context.clearRect(0, 0, this.width, this.height);
if (tear < 0.02) {
diff --git a/src/styles/tokens.css b/src/styles/tokens.css
index ad281f04..a0e98bdd 100644
--- a/src/styles/tokens.css
+++ b/src/styles/tokens.css
@@ -187,7 +187,7 @@ button.nav-trigger {
[aria-expanded="true"] .caret { transform: rotate(180deg); }
.join-pill {
border: 1px solid rgba(94, 230, 160, .45);
- border-radius: var(--radius-pill);
+ border-radius: var(--radius-control);
color: var(--accent);
font-family: var(--font-mono);
font-size: var(--mono-10-5);
@@ -283,11 +283,13 @@ button.nav-trigger {
right: 0;
top: 0;
width: 66%;
+ will-change: transform;
}
.hero-copy {
max-width: 660px;
padding: 92px 0;
position: relative;
+ will-change: transform, opacity;
z-index: 2;
}
.status-pill {
@@ -703,7 +705,7 @@ dd { margin: 6px 0 0; }
}
.metrics-block {
display: grid;
- grid-template-columns: repeat(3, 1fr);
+ grid-template-columns: repeat(var(--metric-count, 3), 1fr);
margin-top: 20px;
}
.metrics-block div {
@@ -1336,8 +1338,7 @@ main > .home-section:last-child { padding-bottom: 120px; }
.oss-menu-list > a.active span { color: var(--accent); }
.oss-menu-list strong { font-size: 15.5px; font-weight: 400; margin-top: 4px; }
.oss-menu-list small { color: rgba(244,242,238,.55); font-size: 12.5px; line-height: 1.45; margin-top: 2px; }
-.oss-menu-list footer { border-top: 1px solid rgba(255,255,255,.08); display: flex; flex-direction: column; font: 9.5px/1.4 var(--font-mono); gap: 8px; letter-spacing: .14em; margin-top: 16px; padding: 16px 12px 0; }
-.oss-menu-list footer a { color: rgba(244,242,238,.5); }
+.oss-menu-list footer { align-items: flex-start; border-top: 1px solid rgba(255,255,255,.08); display: flex; flex-direction: column; font: 9.5px/1.4 var(--font-mono); gap: 8px; letter-spacing: .14em; margin-top: 16px; padding: 16px 12px 0; }
.oss-menu-preview { background: var(--bg-inset); min-height: 300px; overflow: hidden; position: relative; }
.oss-menu-preview canvas { height: 100%; inset: 0; position: absolute; width: 100%; }
.oss-menu-preview p { bottom: 22px; display: flex; flex-direction: column; gap: 4px; left: 26px; margin: 0; position: absolute; right: 26px; }
@@ -1381,7 +1382,15 @@ main > .home-section:last-child { padding-bottom: 120px; }
.article-hero h1 { font: 300 clamp(54px, 7vw, 88px)/.98 var(--font-display); letter-spacing: -.025em; margin: 24px 0; max-width: 960px; }
.article-hero > p:last-child { color: var(--text-2); font-size: 18px; line-height: 1.6; max-width: 680px; }
.article-hero.canvas-variant { min-height: 650px; overflow: hidden; }
-.article-hero.canvas-variant > *:not(canvas) { position: relative; z-index: 2; }
+.article-hero.canvas-variant.kompute-variant::after {
+ background: linear-gradient(90deg, rgba(15, 16, 15, .92) 0%, rgba(15, 16, 15, .7) 42%, transparent 76%);
+ content: '';
+ inset: 0;
+ pointer-events: none;
+ position: absolute;
+ z-index: 1;
+}
+.article-hero.canvas-variant > :not(canvas, .kaos-canvas-mount, .kompute-canvas-mount) { position: relative; z-index: 2; }
.article-hero.canvas-variant .hero-canvas { opacity: .85; }
.article-hero.canvas-variant > .kaos-canvas-mount {
height: min(500px, 100%);
@@ -1392,6 +1401,14 @@ main > .home-section:last-child { padding-bottom: 120px; }
transform: translateY(-50%);
z-index: 0;
}
+.article-hero.canvas-variant > .kompute-canvas-mount {
+ height: 100%;
+ inset: 0;
+ opacity: .58;
+ position: absolute;
+ z-index: 0;
+}
+.article-hero.canvas-variant > .kompute-canvas-mount canvas { height: 100%; width: 100%; }
.section-intro { color: var(--text-2); line-height: 1.6; max-width: 560px; }
.principles-explorer { display: block; }
diff --git a/src/utils/external-links.mjs b/src/utils/external-links.mjs
new file mode 100644
index 00000000..1a6ac660
--- /dev/null
+++ b/src/utils/external-links.mjs
@@ -0,0 +1,12 @@
+export const INSTITUTE_HOST = 'ethical.institute';
+
+export function isExternalHref(href) {
+ if (typeof href !== 'string' || !/^https?:\/\//i.test(href)) return false;
+
+ try {
+ const host = new URL(href).hostname.toLowerCase();
+ return host !== INSTITUTE_HOST && !host.endsWith(`.${INSTITUTE_HOST}`);
+ } catch {
+ return false;
+ }
+}