diff --git a/src/content/docs/concepts/agentic-engineering/assets.json b/src/content/docs/concepts/agentic-engineering/assets.json new file mode 100644 index 00000000..4088da2d --- /dev/null +++ b/src/content/docs/concepts/agentic-engineering/assets.json @@ -0,0 +1,10 @@ +{ + "conceptMap": { + "type": "graph", + "graphId": "graph.agentic-engineering-concept-map", + "webRenderer": "react-flow", + "printRenderer": "vertical-svg", + "altKey": "assets.conceptMap.alt", + "captionKey": "assets.conceptMap.caption" + } +} diff --git a/src/content/docs/concepts/agentic-engineering/messages/en.json b/src/content/docs/concepts/agentic-engineering/messages/en.json new file mode 100644 index 00000000..35f2cfe3 --- /dev/null +++ b/src/content/docs/concepts/agentic-engineering/messages/en.json @@ -0,0 +1,46 @@ +{ + "title": "Agentic Engineering", + "description": "A concept page that explains the shift from one-shot code generation to longer-running software agents that plan, act, and recover over many steps.", + "openingSummary": "Agentic engineering means treating software work as a multi-step loop where the model plans, runs tools, reads feedback, and revises over time. The key difference from vibe coding is that the hard part is no longer one answer, but keeping a long trajectory coherent enough to finish real work.", + "sections": { + "whatItIs": { + "title": "What It Is", + "body": "Agentic engineering is a broad term for using models as persistent workers rather than as one-turn autocomplete. The model must remember goals, inspect files or web pages, call tools, react to failures, and keep making progress over many steps." + }, + "whyItMatters": { + "title": "Why It Matters", + "body": "Long-horizon coding tasks break many systems that look strong in short prompts. Once the task lasts minutes or hours, the quality bottlenecks move toward planning, error recovery, and trajectory management, which is why GLM-5 centers the term instead of treating it as marketing language." + }, + "simpleExample": { + "title": "Simple Example", + "body": "A coding agent that debugs a failing test suite is doing agentic engineering when it can inspect the failure, edit files, rerun checks, and recover from dead ends. In the GLM-5 bundle, Asynchronous Agent Reinforcement Learning teaches that behavior while the slime Rollout Framework keeps the experiments flowing." + }, + "commonConfusions": { + "title": "Common Confusions", + "body": "Agentic engineering does not simply mean adding tools to a chatbot. The idea is broader: the model, the training loop, and the rollout system must all support long trajectories. That is why the GLM-5 paper, the GLM-5 model page, the asynchronous RL page, and the slime page should be read together." + }, + "related": { + "title": "Related Reference Pages" + }, + "tags": { + "title": "Tags" + }, + "references": { + "title": "References" + } + }, + "assets": { + "conceptMap": { + "alt": "A concept map linking agentic engineering to long-horizon tasks, asynchronous RL, and the slime rollout system.", + "caption": "The term only makes sense when the behavior loop, the trainer loop, and the runtime loop all stay in view." + } + }, + "graph": { + "nodes": { + "agenticEngineering": { "label": "Agentic engineering" }, + "longHorizon": { "label": "Long-horizon tasks" }, + "asyncRl": { "label": "Async agent RL" }, + "slime": { "label": "slime framework" } + } + } +} diff --git a/src/content/docs/concepts/agentic-engineering/page.mdx b/src/content/docs/concepts/agentic-engineering/page.mdx new file mode 100644 index 00000000..4c3ba7a9 --- /dev/null +++ b/src/content/docs/concepts/agentic-engineering/page.mdx @@ -0,0 +1,64 @@ +--- +title: "Agentic Engineering" +description: "A concept page that explains the shift from one-shot code generation to longer-running software agents that plan, act, and recover over many steps." +kind: "concept" +registryId: "concept.agentic-engineering" +messageNamespace: "local" +assetNamespace: "local" +status: "published" +tags: + - foundations + - model-family +aliases: + - "agentic engineering" + - "coding agents" + - "software engineering agents" +updatedAt: "2026-06-19" +--- + +import { CitationList } from "@/features/docs/components/CitationList"; +import { DerivedRelatedDocs } from "@/features/docs/components/DerivedRelatedDocs"; +import { RelatedDocs } from "@/features/docs/components/RelatedDocs"; +import { Section } from "@/features/docs/components/Section"; +import { T } from "@/features/docs/components/T"; +import { TagPillList } from "@/features/docs/components/TagPillList"; +import { ConceptMap } from "@/features/models/components/ConceptMap"; + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + +
+ +
+ +
+ +
diff --git a/src/content/docs/models/glm-5/assets.json b/src/content/docs/models/glm-5/assets.json new file mode 100644 index 00000000..8e6c0b09 --- /dev/null +++ b/src/content/docs/models/glm-5/assets.json @@ -0,0 +1,10 @@ +{ + "architectureGraph": { + "type": "graph", + "graphId": "graph.glm-5-architecture", + "webRenderer": "react-flow", + "printRenderer": "vertical-svg", + "altKey": "assets.architectureGraph.alt", + "captionKey": "assets.architectureGraph.caption" + } +} diff --git a/src/content/docs/models/glm-5/messages/en.json b/src/content/docs/models/glm-5/messages/en.json new file mode 100644 index 00000000..f80a8e30 --- /dev/null +++ b/src/content/docs/models/glm-5/messages/en.json @@ -0,0 +1,66 @@ +{ + "title": "GLM-5", + "description": "A model page for the GLM-5 release that explains its sparse MoE shape, long-context attention choices, and linked training and rollout systems.", + "openingSummary": "GLM-5 is a large coding-focused model family built around sparse expert routing, long-context attention efficiency, and post-training meant for long-running agents. The key reader payoff is seeing how the model, its asynchronous RL recipe, and the slime rollout stack fit together without reading the whole paper first.", + "sections": { + "whatItIs": { + "title": "What It Is", + "body": "GLM-5 is the flagship model release described in the GLM-5 paper from Zhipu AI. It is best understood as a sparse MoE language model tuned for coding, reasoning, and agent-style workflows rather than as a small architectural tweak on its own." + }, + "inputsAndOutputs": { + "title": "Inputs And Outputs", + "body": "The public paper frames GLM-5 as a text model for long-context reasoning and software engineering tasks. In practice, the important interface is not only next-token generation but also the ability to sustain longer tool-using trajectories with fewer costly stalls." + }, + "architecture": { + "title": "Architecture", + "body": "The release combines a sparse expert backbone with long-context attention choices borrowed from the nearby Multi-head Latent Attention and Sparse Attention family discussions. The paper also reports a 744B-parameter model with 40B active parameters, 256 experts, and design choices meant to keep long-context coding practical instead of purely maximal." + }, + "importantModules": { + "title": "Important Modules", + "body": "The nearby module pages matter because GLM-5 is not explained by a single proprietary block. Multi-head Latent Attention, Sparse Attention, Mixture of Experts, and RMSNorm give the cleanest public view of the efficiency and backbone choices around the release." + }, + "training": { + "title": "Training", + "body": "The model page links directly to Asynchronous Agent Reinforcement Learning for the algorithmic post-training loop and back to the GLM-5 paper for the broader recipe. On-Policy Distillation remains relevant as a nearby existing regime because GLM-5 still treats knowledge retention across post-training stages as a first-class concern." + }, + "practicalNotes": { + "title": "Practical Notes", + "body": "Readers should treat GLM-5 as a release bundle, not a single canonical module. If you want the broad product shift, open Agentic Engineering; if you want the trainer loop, open Asynchronous Agent Reinforcement Learning; if you want the runtime layer, open the slime Rollout Framework." + }, + "related": { + "title": "Related Reference Pages" + }, + "tags": { + "title": "Tags" + }, + "references": { + "title": "References" + } + }, + "assets": { + "architectureGraph": { + "alt": "A compact architecture sketch for GLM-5 showing the model root connected to MoE backbone, long-context attention, and asynchronous post-training.", + "caption": "This page emphasizes three teaching layers: sparse backbone, long-context attention, and agent-focused post-training." + } + }, + "graph": { + "nodes": { + "glm5": { + "label": "GLM-5", + "summary": "A coding-focused sparse MoE release." + }, + "moeBackbone": { + "label": "MoE backbone", + "summary": "Sparse experts increase capacity without activating all parameters at once." + }, + "longContext": { + "label": "Long-context attention", + "summary": "Nearby attention variants explain the efficiency story around the release." + }, + "postTraining": { + "label": "Async post-training", + "summary": "Agent RL and rollout systems are part of the model story, not an afterthought." + } + } + } +} diff --git a/src/content/docs/models/glm-5/page.mdx b/src/content/docs/models/glm-5/page.mdx new file mode 100644 index 00000000..d1fd0141 --- /dev/null +++ b/src/content/docs/models/glm-5/page.mdx @@ -0,0 +1,78 @@ +--- +title: "GLM-5" +description: "A model page for the GLM-5 release that explains its sparse MoE shape, long-context attention choices, and linked training and rollout systems." +kind: "model" +registryId: "model.glm-5" +messageNamespace: "local" +assetNamespace: "local" +status: "published" +tags: + - foundations + - context-window + - model-family +aliases: + - "GLM-5" + - "GLM 5" +updatedAt: "2026-06-19" +--- + +import { CitationList } from "@/features/docs/components/CitationList"; +import { DerivedRelatedDocs } from "@/features/docs/components/DerivedRelatedDocs"; +import { Section } from "@/features/docs/components/Section"; +import { T } from "@/features/docs/components/T"; +import { TagPillList } from "@/features/docs/components/TagPillList"; +import { ModelArchitectureGraph } from "@/features/models/components/ModelArchitectureGraph"; +import { ModelAtAGlance } from "@/features/models/components/ModelAtAGlance"; +import { ModelModuleList } from "@/features/models/components/ModelModuleList"; +import { ModelTrainingSummary } from "@/features/models/components/ModelTrainingSummary"; + + + + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + + +
+ +
+ +
+ +
diff --git a/src/content/docs/papers/glm-5/assets.json b/src/content/docs/papers/glm-5/assets.json new file mode 100644 index 00000000..7fc82939 --- /dev/null +++ b/src/content/docs/papers/glm-5/assets.json @@ -0,0 +1,10 @@ +{ + "contributionGraph": { + "type": "graph", + "graphId": "graph.glm-5-contribution", + "webRenderer": "react-flow", + "printRenderer": "vertical-svg", + "altKey": "assets.contributionGraph.alt", + "captionKey": "assets.contributionGraph.caption" + } +} diff --git a/src/content/docs/papers/glm-5/messages/en.json b/src/content/docs/papers/glm-5/messages/en.json new file mode 100644 index 00000000..3f3dbbcd --- /dev/null +++ b/src/content/docs/papers/glm-5/messages/en.json @@ -0,0 +1,55 @@ +{ + "title": "GLM-5: from Vibe Coding to Agentic Engineering", + "description": "A paper page that breaks GLM-5 into its model, agent-training, and rollout-system contributions so readers can navigate the release without reading the full report first.", + "openingSummary": "GLM-5 matters because it treats coding agents as long-running systems rather than one-shot code generators. The paper combines a large sparse MoE model, asynchronous agent reinforcement learning, and the slime rollout framework into one practical story about making agentic engineering work at scale.", + "sections": { + "whatThePaperIntroduced": { + "title": "What The Paper Introduced", + "body": "The report introduces the GLM-5 model page, the Agentic Engineering concept, Asynchronous Agent Reinforcement Learning, and the slime Rollout Framework as one connected bundle. It also anchors GLM-5 to nearby reference pages such as Multi-head Latent Attention, Sparse Attention, and On-Policy Distillation so readers can move from the flagship release into the reusable parts." + }, + "whyItMatters": { + "title": "Why It Matters", + "body": "Many model reports describe one model and then leave the training and runtime story scattered across appendices. GLM-5 matters because it argues that real coding agents need all three layers at once: a capable base model, a post-training loop that can learn from long trajectories, and a rollout stack that keeps those trajectories flowing." + }, + "methodOrArchitecture": { + "title": "Method Or Architecture", + "body": "At a high level, GLM-5 keeps a large MoE language model but pushes harder on long-context efficiency and agent post-training. The model route is GLM-5, the broad idea is Agentic Engineering, the post-training algorithm is Asynchronous Agent Reinforcement Learning, and the rollout substrate is the slime Rollout Framework." + }, + "evidence": { + "title": "Evidence", + "body": "For this reference page, the useful evidence is not the leaderboard table itself. The important signal is that the paper reports stronger long-horizon coding behavior after pairing asynchronous rollout generation, filtered trajectory updates, and a rollout framework tuned for tail latency and fault tolerance." + }, + "limitations": { + "title": "Limitations", + "body": "The paper is broad, so some claims are stack-level rather than clean single-variable proofs. Readers should treat the release as evidence for a combined recipe, not as a guarantee that every isolated ingredient always transfers unchanged to other agent stacks." + }, + "whatItConnectsTo": { + "title": "What It Connects To", + "body": "This record map is the fastest way to jump from the report into the canonical pages it introduced and the nearby existing references it depends on." + }, + "related": { + "title": "Related Reference Pages" + }, + "tags": { + "title": "Tags" + }, + "references": { + "title": "References" + } + }, + "assets": { + "contributionGraph": { + "alt": "A contribution map that splits GLM-5 into architecture, asynchronous training, rollout systems, and agentic engineering.", + "caption": "GLM-5 reads best as four connected branches: model architecture, asynchronous training, rollout infrastructure, and the broader shift toward agentic engineering." + } + }, + "graph": { + "nodes": { + "paper": { "label": "GLM-5 report" }, + "architecture": { "label": "Model architecture" }, + "training": { "label": "Async agent RL" }, + "systems": { "label": "slime rollout stack" }, + "agentic": { "label": "Agentic engineering" } + } + } +} diff --git a/src/content/docs/papers/glm-5/page.mdx b/src/content/docs/papers/glm-5/page.mdx new file mode 100644 index 00000000..c450533c --- /dev/null +++ b/src/content/docs/papers/glm-5/page.mdx @@ -0,0 +1,84 @@ +--- +title: "GLM-5: from Vibe Coding to Agentic Engineering" +description: "A paper page that breaks GLM-5 into its model, agent-training, and rollout-system contributions so readers can navigate the release without reading the full report first." +kind: "paper" +registryId: "paper.glm-5" +messageNamespace: "local" +assetNamespace: "local" +status: "published" +tags: + - foundations + - context-window + - model-family +aliases: + - "GLM-5" + - "GLM-5: from Vibe Coding to Agentic Engineering" +updatedAt: "2026-06-19" +--- + +import { CitationList } from "@/features/docs/components/CitationList"; +import { DerivedRelatedDocs } from "@/features/docs/components/DerivedRelatedDocs"; +import { RegistryAssociatedRecords } from "@/features/docs/components/RegistryAssociatedRecords"; +import { RelatedDocs } from "@/features/docs/components/RelatedDocs"; +import { Section } from "@/features/docs/components/Section"; +import { T } from "@/features/docs/components/T"; +import { TagPillList } from "@/features/docs/components/TagPillList"; +import { PaperContributionGraph } from "@/features/models/components/PaperContributionGraph"; +import { PaperAtAGlance } from "@/features/models/components/PaperAtAGlance"; + + + + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
+ +
+ +
+ +
diff --git a/src/content/docs/systems/slime-rollout-framework/assets.json b/src/content/docs/systems/slime-rollout-framework/assets.json new file mode 100644 index 00000000..46de6037 --- /dev/null +++ b/src/content/docs/systems/slime-rollout-framework/assets.json @@ -0,0 +1,10 @@ +{ + "systemFlow": { + "type": "graph", + "graphId": "graph.slime-rollout-framework-system-flow", + "webRenderer": "react-flow", + "printRenderer": "vertical-svg", + "altKey": "assets.systemFlow.alt", + "captionKey": "assets.systemFlow.caption" + } +} diff --git a/src/content/docs/systems/slime-rollout-framework/messages/en.json b/src/content/docs/systems/slime-rollout-framework/messages/en.json new file mode 100644 index 00000000..d26b25a5 --- /dev/null +++ b/src/content/docs/systems/slime-rollout-framework/messages/en.json @@ -0,0 +1,49 @@ +{ + "title": "slime Rollout Framework", + "description": "A system page that explains the rollout infrastructure GLM-5 uses to run customizable, latency-sensitive, and fault-tolerant agent trajectories at scale.", + "openingSummary": "The slime rollout framework matters because long-horizon agent training is often blocked by runtime behavior, not by the optimizer alone. slime provides the rollout-side machinery for customizable tasks, tail-latency control, and heartbeat-based recovery so asynchronous agent training can stay productive instead of spending most of its time waiting.", + "sections": { + "whatItIs": { + "title": "What It Is", + "body": "slime is the rollout framework GLM-5 uses for reinforcement-learning style agent training. It is not the learning rule itself; it is the runtime layer that serves environments, executes tool-rich trajectories, and keeps rollout traffic moving across many workers." + }, + "whereItSits": { + "title": "Where It Sits", + "body": "This system sits between the model and the trainer. The model still decides what action to take, and Asynchronous Agent Reinforcement Learning still decides how updates are computed, but slime is the layer that actually makes large rollout batches feasible." + }, + "howItWorks": { + "title": "How It Works", + "body": "The GLM-5 paper highlights three ideas: highly customizable rollouts for many task types, latency-oriented scheduling to reduce tail stalls, and heartbeat-driven fault tolerance so dead or unhealthy rollout servers do not silently poison progress. The page keeps those runtime concerns here instead of duplicating the full training thesis from the asynchronous RL page." + }, + "practicalImpact": { + "title": "Practical Impact", + "body": "The practical payoff is more usable agent data per unit time. When long or tool-heavy trajectories stop clogging the pipeline, researchers can run more experiments and trainers spend less time waiting for the slowest sample." + }, + "associatedRecords": { + "title": "Associated Records" + }, + "related": { + "title": "Related Reference Pages" + }, + "tags": { + "title": "Tags" + }, + "references": { + "title": "References" + } + }, + "assets": { + "systemFlow": { + "alt": "A system flow where the slime framework coordinates custom rollouts, scheduling, and heartbeat supervision.", + "caption": "slime is easiest to understand as runtime glue for customizable rollouts, tail-latency control, and fault recovery." + } + }, + "graph": { + "nodes": { + "slime": { "label": "slime framework" }, + "customRollouts": { "label": "Custom rollouts" }, + "scheduler": { "label": "Latency-aware scheduler" }, + "heartbeat": { "label": "Heartbeat recovery" } + } + } +} diff --git a/src/content/docs/systems/slime-rollout-framework/page.mdx b/src/content/docs/systems/slime-rollout-framework/page.mdx new file mode 100644 index 00000000..7c885a0d --- /dev/null +++ b/src/content/docs/systems/slime-rollout-framework/page.mdx @@ -0,0 +1,43 @@ +--- +title: "slime Rollout Framework" +description: "A system page that explains the rollout infrastructure GLM-5 uses to run customizable, latency-sensitive, and fault-tolerant agent trajectories at scale." +kind: "system" +registryId: "system.slime-rollout-framework" +messageNamespace: "local" +assetNamespace: "local" +status: "published" +tags: + - foundations + - kv-cache +aliases: + - "slime" + - "slime framework" + - "slime rollout framework" +updatedAt: "2026-06-19" +--- + +import { CitationList } from "@/features/docs/components/CitationList"; +import { DerivedRelatedDocs } from "@/features/docs/components/DerivedRelatedDocs"; +import { RegistryAssociatedRecords } from "@/features/docs/components/RegistryAssociatedRecords"; +import { Section } from "@/features/docs/components/Section"; +import { T } from "@/features/docs/components/T"; +import { TagPillList } from "@/features/docs/components/TagPillList"; +import { SystemAtAGlance } from "@/features/models/components/SystemAtAGlance"; +import { SystemFlowGraph } from "@/features/models/components/SystemFlowGraph"; + + + + +
+
+
+
+
+ +
+
diff --git a/src/content/docs/training/asynchronous-agent-reinforcement-learning/assets.json b/src/content/docs/training/asynchronous-agent-reinforcement-learning/assets.json new file mode 100644 index 00000000..8d65f0f8 --- /dev/null +++ b/src/content/docs/training/asynchronous-agent-reinforcement-learning/assets.json @@ -0,0 +1,10 @@ +{ + "trainingFlow": { + "type": "graph", + "graphId": "graph.asynchronous-agent-reinforcement-learning-training-flow", + "webRenderer": "react-flow", + "printRenderer": "vertical-svg", + "altKey": "assets.trainingFlow.alt", + "captionKey": "assets.trainingFlow.caption" + } +} diff --git a/src/content/docs/training/asynchronous-agent-reinforcement-learning/messages/en.json b/src/content/docs/training/asynchronous-agent-reinforcement-learning/messages/en.json new file mode 100644 index 00000000..5c5a87ed --- /dev/null +++ b/src/content/docs/training/asynchronous-agent-reinforcement-learning/messages/en.json @@ -0,0 +1,55 @@ +{ + "title": "Asynchronous Agent Reinforcement Learning", + "description": "A training-regime page that explains how GLM-5 separates rollout generation from model updates so agent trajectories can be gathered and filtered without a tight synchronous loop.", + "openingSummary": "Asynchronous agent reinforcement learning helps long-horizon agents because the slowest rollout no longer blocks every model update. The idea is to let generation and training move on partially separate clocks, then filter or reweight stale trajectories so learning stays stable enough to remain useful.", + "sections": { + "whatItIs": { + "title": "What It Is", + "body": "Asynchronous agent reinforcement learning is a post-training setup where rollout workers keep generating trajectories while trainers continue consuming buffered data. In the GLM-5 paper, this design is used for agentic tasks that are too long and irregular for a simple fully synchronous RL loop." + }, + "whatItOptimizes": { + "title": "What It Optimizes", + "body": "The main pressure is throughput on long, messy trajectories. Instead of letting one slow environment or one tail sample freeze the whole step, the asynchronous design tries to keep GPUs busy while still preserving enough policy freshness to learn from the right behaviors." + }, + "howItWorks": { + "title": "How It Works", + "body": "The paper describes a decoupled loop: rollout workers collect agent traces, a buffer holds them long enough for trainer consumption, and stability controls decide how much stale or noisy data to trust. Token-in-token-out training, importance-weighted clipping, and dropping off-policy or noisy samples are the core ideas on the algorithmic side, while the slime Rollout Framework handles the runtime side." + }, + "practicalBenefit": { + "title": "Practical Benefit", + "body": "The payoff is that the model can keep learning from long-horizon tasks without turning every training step into a global synchronization barrier. That matters for coding agents because the useful trajectories are often the longest and noisiest ones." + }, + "comparedToNearbyRegimes": { + "title": "Compared To Nearby Regimes", + "body": "Compared with more stage-bound or synchronous post-training, this regime makes freshness and filtering explicit tradeoffs instead of pretending every sample arrives on the same schedule. On-Policy Distillation is the closest nearby page for understanding how GLM-style post-training still cares about policy alignment and retention across stages." + }, + "modelsAndPapers": { + "title": "Models And Papers", + "body": "GLM-5 is the canonical model example for this page, and the GLM-5 paper is the primary source that motivates the regime." + }, + "limitationsAndFailureModes": { + "title": "Limitations And Failure Modes", + "body": "The extra throughput comes with a real risk of stale, off-policy, or simply bad trajectories. That is why the page distinguishes the algorithmic filtering story here from the rollout infrastructure story on the slime Rollout Framework page." + }, + "tags": { + "title": "Tags" + }, + "references": { + "title": "References" + } + }, + "assets": { + "trainingFlow": { + "alt": "A training flow where rollout workers feed a trajectory buffer, a trainer, and filtering logic on partially separate clocks.", + "caption": "The core teaching point is decoupling generation from updates without ignoring stale-sample risk." + } + }, + "graph": { + "nodes": { + "rolloutWorkers": { "label": "Rollout workers" }, + "trajectoryBuffer": { "label": "Trajectory buffer" }, + "trainer": { "label": "Trainer" }, + "filters": { "label": "Stability filters" } + } + } +} diff --git a/src/content/docs/training/asynchronous-agent-reinforcement-learning/page.mdx b/src/content/docs/training/asynchronous-agent-reinforcement-learning/page.mdx new file mode 100644 index 00000000..702163fd --- /dev/null +++ b/src/content/docs/training/asynchronous-agent-reinforcement-learning/page.mdx @@ -0,0 +1,70 @@ +--- +title: "Asynchronous Agent Reinforcement Learning" +description: "A training-regime page that explains how GLM-5 separates rollout generation from model updates so agent trajectories can be gathered and filtered without a tight synchronous loop." +kind: "training-regime" +registryId: "training-regime.asynchronous-agent-reinforcement-learning" +messageNamespace: "local" +assetNamespace: "local" +status: "published" +tags: + - foundations +aliases: + - "asynchronous agent reinforcement learning" + - "asynchronous agent RL" +updatedAt: "2026-06-19" +--- + +import { CitationList } from "@/features/docs/components/CitationList"; +import { DerivedRelatedDocs } from "@/features/docs/components/DerivedRelatedDocs"; +import { RelatedDocs } from "@/features/docs/components/RelatedDocs"; +import { RegistryAssociatedRecords } from "@/features/docs/components/RegistryAssociatedRecords"; +import { Section } from "@/features/docs/components/Section"; +import { T } from "@/features/docs/components/T"; +import { TagPillList } from "@/features/docs/components/TagPillList"; +import { TrainingRegimeFlow } from "@/features/models/components/TrainingRegimeFlow"; +import { TrainingRegimeAtAGlance } from "@/features/models/components/TrainingRegimeAtAGlance"; + + + + +
+ +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
diff --git a/src/content/registry/citations/glm-5-paper.json b/src/content/registry/citations/glm-5-paper.json new file mode 100644 index 00000000..2df36f3a --- /dev/null +++ b/src/content/registry/citations/glm-5-paper.json @@ -0,0 +1,20 @@ +{ + "id": "citation.glm-5-paper", + "slug": "glm-5-paper", + "kind": "citation", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["GLM-5 paper"], + "tags": ["foundations", "attention", "context-window", "model-family"], + "relatedIds": [], + "citationIds": [], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "citationType": "paper", + "authors": ["GLM-5 Team"], + "title": "GLM-5: from Vibe Coding to Agentic Engineering", + "url": "https://arxiv.org/abs/2602.15763", + "mla": "GLM-5 Team. \"GLM-5: from Vibe Coding to Agentic Engineering.\" arXiv, 2026.", + "year": 2026 +} diff --git a/src/content/registry/concepts/agentic-engineering.json b/src/content/registry/concepts/agentic-engineering.json new file mode 100644 index 00000000..0be69e9c --- /dev/null +++ b/src/content/registry/concepts/agentic-engineering.json @@ -0,0 +1,35 @@ +{ + "id": "concept.agentic-engineering", + "slug": "agentic-engineering", + "kind": "concept", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": [ + "agentic engineering", + "coding agents", + "software engineering agents" + ], + "tags": ["foundations", "model-family"], + "relatedIds": [ + "paper.glm-5", + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + "concept.transformer-architecture", + "training-regime.on-policy-distillation" + ], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "authors": ["GLM-5 Team"], + "sourceId": "paper.glm-5", + "releaseDate": "2026-02-17", + "conceptType": "systems", + "prerequisiteIds": ["concept.transformer-architecture"], + "explainsIds": [ + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework" + ] +} diff --git a/src/content/registry/graphs/agentic-engineering-concept-map.json b/src/content/registry/graphs/agentic-engineering-concept-map.json new file mode 100644 index 00000000..409d2f92 --- /dev/null +++ b/src/content/registry/graphs/agentic-engineering-concept-map.json @@ -0,0 +1,84 @@ +{ + "id": "graph.agentic-engineering-concept-map", + "slug": "agentic-engineering-concept-map", + "kind": "graph", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["agentic engineering concept map"], + "tags": ["foundations", "model-family"], + "relatedIds": [], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "subjectId": "concept.agentic-engineering", + "graphType": "concept-map", + "rootNodeId": "agentic-engineering", + "layout": "vertical-expandable", + "defaultExpandedDepth": 1, + "supportedRenderers": ["react-flow", "vertical-svg"], + "nodes": [ + { + "id": "agentic-engineering", + "labelKey": "graph.nodes.agenticEngineering.label", + "moduleKind": "other", + "position": { "x": 210, "y": 0 }, + "size": { "width": 240, "height": 72 }, + "visualRole": "summary-node", + "childNodeIds": ["long-horizon", "async-rl", "slime"] + }, + { + "id": "long-horizon", + "labelKey": "graph.nodes.longHorizon.label", + "moduleKind": "other", + "position": { "x": 0, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "async-rl", + "labelKey": "graph.nodes.asyncRl.label", + "moduleKind": "loss", + "position": { "x": 230, "y": 160 }, + "size": { "width": 220, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "slime", + "labelKey": "graph.nodes.slime.label", + "moduleKind": "other", + "position": { "x": 500, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + } + ], + "edges": [ + { + "id": "agentic-long-horizon", + "source": "agentic-engineering", + "target": "long-horizon", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "agentic-async-rl", + "source": "agentic-engineering", + "target": "async-rl", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "agentic-slime", + "source": "agentic-engineering", + "target": "slime", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + } + ] +} diff --git a/src/content/registry/graphs/asynchronous-agent-reinforcement-learning-training-flow.json b/src/content/registry/graphs/asynchronous-agent-reinforcement-learning-training-flow.json new file mode 100644 index 00000000..b0d055a1 --- /dev/null +++ b/src/content/registry/graphs/asynchronous-agent-reinforcement-learning-training-flow.json @@ -0,0 +1,84 @@ +{ + "id": "graph.asynchronous-agent-reinforcement-learning-training-flow", + "slug": "asynchronous-agent-reinforcement-learning-training-flow", + "kind": "graph", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["asynchronous agent RL training flow"], + "tags": ["foundations", "attention"], + "relatedIds": [], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "subjectId": "training-regime.asynchronous-agent-reinforcement-learning", + "graphType": "module-compute-flow", + "rootNodeId": "rollout-workers", + "layout": "vertical-expandable", + "defaultExpandedDepth": 1, + "supportedRenderers": ["react-flow", "vertical-svg"], + "nodes": [ + { + "id": "rollout-workers", + "labelKey": "graph.nodes.rolloutWorkers.label", + "moduleKind": "other", + "position": { "x": 210, "y": 0 }, + "size": { "width": 220, "height": 72 }, + "visualRole": "summary-node", + "childNodeIds": ["trajectory-buffer", "trainer", "filters"] + }, + { + "id": "trajectory-buffer", + "labelKey": "graph.nodes.trajectoryBuffer.label", + "moduleKind": "cache", + "position": { "x": 0, "y": 160 }, + "size": { "width": 190, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "trainer", + "labelKey": "graph.nodes.trainer.label", + "moduleKind": "loss", + "position": { "x": 250, "y": 160 }, + "size": { "width": 150, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "filters", + "labelKey": "graph.nodes.filters.label", + "moduleKind": "other", + "position": { "x": 460, "y": 160 }, + "size": { "width": 210, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + } + ], + "edges": [ + { + "id": "workers-buffer", + "source": "rollout-workers", + "target": "trajectory-buffer", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "buffer-trainer", + "source": "trajectory-buffer", + "target": "trainer", + "edgeKind": "data-flow", + "sourceHandleSide": "right", + "targetHandleSide": "left" + }, + { + "id": "workers-filters", + "source": "rollout-workers", + "target": "filters", + "edgeKind": "control-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + } + ] +} diff --git a/src/content/registry/graphs/glm-5-architecture.json b/src/content/registry/graphs/glm-5-architecture.json new file mode 100644 index 00000000..ef807102 --- /dev/null +++ b/src/content/registry/graphs/glm-5-architecture.json @@ -0,0 +1,92 @@ +{ + "id": "graph.glm-5-architecture", + "slug": "glm-5-architecture", + "kind": "graph", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["GLM-5 architecture graph"], + "tags": ["foundations", "attention", "model-family"], + "relatedIds": [], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "subjectId": "model.glm-5", + "graphType": "model-architecture", + "rootNodeId": "glm-5", + "layout": "vertical-expandable", + "defaultExpandedDepth": 1, + "supportedRenderers": ["react-flow", "vertical-svg"], + "nodes": [ + { + "id": "glm-5", + "labelKey": "graph.nodes.glm5.label", + "summaryKey": "graph.nodes.glm5.summary", + "registryId": "model.glm-5", + "moduleKind": "model", + "position": { "x": 220, "y": 0 }, + "size": { "width": 220, "height": 72 }, + "visualRole": "summary-node", + "childNodeIds": ["moe-backbone", "long-context", "post-training"] + }, + { + "id": "moe-backbone", + "labelKey": "graph.nodes.moeBackbone.label", + "summaryKey": "graph.nodes.moeBackbone.summary", + "registryId": "module.mixture-of-experts", + "moduleKind": "feed-forward", + "position": { "x": 0, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "architecture-feed-forward", + "childNodeIds": [] + }, + { + "id": "long-context", + "labelKey": "graph.nodes.longContext.label", + "summaryKey": "graph.nodes.longContext.summary", + "registryId": "module.multi-head-latent-attention", + "moduleKind": "attention", + "position": { "x": 220, "y": 160 }, + "size": { "width": 220, "height": 72 }, + "visualRole": "architecture-attention", + "childNodeIds": [] + }, + { + "id": "post-training", + "labelKey": "graph.nodes.postTraining.label", + "summaryKey": "graph.nodes.postTraining.summary", + "registryId": "training-regime.asynchronous-agent-reinforcement-learning", + "moduleKind": "loss", + "position": { "x": 470, "y": 160 }, + "size": { "width": 210, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + } + ], + "edges": [ + { + "id": "glm5-moe", + "source": "glm-5", + "target": "moe-backbone", + "edgeKind": "contains", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "glm5-long-context", + "source": "glm-5", + "target": "long-context", + "edgeKind": "contains", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "glm5-post-training", + "source": "glm-5", + "target": "post-training", + "edgeKind": "contains", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + } + ] +} diff --git a/src/content/registry/graphs/glm-5-contribution.json b/src/content/registry/graphs/glm-5-contribution.json new file mode 100644 index 00000000..41e70d23 --- /dev/null +++ b/src/content/registry/graphs/glm-5-contribution.json @@ -0,0 +1,101 @@ +{ + "id": "graph.glm-5-contribution", + "slug": "glm-5-contribution", + "kind": "graph", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["GLM-5 contribution graph"], + "tags": ["foundations", "attention"], + "relatedIds": [], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "subjectId": "paper.glm-5", + "graphType": "paper-contribution", + "rootNodeId": "paper", + "layout": "vertical-expandable", + "defaultExpandedDepth": 1, + "supportedRenderers": ["react-flow", "vertical-svg"], + "nodes": [ + { + "id": "paper", + "labelKey": "graph.nodes.paper.label", + "moduleKind": "other", + "position": { "x": 250, "y": 0 }, + "size": { "width": 240, "height": 72 }, + "visualRole": "summary-node", + "childNodeIds": ["architecture", "training", "systems", "agentic"] + }, + { + "id": "architecture", + "labelKey": "graph.nodes.architecture.label", + "moduleKind": "block", + "position": { "x": 0, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "training", + "labelKey": "graph.nodes.training.label", + "moduleKind": "loss", + "position": { "x": 210, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "systems", + "labelKey": "graph.nodes.systems.label", + "moduleKind": "other", + "position": { "x": 420, "y": 160 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "agentic", + "labelKey": "graph.nodes.agentic.label", + "moduleKind": "other", + "position": { "x": 210, "y": 280 }, + "size": { "width": 180, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + } + ], + "edges": [ + { + "id": "paper-architecture", + "source": "paper", + "target": "architecture", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "paper-training", + "source": "paper", + "target": "training", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "paper-systems", + "source": "paper", + "target": "systems", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "paper-agentic", + "source": "paper", + "target": "agentic", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + } + ] +} diff --git a/src/content/registry/graphs/slime-rollout-framework-system-flow.json b/src/content/registry/graphs/slime-rollout-framework-system-flow.json new file mode 100644 index 00000000..287b05b4 --- /dev/null +++ b/src/content/registry/graphs/slime-rollout-framework-system-flow.json @@ -0,0 +1,84 @@ +{ + "id": "graph.slime-rollout-framework-system-flow", + "slug": "slime-rollout-framework-system-flow", + "kind": "graph", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["slime rollout framework system flow"], + "tags": ["foundations", "kv-cache"], + "relatedIds": [], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "subjectId": "system.slime-rollout-framework", + "graphType": "module-compute-flow", + "rootNodeId": "slime", + "layout": "vertical-expandable", + "defaultExpandedDepth": 1, + "supportedRenderers": ["react-flow", "vertical-svg"], + "nodes": [ + { + "id": "slime", + "labelKey": "graph.nodes.slime.label", + "moduleKind": "other", + "position": { "x": 210, "y": 0 }, + "size": { "width": 220, "height": 72 }, + "visualRole": "summary-node", + "childNodeIds": ["custom-rollouts", "scheduler", "heartbeat"] + }, + { + "id": "custom-rollouts", + "labelKey": "graph.nodes.customRollouts.label", + "moduleKind": "other", + "position": { "x": 0, "y": 160 }, + "size": { "width": 200, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "scheduler", + "labelKey": "graph.nodes.scheduler.label", + "moduleKind": "other", + "position": { "x": 230, "y": 160 }, + "size": { "width": 190, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + }, + { + "id": "heartbeat", + "labelKey": "graph.nodes.heartbeat.label", + "moduleKind": "other", + "position": { "x": 470, "y": 160 }, + "size": { "width": 190, "height": 72 }, + "visualRole": "process-node", + "childNodeIds": [] + } + ], + "edges": [ + { + "id": "slime-rollouts", + "source": "slime", + "target": "custom-rollouts", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "slime-scheduler", + "source": "slime", + "target": "scheduler", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + }, + { + "id": "slime-heartbeat", + "source": "slime", + "target": "heartbeat", + "edgeKind": "data-flow", + "sourceHandleSide": "bottom", + "targetHandleSide": "top" + } + ] +} diff --git a/src/content/registry/models/glm-5.json b/src/content/registry/models/glm-5.json new file mode 100644 index 00000000..29780897 --- /dev/null +++ b/src/content/registry/models/glm-5.json @@ -0,0 +1,48 @@ +{ + "id": "model.glm-5", + "slug": "glm-5", + "kind": "model", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["GLM-5", "GLM 5"], + "tags": ["foundations", "context-window", "model-family"], + "relatedIds": [ + "paper.glm-5", + "concept.agentic-engineering", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + "module.multi-head-latent-attention", + "module.sparse-attention" + ], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "authors": ["GLM-5 Team"], + "sourceId": "paper.glm-5", + "family": "glm", + "sourceType": "research", + "modalities": ["text"], + "architectureIds": [ + "concept.transformer-architecture", + "concept.agentic-engineering" + ], + "moduleIds": [ + "module.multi-head-latent-attention", + "module.sparse-attention", + "module.mixture-of-experts", + "module.rmsnorm" + ], + "trainingRegimeIds": [ + "training-regime.asynchronous-agent-reinforcement-learning", + "training-regime.on-policy-distillation" + ], + "datasetIds": [], + "paperIds": ["paper.glm-5"], + "organizationId": "organization.zhipu-ai", + "releaseDate": "2026-02-17", + "parameterCount": "744 billion total parameters", + "activeParameterCount": "40 billion active parameters", + "contextLength": 200000, + "precision": ["bf16", "fp8", "int4"] +} diff --git a/src/content/registry/organizations/zhipu-ai.json b/src/content/registry/organizations/zhipu-ai.json new file mode 100644 index 00000000..dbaf0b01 --- /dev/null +++ b/src/content/registry/organizations/zhipu-ai.json @@ -0,0 +1,18 @@ +{ + "id": "organization.zhipu-ai", + "slug": "zhipu-ai", + "kind": "organization", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["Zhipu AI", "Z.ai"], + "tags": ["foundations", "model-family"], + "relatedIds": ["paper.glm-5", "model.glm-5"], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "website": "https://www.z.ai", + "modelIds": ["model.glm-5"], + "paperIds": ["paper.glm-5"], + "systemIds": ["system.slime-rollout-framework"] +} diff --git a/src/content/registry/papers/glm-5.json b/src/content/registry/papers/glm-5.json new file mode 100644 index 00000000..48bfceaf --- /dev/null +++ b/src/content/registry/papers/glm-5.json @@ -0,0 +1,45 @@ +{ + "id": "paper.glm-5", + "slug": "glm-5", + "kind": "paper", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["GLM-5", "GLM-5: from Vibe Coding to Agentic Engineering"], + "tags": ["foundations", "context-window", "model-family"], + "relatedIds": [ + "model.glm-5", + "concept.agentic-engineering", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + "module.multi-head-latent-attention", + "module.sparse-attention", + "training-regime.on-policy-distillation" + ], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "authors": ["GLM-5 Team"], + "publishedAt": "2026-02-17", + "url": "https://arxiv.org/abs/2602.15763", + "introducesIds": [ + "model.glm-5", + "concept.agentic-engineering", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework" + ], + "supportsIds": ["concept.transformer-architecture"], + "arguesAgainstIds": [], + "modelIds": ["model.glm-5"], + "moduleIds": [ + "module.multi-head-latent-attention", + "module.sparse-attention", + "module.mixture-of-experts" + ], + "conceptIds": [ + "concept.agentic-engineering", + "concept.transformer-architecture" + ], + "venue": "arXiv", + "arxivId": "2602.15763" +} diff --git a/src/content/registry/systems/slime-rollout-framework.json b/src/content/registry/systems/slime-rollout-framework.json new file mode 100644 index 00000000..6b980751 --- /dev/null +++ b/src/content/registry/systems/slime-rollout-framework.json @@ -0,0 +1,32 @@ +{ + "id": "system.slime-rollout-framework", + "slug": "slime-rollout-framework", + "kind": "system", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": ["slime", "slime framework", "slime rollout framework"], + "tags": ["foundations", "kv-cache"], + "relatedIds": [ + "paper.glm-5", + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "concept.agentic-engineering", + "system.on-disk-kv-cache" + ], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "releaseDate": "2026-02-17", + "authors": ["GLM-5 Team"], + "sourceId": "paper.glm-5", + "systemType": "training-infrastructure", + "relatedModelIds": ["model.glm-5"], + "relatedModuleIds": ["module.multi-head-latent-attention"], + "relatedConceptIds": ["concept.agentic-engineering"], + "paperIds": ["paper.glm-5"], + "datasetIds": [], + "organizationId": "organization.zhipu-ai", + "conceptType": "systems", + "variantGroup": "glm-5-agent-training" +} diff --git a/src/content/registry/training-regimes/asynchronous-agent-reinforcement-learning.json b/src/content/registry/training-regimes/asynchronous-agent-reinforcement-learning.json new file mode 100644 index 00000000..e831c63f --- /dev/null +++ b/src/content/registry/training-regimes/asynchronous-agent-reinforcement-learning.json @@ -0,0 +1,33 @@ +{ + "id": "training-regime.asynchronous-agent-reinforcement-learning", + "slug": "asynchronous-agent-reinforcement-learning", + "kind": "training-regime", + "defaultTitleKey": "title", + "defaultSummaryKey": "description", + "aliases": [ + "asynchronous agent reinforcement learning", + "asynchronous agent RL", + "asynchronous reinforcement learning for agentic tasks" + ], + "tags": ["foundations"], + "relatedIds": [ + "paper.glm-5", + "model.glm-5", + "system.slime-rollout-framework", + "concept.agentic-engineering", + "training-regime.on-policy-distillation" + ], + "citationIds": ["citation.glm-5-paper"], + "status": "published", + "createdAt": "2026-06-19T00:00:00.000Z", + "updatedAt": "2026-06-19T00:00:00.000Z", + "releaseDate": "2026-02-17", + "authors": ["GLM-5 Team"], + "sourceId": "paper.glm-5", + "regimeType": "rl", + "usedByModelIds": ["model.glm-5"], + "relatedModuleIds": [], + "paperIds": ["paper.glm-5"], + "conceptType": "training", + "variantGroup": "glm-5-post-training" +} diff --git a/src/features/models/components/ModelAtAGlance.tsx b/src/features/models/components/ModelAtAGlance.tsx index 428f9c4d..62f95ced 100644 --- a/src/features/models/components/ModelAtAGlance.tsx +++ b/src/features/models/components/ModelAtAGlance.tsx @@ -4,7 +4,10 @@ import { AtAGlanceDefinitionRow, } from "@/features/models/components/AtAGlanceCard"; import { buildPageReleaseMetadata } from "@/lib/content/page-release-metadata"; -import { getModelById } from "@/lib/content/registry-runtime"; +import { + getModelById, + getOrganizationById, +} from "@/lib/content/registry-runtime"; function formatToken(value: string): string { return value @@ -28,6 +31,9 @@ export function ModelAtAGlance({ registryId }: { registryId: string }) { return null; } const releaseMetadata = buildPageReleaseMetadata(record); + const organization = record.organizationId + ? getOrganizationById(record.organizationId) + : undefined; const modalities = record.modalities.map(formatToken).join(", "); const precision = @@ -62,6 +68,25 @@ export function ModelAtAGlance({ registryId }: { registryId: string }) { : undefined } /> + + {organization.aliases[0] ?? organization.slug} + + ) : ( + (organization.aliases[0] ?? organization.slug) + ) + ) : undefined + } + /> { + test("registry record is published with GLM-5 links and canonical aliases", () => { + const record = getConceptById("concept.agentic-engineering"); + expect(record?.status).toBe("published"); + expect(record?.aliases).toEqual([ + "agentic engineering", + "coding agents", + "software engineering agents", + ]); + expect(record?.conceptType).toBe("systems"); + expect(record?.relatedIds).toEqual( + expect.arrayContaining([ + "paper.glm-5", + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + ]), + ); + expect(record?.explainsIds).toEqual([ + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + ]); + expect(PUBLISHED_DOCS_REGISTRY_IDS.has("concept.agentic-engineering")).toBe( + true, + ); + }); + + test("page renders folded-summary content and direct links to the GLM-5 bundle", async () => { + const page = await loadConceptPage("agentic-engineering"); + expect(page.frontmatter.status).toBe("published"); + expect(page.frontmatter.registryId).toBe("concept.agentic-engineering"); + expect(page.messages.title).toBe("Agentic Engineering"); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "multi-step loop", + ); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "long trajectory coherent enough", + ); + + const html = renderToStaticMarkup( + createElement(ModulePageProviders, { + messages: page.messages, + assets: page.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: page.content, + }), + ); + + expect(html).toContain("What It Is"); + expect(html).toContain("Why It Matters"); + expect(html).toContain("Simple Example"); + expect(html).toContain("Common Confusions"); + expect(html).toContain( + 'data-graph-id="graph.agentic-engineering-concept-map"', + ); + expect(html).toContain('href="/docs/papers/glm-5"'); + expect(html).toContain('href="/docs/models/glm-5"'); + expect(html).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(html).toContain('href="/docs/systems/slime-rollout-framework"'); + expect(html).toContain('data-testid="curated-related-docs"'); + expect(html).not.toContain("Reader Shortcut"); + expect(html).not.toContain("benchmark"); + }); +}); diff --git a/src/lib/content/architecture.ts b/src/lib/content/architecture.ts index ae2047ad..dbebd25d 100644 --- a/src/lib/content/architecture.ts +++ b/src/lib/content/architecture.ts @@ -34,6 +34,7 @@ function isFoundationsArchitectureConceptRecord( return ( isConceptRecord(record) && record.tags.includes("foundations") && + record.conceptType !== "systems" && !record.tags.includes("token-to-probability-chain") ); } diff --git a/src/lib/content/asynchronous-agent-reinforcement-learning-page.test.ts b/src/lib/content/asynchronous-agent-reinforcement-learning-page.test.ts new file mode 100644 index 00000000..41b41776 --- /dev/null +++ b/src/lib/content/asynchronous-agent-reinforcement-learning-page.test.ts @@ -0,0 +1,87 @@ +import { describe, expect, test } from "bun:test"; +import { createElement, type ReactElement } from "react"; +import { renderToReadableStream } from "react-dom/server"; +import { ModulePageProviders } from "@/features/docs/components/ModulePageProviders"; +import { PUBLISHED_DOCS_REGISTRY_IDS } from "@/lib/content/published-docs-registry-ids"; +import { getTrainingRegimeById } from "@/lib/content/registry-runtime"; +import { loadTrainingRegimePage } from "@/lib/content/training-regime-page"; + +async function renderPageHtml(element: ReactElement): Promise { + const stream = await renderToReadableStream(element); + await stream.allReady; + return await new Response(stream).text(); +} + +describe("GLM-5 asynchronous agent reinforcement learning page (glm-5-2-004)", () => { + test("registry record is published with GLM-5 links and canonical aliases", () => { + const record = getTrainingRegimeById( + "training-regime.asynchronous-agent-reinforcement-learning", + ); + + expect(record?.status).toBe("published"); + expect(record?.aliases).toEqual([ + "asynchronous agent reinforcement learning", + "asynchronous agent RL", + "asynchronous reinforcement learning for agentic tasks", + ]); + expect(record?.regimeType).toBe("rl"); + expect(record?.relatedIds).toEqual( + expect.arrayContaining([ + "paper.glm-5", + "model.glm-5", + "system.slime-rollout-framework", + "concept.agentic-engineering", + ]), + ); + expect(record?.usedByModelIds).toEqual(["model.glm-5"]); + expect(record?.paperIds).toEqual(["paper.glm-5"]); + expect( + PUBLISHED_DOCS_REGISTRY_IDS.has( + "training-regime.asynchronous-agent-reinforcement-learning", + ), + ).toBe(true); + }); + + test("page renders folded-summary content and direct links to the GLM-5 bundle", async () => { + const page = await loadTrainingRegimePage( + "asynchronous-agent-reinforcement-learning", + ); + + expect(page.frontmatter.status).toBe("published"); + expect(page.frontmatter.registryId).toBe( + "training-regime.asynchronous-agent-reinforcement-learning", + ); + expect(page.messages.title).toBe( + "Asynchronous Agent Reinforcement Learning", + ); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "long-horizon agents", + ); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "partially separate clocks", + ); + + const html = await renderPageHtml( + createElement(ModulePageProviders, { + messages: page.messages, + assets: page.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: page.content, + }), + ); + + expect(html).toContain("What It Is"); + expect(html).toContain("How It Works"); + expect(html).toContain("Limitations And Failure Modes"); + expect(html).toContain( + 'data-graph-id="graph.asynchronous-agent-reinforcement-learning-training-flow"', + ); + expect(html).toContain('href="/docs/papers/glm-5"'); + expect(html).toContain('href="/docs/models/glm-5"'); + expect(html).toContain('href="/docs/systems/slime-rollout-framework"'); + expect(html).toContain('href="/docs/training/on-policy-distillation"'); + expect(html).toContain('data-testid="derived-related-docs"'); + expect(html).not.toContain("Reader Shortcut"); + expect(html).not.toContain("benchmark leaderboard"); + }); +}); diff --git a/src/lib/content/content-paths.test.ts b/src/lib/content/content-paths.test.ts index 25d90af0..5261f6c4 100644 --- a/src/lib/content/content-paths.test.ts +++ b/src/lib/content/content-paths.test.ts @@ -1,4 +1,6 @@ import { describe, expect, test } from "bun:test"; +import { mkdirSync, mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; import { join } from "node:path"; import { ATTENTION_MODULE_PAGE_DIR, @@ -53,4 +55,23 @@ describe("content-paths", () => { ); expect(TOKEN_GLOSSARY_PAGE_DIR).toBe(join(GLOSSARY_DOCS_ROOT, "token")); }); + + test("falls back to the repository root when cwd has no content tree", () => { + const originalCwd = process.cwd(); + const tempRoot = mkdtempSync(join(tmpdir(), "content-paths-")); + mkdirSync(join(tempRoot, ".next")); + + try { + process.chdir(tempRoot); + const projectRoot = getProjectRoot(); + + expect(projectRoot).not.toBe(tempRoot); + expect(getContentRoot(projectRoot)).toBe( + join(projectRoot, "src/content"), + ); + } finally { + process.chdir(originalCwd); + rmSync(tempRoot, { recursive: true, force: true }); + } + }); }); diff --git a/src/lib/content/content-paths.ts b/src/lib/content/content-paths.ts index 3e6b6ecc..04fdca44 100644 --- a/src/lib/content/content-paths.ts +++ b/src/lib/content/content-paths.ts @@ -1,11 +1,20 @@ -import { dirname, join } from "node:path"; +import { existsSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const CONTENT_PATHS_MODULE_DIR = dirname(fileURLToPath(import.meta.url)); -const REPO_ROOT = join(CONTENT_PATHS_MODULE_DIR, "../../.."); +const REPO_ROOT = resolve(CONTENT_PATHS_MODULE_DIR, "../../.."); + +function hasContentTree(projectRoot: string): boolean { + return existsSync(join(projectRoot, "src", "content", "docs")); +} /** Repository root for committed docs/registry content regardless of caller cwd. */ export function getProjectRoot(): string { + const cwd = process.cwd(); + if (hasContentTree(cwd)) { + return cwd; + } return REPO_ROOT; } diff --git a/src/lib/content/glm-5-model-page.test.ts b/src/lib/content/glm-5-model-page.test.ts new file mode 100644 index 00000000..d0185763 --- /dev/null +++ b/src/lib/content/glm-5-model-page.test.ts @@ -0,0 +1,77 @@ +import { describe, expect, test } from "bun:test"; +import { createElement } from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { ModulePageProviders } from "@/features/docs/components/ModulePageProviders"; +import { loadModelPage } from "@/lib/content/model-page"; +import { getModelById } from "@/lib/content/registry-runtime"; + +describe("GLM-5 model page", () => { + test("registry record carries model-family metadata, architecture links, and organization ownership", () => { + const record = getModelById("model.glm-5"); + + expect(record?.status).toBe("published"); + expect(record?.aliases).toEqual(["GLM-5", "GLM 5"]); + expect(record?.tags).toEqual( + expect.arrayContaining(["model-family", "context-window"]), + ); + expect(record?.architectureIds).toEqual( + expect.arrayContaining([ + "concept.transformer-architecture", + "concept.agentic-engineering", + ]), + ); + expect(record?.moduleIds).toEqual( + expect.arrayContaining([ + "module.multi-head-latent-attention", + "module.sparse-attention", + "module.mixture-of-experts", + ]), + ); + expect(record?.trainingRegimeIds).toEqual( + expect.arrayContaining([ + "training-regime.asynchronous-agent-reinforcement-learning", + ]), + ); + expect(record?.paperIds).toEqual(["paper.glm-5"]); + expect(record?.organizationId).toBe("organization.zhipu-ai"); + expect(record?.relatedIds).toEqual( + expect.arrayContaining(["paper.glm-5", "system.slime-rollout-framework"]), + ); + }); + + test("route renders the folded summary, architecture teaching block, and linked model dependencies", async () => { + const page = await loadModelPage("glm-5"); + + expect(page.frontmatter.status).toBe("published"); + expect(page.frontmatter.registryId).toBe("model.glm-5"); + expect(page.messages.title).toBe("GLM-5"); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "post-training", + ); + + const html = renderToStaticMarkup( + createElement(ModulePageProviders, { + messages: page.messages, + assets: page.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: page.content, + }), + ); + + expect(html).toContain("Organization"); + expect(html).toContain("Zhipu AI"); + expect(html).toContain('href="https://www.z.ai"'); + expect(html).toContain("Architecture"); + expect(html).toContain('data-graph-id="graph.glm-5-architecture"'); + expect(html).toContain('href="/docs/papers/glm-5"'); + expect(html).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(html).toContain('href="/docs/systems/slime-rollout-framework"'); + expect(html).toContain('href="/docs/modules/multi-head-latent-attention"'); + expect(html).toContain('href="/docs/modules/sparse-attention"'); + expect(html).toContain('href="/docs/modules/mixture-of-experts"'); + expect(html).toContain('data-testid="derived-related-docs"'); + expect(html).not.toContain("benchmark leaderboard"); + }); +}); diff --git a/src/lib/content/glm-5-paper-page.test.ts b/src/lib/content/glm-5-paper-page.test.ts new file mode 100644 index 00000000..eab426d0 --- /dev/null +++ b/src/lib/content/glm-5-paper-page.test.ts @@ -0,0 +1,137 @@ +import { describe, expect, test } from "bun:test"; +import { createElement, type ReactElement } from "react"; +import { renderToReadableStream } from "react-dom/server"; +import { ModulePageProviders } from "@/features/docs/components/ModulePageProviders"; +import { loadConceptPage } from "@/lib/content/concept-page"; +import { loadModelPage } from "@/lib/content/model-page"; +import { loadPaperPage } from "@/lib/content/paper-page"; +import { getPaperById } from "@/lib/content/registry-runtime"; +import { loadSystemPage } from "@/lib/content/system-page"; +import { loadTrainingRegimePage } from "@/lib/content/training-regime-page"; + +async function renderPageHtml(element: ReactElement): Promise { + const stream = await renderToReadableStream(element); + await stream.allReady; + return await new Response(stream).text(); +} + +describe("GLM-5 paper bundle", () => { + test("paper registry record links the canonical bundle and nearby references", () => { + const record = getPaperById("paper.glm-5"); + expect(record?.status).toBe("published"); + expect(record?.aliases).toEqual([ + "GLM-5", + "GLM-5: from Vibe Coding to Agentic Engineering", + ]); + expect(record?.modelIds).toEqual(["model.glm-5"]); + expect(record?.introducesIds).toEqual([ + "model.glm-5", + "concept.agentic-engineering", + "training-regime.asynchronous-agent-reinforcement-learning", + "system.slime-rollout-framework", + ]); + expect(record?.relatedIds).toEqual( + expect.arrayContaining([ + "module.multi-head-latent-attention", + "module.sparse-attention", + "training-regime.on-policy-distillation", + ]), + ); + }); + + test("paper route renders folded summary, introduced-record graph, and direct links to the canonical follow-on pages", async () => { + const page = await loadPaperPage("glm-5"); + expect(page.frontmatter.status).toBe("published"); + expect(page.frontmatter.registryId).toBe("paper.glm-5"); + expect(page.messages.title).toBe( + "GLM-5: from Vibe Coding to Agentic Engineering", + ); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "agentic engineering", + ); + + const html = await renderPageHtml( + createElement(ModulePageProviders, { + messages: page.messages, + assets: page.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: page.content, + }), + ); + + expect(html).toContain("What The Paper Introduced"); + expect(html).toContain('data-graph-id="graph.glm-5-contribution"'); + expect(html).toContain('href="/docs/models/glm-5"'); + expect(html).toContain('href="/docs/concepts/agentic-engineering"'); + expect(html).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(html).toContain('href="/docs/systems/slime-rollout-framework"'); + expect(html).toContain('href="/docs/modules/multi-head-latent-attention"'); + expect(html).toContain('href="/docs/modules/sparse-attention"'); + expect(html).toContain('href="/docs/training/on-policy-distillation"'); + expect(html).not.toContain("Reader Shortcut"); + expect(html).not.toContain("benchmark leaderboard"); + }); + + test("supporting GLM-5 pages render and cross-link back into the paper bundle", async () => { + const modelPage = await loadModelPage("glm-5"); + const modelHtml = await renderPageHtml( + createElement(ModulePageProviders, { + messages: modelPage.messages, + assets: modelPage.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: modelPage.content, + }), + ); + expect(modelHtml).toContain('href="/docs/papers/glm-5"'); + expect(modelHtml).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(modelHtml).toContain('href="/docs/systems/slime-rollout-framework"'); + + const conceptPage = await loadConceptPage("agentic-engineering"); + const conceptHtml = await renderPageHtml( + createElement(ModulePageProviders, { + messages: conceptPage.messages, + assets: conceptPage.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: conceptPage.content, + }), + ); + expect(conceptHtml).toContain('href="/docs/papers/glm-5"'); + expect(conceptHtml).toContain('href="/docs/models/glm-5"'); + + const trainingPage = await loadTrainingRegimePage( + "asynchronous-agent-reinforcement-learning", + ); + const trainingHtml = await renderPageHtml( + createElement(ModulePageProviders, { + messages: trainingPage.messages, + assets: trainingPage.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: trainingPage.content, + }), + ); + expect(trainingHtml).toContain('href="/docs/papers/glm-5"'); + expect(trainingHtml).toContain('href="/docs/models/glm-5"'); + expect(trainingHtml).toContain( + 'href="/docs/systems/slime-rollout-framework"', + ); + + const systemPage = await loadSystemPage("slime-rollout-framework"); + const systemHtml = await renderPageHtml( + createElement(ModulePageProviders, { + messages: systemPage.messages, + assets: systemPage.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: systemPage.content, + }), + ); + expect(systemHtml).toContain('href="/docs/papers/glm-5"'); + expect(systemHtml).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(systemHtml).toContain('href="/docs/models/glm-5"'); + }); +}); diff --git a/src/lib/content/graph-registry-runtime.test.ts b/src/lib/content/graph-registry-runtime.test.ts index 3eadd552..1af220ea 100644 --- a/src/lib/content/graph-registry-runtime.test.ts +++ b/src/lib/content/graph-registry-runtime.test.ts @@ -150,7 +150,7 @@ describe("graph-registry-runtime", () => { test("lists all bundled graph records", () => { const records = listGraphRecords(); - expect(records.length).toBe(44); + expect(records.length).toBe(49); expect(records.map((record) => record.id)).toContain( "graph.deepseek-v4-contribution", ); @@ -166,5 +166,20 @@ describe("graph-registry-runtime", () => { expect(records.map((record) => record.id)).toContain( "graph.expert-parallel-overlap-system-flow", ); + expect(records.map((record) => record.id)).toContain( + "graph.glm-5-architecture", + ); + expect(records.map((record) => record.id)).toContain( + "graph.glm-5-contribution", + ); + expect(records.map((record) => record.id)).toContain( + "graph.agentic-engineering-concept-map", + ); + expect(records.map((record) => record.id)).toContain( + "graph.asynchronous-agent-reinforcement-learning-training-flow", + ); + expect(records.map((record) => record.id)).toContain( + "graph.slime-rollout-framework-system-flow", + ); }); }); diff --git a/src/lib/content/graph-registry-runtime.ts b/src/lib/content/graph-registry-runtime.ts index e3a55424..1c20a6b1 100644 --- a/src/lib/content/graph-registry-runtime.ts +++ b/src/lib/content/graph-registry-runtime.ts @@ -1,3 +1,5 @@ +import agenticEngineeringConceptMap from "@/content/registry/graphs/agentic-engineering-concept-map.json"; +import asynchronousAgentReinforcementLearningTrainingFlow from "@/content/registry/graphs/asynchronous-agent-reinforcement-learning-training-flow.json"; import batchNormComputeFlow from "@/content/registry/graphs/batch-norm-compute-flow.json"; import bidirectionalAttentionTimePattern from "@/content/registry/graphs/bidirectional-attention-time-pattern.json"; import compressedSparseAttentionFlow from "@/content/registry/graphs/compressed-sparse-attention-flow.json"; @@ -8,6 +10,8 @@ import deepseekmoeRoutingFlow from "@/content/registry/graphs/deepseekmoe-routin import expertParallelOverlapSystemFlow from "@/content/registry/graphs/expert-parallel-overlap-system-flow.json"; import feedForwardNetworkFamilyOverview from "@/content/registry/graphs/feed-forward-network-family-overview.json"; import fp4QuantizationAwareTrainingTrainingFlow from "@/content/registry/graphs/fp4-quantization-aware-training-training-flow.json"; +import glm5Architecture from "@/content/registry/graphs/glm-5-architecture.json"; +import glm5Contribution from "@/content/registry/graphs/glm-5-contribution.json"; import gpt3Architecture from "@/content/registry/graphs/gpt-3-architecture.json"; import groupNormComputeFlow from "@/content/registry/graphs/group-norm-compute-flow.json"; import groupedQueryAttentionComputeFlow from "@/content/registry/graphs/grouped-query-attention-compute-flow.json"; @@ -36,6 +40,7 @@ import reluActivationFlow from "@/content/registry/graphs/relu-activation-flow.j import rmsnormComputeFlow from "@/content/registry/graphs/rmsnorm-compute-flow.json"; import siluActivationFlow from "@/content/registry/graphs/silu-activation-flow.json"; import slidingWindowAttentionTimeWindowPattern from "@/content/registry/graphs/sliding-window-attention-time-window-pattern.json"; +import slimeRolloutFrameworkSystemFlow from "@/content/registry/graphs/slime-rollout-framework-system-flow.json"; import sparseAttentionTimePattern from "@/content/registry/graphs/sparse-attention-time-pattern.json"; import specialistTrainingTrainingFlow from "@/content/registry/graphs/specialist-training-training-flow.json"; import standardFfnComputeFlow from "@/content/registry/graphs/standard-ffn-compute-flow.json"; @@ -45,6 +50,8 @@ import tokenConceptMap from "@/content/registry/graphs/token-concept-map.json"; import { type GraphRecord, graphRecordSchema } from "@/lib/content/schemas"; const graphRecords: GraphRecord[] = [ + graphRecordSchema.parse(agenticEngineeringConceptMap), + graphRecordSchema.parse(asynchronousAgentReinforcementLearningTrainingFlow), graphRecordSchema.parse(batchNormComputeFlow), graphRecordSchema.parse(bidirectionalAttentionTimePattern), graphRecordSchema.parse(compressedSparseAttentionFlow), @@ -55,6 +62,8 @@ const graphRecords: GraphRecord[] = [ graphRecordSchema.parse(expertParallelOverlapSystemFlow), graphRecordSchema.parse(feedForwardNetworkFamilyOverview), graphRecordSchema.parse(fp4QuantizationAwareTrainingTrainingFlow), + graphRecordSchema.parse(glm5Architecture), + graphRecordSchema.parse(glm5Contribution), graphRecordSchema.parse(gpt3Architecture), graphRecordSchema.parse(groupNormComputeFlow), graphRecordSchema.parse(groupedQueryAttentionComputeFlow), @@ -82,6 +91,7 @@ const graphRecords: GraphRecord[] = [ graphRecordSchema.parse(rmsnormComputeFlow), graphRecordSchema.parse(siluActivationFlow), graphRecordSchema.parse(specialistTrainingTrainingFlow), + graphRecordSchema.parse(slimeRolloutFrameworkSystemFlow), graphRecordSchema.parse(sparseAttentionTimePattern), graphRecordSchema.parse(standardFfnComputeFlow), graphRecordSchema.parse(standardFfnParallelBaseline), diff --git a/src/lib/content/published-docs-registry-ids.ts b/src/lib/content/published-docs-registry-ids.ts index 60e1ebbc..09997892 100644 --- a/src/lib/content/published-docs-registry-ids.ts +++ b/src/lib/content/published-docs-registry-ids.ts @@ -1,5 +1,6 @@ /** Concept registry ids whose published docs page lives under `/docs/concepts`. */ export const PUBLISHED_CONCEPT_SECTION_REGISTRY_IDS = new Set([ + "concept.agentic-engineering", "concept.page-spec-workflow-sample", "concept.transformer-architecture", "concept.positional-encodings", @@ -49,7 +50,9 @@ export const PUBLISHED_DOCS_REGISTRY_IDS = new Set([ "model.gpt-3", "model.deepseek-v4-pro", "model.deepseek-v4-flash", + "model.glm-5", "paper.deepseek-v4", + "paper.glm-5", "module.attention", "module.bidirectional-attention", "module.compressed-sparse-attention", @@ -142,6 +145,7 @@ export const PUBLISHED_DOCS_REGISTRY_IDS = new Set([ "concept.multimodal-model", "concept.world-model", "concept.page-spec-workflow-sample", + "concept.agentic-engineering", "concept.transformer-architecture", "concept.feed-forward-network", "concept.standard-ffn", @@ -184,9 +188,11 @@ export const PUBLISHED_DOCS_REGISTRY_IDS = new Set([ "concept.activation-quantization", "concept.kv-cache-quantization", "concept.why-4-bit-models-are-not-exactly-4x-faster", + "training-regime.asynchronous-agent-reinforcement-learning", "training-regime.on-policy-distillation", "training-regime.specialist-training", "training-regime.fp4-quantization-aware-training", + "system.slime-rollout-framework", "system.on-disk-kv-cache", "system.expert-parallel-overlap", ]); diff --git a/src/lib/content/registry-runtime.ts b/src/lib/content/registry-runtime.ts index ff3b4886..35339dd6 100644 --- a/src/lib/content/registry-runtime.ts +++ b/src/lib/content/registry-runtime.ts @@ -5,6 +5,7 @@ import chenPositionalInterpolationCitation from "@/content/registry/citations/ch import deepseekV2MlaPaperCitation from "@/content/registry/citations/deepseek-v2-mla-paper.json"; import deepseekV4PaperCitation from "@/content/registry/citations/deepseek-v4-paper.json"; import dingLongropeCitation from "@/content/registry/citations/ding-longrope.json"; +import glm5PaperCitation from "@/content/registry/citations/glm-5-paper.json"; import goodfellowDeepLearningCitation from "@/content/registry/citations/goodfellow-deep-learning.json"; import gqaPaperCitation from "@/content/registry/citations/gqa-paper.json"; import kaiokendevSuperhotCitation from "@/content/registry/citations/kaiokendev-superhot.json"; @@ -24,6 +25,7 @@ import weiEmergentAbilitiesCitation from "@/content/registry/citations/wei-emerg import absolutePositionalEmbeddingsConcept from "@/content/registry/concepts/absolute-positional-embeddings.json"; import activationConcept from "@/content/registry/concepts/activation.json"; import activationQuantizationConcept from "@/content/registry/concepts/activation-quantization.json"; +import agenticEngineeringConcept from "@/content/registry/concepts/agentic-engineering.json"; import alibiConcept from "@/content/registry/concepts/alibi.json"; import alignmentConcept from "@/content/registry/concepts/alignment.json"; import architectureConcept from "@/content/registry/concepts/architecture.json"; @@ -119,6 +121,7 @@ import yarnConcept from "@/content/registry/concepts/yarn.json"; import deepseekV4SpecialistCorpus from "@/content/registry/datasets/deepseek-v4-specialist-corpus.json"; import deepseekV4FlashModel from "@/content/registry/models/deepseek-v4-flash.json"; import deepseekV4ProModel from "@/content/registry/models/deepseek-v4-pro.json"; +import glm5Model from "@/content/registry/models/glm-5.json"; import gpt3Model from "@/content/registry/models/gpt-3.json"; import absolutePositionalEmbeddingsModule from "@/content/registry/modules/absolute-positional-embeddings.json"; import alibiModule from "@/content/registry/modules/alibi.json"; @@ -159,9 +162,13 @@ import swigluModule from "@/content/registry/modules/swiglu.json"; import t5RelativePositionBiasModule from "@/content/registry/modules/t5-relative-position-bias.json"; import yarnModule from "@/content/registry/modules/yarn.json"; import deepseekAiOrganization from "@/content/registry/organizations/deepseek-ai.json"; +import zhipuAiOrganization from "@/content/registry/organizations/zhipu-ai.json"; import deepseekV4Paper from "@/content/registry/papers/deepseek-v4.json"; +import glm5Paper from "@/content/registry/papers/glm-5.json"; import expertParallelOverlapSystem from "@/content/registry/systems/expert-parallel-overlap.json"; import onDiskKvCacheSystem from "@/content/registry/systems/on-disk-kv-cache.json"; +import slimeRolloutFrameworkSystem from "@/content/registry/systems/slime-rollout-framework.json"; +import asynchronousAgentReinforcementLearningRegime from "@/content/registry/training-regimes/asynchronous-agent-reinforcement-learning.json"; import fp4QuantizationAwareTrainingRegime from "@/content/registry/training-regimes/fp4-quantization-aware-training.json"; import onPolicyDistillationRegime from "@/content/registry/training-regimes/on-policy-distillation.json"; import specialistTrainingRegime from "@/content/registry/training-regimes/specialist-training.json"; @@ -234,6 +241,7 @@ const moduleRecords: ModuleRecord[] = [ const conceptRecords: ConceptRecord[] = [ conceptRecordSchema.parse(tokenConcept), + conceptRecordSchema.parse(agenticEngineeringConcept), conceptRecordSchema.parse(embeddingConcept), conceptRecordSchema.parse(tensorConcept), conceptRecordSchema.parse(vectorConcept), @@ -334,9 +342,16 @@ const modelRecords: ModelRecord[] = [ modelRecordSchema.parse(gpt3Model), modelRecordSchema.parse(deepseekV4ProModel), modelRecordSchema.parse(deepseekV4FlashModel), + modelRecordSchema.parse(glm5Model), +]; +const paperRecords: PaperRecord[] = [ + paperRecordSchema.parse(deepseekV4Paper), + paperRecordSchema.parse(glm5Paper), ]; -const paperRecords: PaperRecord[] = [paperRecordSchema.parse(deepseekV4Paper)]; const trainingRegimeRecords: TrainingRegimeRecord[] = [ + trainingRegimeRecordSchema.parse( + asynchronousAgentReinforcementLearningRegime, + ), trainingRegimeRecordSchema.parse(onPolicyDistillationRegime), trainingRegimeRecordSchema.parse(specialistTrainingRegime), trainingRegimeRecordSchema.parse(fp4QuantizationAwareTrainingRegime), @@ -344,12 +359,14 @@ const trainingRegimeRecords: TrainingRegimeRecord[] = [ const systemRecords: SystemRecord[] = [ systemRecordSchema.parse(onDiskKvCacheSystem), systemRecordSchema.parse(expertParallelOverlapSystem), + systemRecordSchema.parse(slimeRolloutFrameworkSystem), ]; const datasetRecords: DatasetRecord[] = [ datasetRecordSchema.parse(deepseekV4SpecialistCorpus), ]; const organizationRecords: OrganizationRecord[] = [ organizationRecordSchema.parse(deepseekAiOrganization), + organizationRecordSchema.parse(zhipuAiOrganization), ]; const citationRecords: CitationRecord[] = [ @@ -360,6 +377,7 @@ const citationRecords: CitationRecord[] = [ citationRecordSchema.parse(deepseekV2MlaPaperCitation), citationRecordSchema.parse(deepseekV4PaperCitation), citationRecordSchema.parse(dingLongropeCitation), + citationRecordSchema.parse(glm5PaperCitation), citationRecordSchema.parse(goodfellowDeepLearningCitation), citationRecordSchema.parse(gqaPaperCitation), citationRecordSchema.parse(kaiokendevSuperhotCitation), diff --git a/src/lib/content/slime-rollout-framework-system-page.test.ts b/src/lib/content/slime-rollout-framework-system-page.test.ts new file mode 100644 index 00000000..7daccb35 --- /dev/null +++ b/src/lib/content/slime-rollout-framework-system-page.test.ts @@ -0,0 +1,80 @@ +import { describe, expect, test } from "bun:test"; +import { createElement, type ReactElement } from "react"; +import { renderToReadableStream } from "react-dom/server"; +import { ModulePageProviders } from "@/features/docs/components/ModulePageProviders"; +import { PUBLISHED_DOCS_REGISTRY_IDS } from "@/lib/content/published-docs-registry-ids"; +import { getSystemById } from "@/lib/content/registry-runtime"; +import { loadSystemPage } from "@/lib/content/system-page"; + +async function renderPageHtml(element: ReactElement): Promise { + const stream = await renderToReadableStream(element); + await stream.allReady; + return await new Response(stream).text(); +} + +describe("GLM-5 slime rollout framework system page (glm-5-2-005)", () => { + test("registry record is published with GLM-5 links and canonical aliases", () => { + const record = getSystemById("system.slime-rollout-framework"); + + expect(record?.status).toBe("published"); + expect(record?.aliases).toEqual([ + "slime", + "slime framework", + "slime rollout framework", + ]); + expect(record?.systemType).toBe("training-infrastructure"); + expect(record?.relatedIds).toEqual( + expect.arrayContaining([ + "paper.glm-5", + "model.glm-5", + "training-regime.asynchronous-agent-reinforcement-learning", + "concept.agentic-engineering", + ]), + ); + expect(record?.relatedModelIds).toEqual(["model.glm-5"]); + expect(record?.paperIds).toEqual(["paper.glm-5"]); + expect( + PUBLISHED_DOCS_REGISTRY_IDS.has("system.slime-rollout-framework"), + ).toBe(true); + }); + + test("page renders folded-summary content and direct links to the GLM-5 bundle", async () => { + const page = await loadSystemPage("slime-rollout-framework"); + + expect(page.frontmatter.status).toBe("published"); + expect(page.frontmatter.registryId).toBe("system.slime-rollout-framework"); + expect(page.messages.title).toBe("slime Rollout Framework"); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "runtime behavior", + ); + expect(page.messages.openingSummary?.toLowerCase()).toContain( + "heartbeat-based recovery", + ); + + const html = await renderPageHtml( + createElement(ModulePageProviders, { + messages: page.messages, + assets: page.assets, + // biome-ignore lint/correctness/noChildrenProp: third createElement arg conflicts with strict props typing + children: page.content, + }), + ); + + expect(html).toContain("What It Is"); + expect(html).toContain("Where It Sits"); + expect(html).toContain("How It Works"); + expect(html).toContain("Practical Impact"); + expect(html).toContain( + 'data-graph-id="graph.slime-rollout-framework-system-flow"', + ); + expect(html).toContain( + 'href="/docs/training/asynchronous-agent-reinforcement-learning"', + ); + expect(html).toContain('href="/docs/papers/glm-5"'); + expect(html).toContain('href="/docs/models/glm-5"'); + expect(html).toContain('href="/docs/modules/multi-head-latent-attention"'); + expect(html).toContain('data-testid="derived-related-docs"'); + expect(html).not.toContain("Reader Shortcut"); + expect(html).not.toContain("benchmark leaderboard"); + }); +}); diff --git a/src/lib/source.test.ts b/src/lib/source.test.ts index 8073a8dd..26e5cb04 100644 --- a/src/lib/source.test.ts +++ b/src/lib/source.test.ts @@ -106,12 +106,17 @@ const MODULE_INDEX_URLS = [ const MODEL_INDEX_URLS = [ "/docs/models/deepseek-v4-flash", "/docs/models/deepseek-v4-pro", + "/docs/models/glm-5", "/docs/models/gpt-3", ] as const; -const PAPER_INDEX_URLS = ["/docs/papers/deepseek-v4"] as const; +const PAPER_INDEX_URLS = [ + "/docs/papers/deepseek-v4", + "/docs/papers/glm-5", +] as const; const TRAINING_INDEX_URLS = [ + "/docs/training/asynchronous-agent-reinforcement-learning", "/docs/training/fp4-quantization-aware-training", "/docs/training/on-policy-distillation", "/docs/training/specialist-training", @@ -120,6 +125,7 @@ const TRAINING_INDEX_URLS = [ const SYSTEM_INDEX_URLS = [ "/docs/systems/expert-parallel-overlap", "/docs/systems/on-disk-kv-cache", + "/docs/systems/slime-rollout-framework", ] as const; function collectPageUrls(nodes: Node[]): string[] { diff --git a/src/lib/verify/phase-1-search-dialog-checks.ts b/src/lib/verify/phase-1-search-dialog-checks.ts index bb1acb09..d8b26e16 100644 --- a/src/lib/verify/phase-1-search-dialog-checks.ts +++ b/src/lib/verify/phase-1-search-dialog-checks.ts @@ -27,6 +27,16 @@ export type SearchDialogDomSnapshot = { hasGroupedQueryAttentionButton: boolean; }; +export type SearchDialogInputHydrationSnapshot = { + inputVisible: boolean; + inputFocused: boolean; + inputValue: string; + idleVisible: boolean; + loadingVisible: boolean; + resultsVisible: boolean; + emptyVisible: boolean; +}; + export const VERIFY_SEARCH_DIALOG_STUB_ENV = "VERIFY_SEARCH_DIALOG_STUB"; export type RunPhase1SearchDialogChecksOptions = { @@ -58,12 +68,16 @@ export function resolveSearchDialogCheckOptionsFromEnv( } const SEARCH_DIALOG_TRIGGER_SELECTOR = "button[data-search]"; +const SEARCH_DIALOG_IDLE_SELECTOR = '[data-testid="search-dialog-idle"]'; +const SEARCH_DIALOG_LOADING_SELECTOR = '[data-testid="search-dialog-loading"]'; const SEARCH_DIALOG_EMPTY_SELECTOR = '[data-testid="search-dialog-empty"]'; const SEARCH_RESULT_URL_SELECTOR = '[data-testid="search-result-url"]'; const SEARCH_DIALOG_OPEN_RETRY_INTERVAL_MS = 250; +const SEARCH_INPUT_SNAPSHOT_FIELD_TIMEOUT_MS = 5_000; /** Default per-query browser deadline (client hydration can exceed 10s under CI load). */ -export const DEFAULT_SEARCH_DIALOG_TIMEOUT_MS = 30_000; +export const DEFAULT_SEARCH_DIALOG_TIMEOUT_MS = 45_000; +export const SEARCH_DIALOG_QUERY_RETRY_LIMIT = 1; export function formatPhase1SearchDialogCheckFailure( failure: Phase1SearchDialogCheckFailure, @@ -71,6 +85,19 @@ export function formatPhase1SearchDialogCheckFailure( return `${failure.surface}?query=${encodeURIComponent(failure.query)}: ${failure.reason}`; } +export function shouldRetrySearchDialogQuery(reason: string): boolean { + return ( + reason.startsWith( + "search input did not hydrate in header search dialog within ", + ) || + reason.startsWith( + "timed out waiting for search results in header search dialog for query ", + ) || + reason === + "no loading, results, or empty outcome appeared after entering a query in header search dialog" + ); +} + /** * Pure DOM outcome for the header search dialog — used by Playwright and unit tests. */ @@ -146,6 +173,16 @@ async function sleep(ms: number): Promise { await new Promise((resolve) => setTimeout(resolve, ms)); } +async function readBoundedInputValue(input: Locator): Promise { + try { + return await input.inputValue({ + timeout: SEARCH_INPUT_SNAPSHOT_FIELD_TIMEOUT_MS, + }); + } catch { + return ""; + } +} + async function openHeaderSearchDialog( page: Page, baseUrl: string, @@ -154,7 +191,7 @@ async function openHeaderSearchDialog( const homeUrl = normalizeVerifyBaseUrl(baseUrl); await page.goto(homeUrl, { timeout: timeoutMs, - waitUntil: "domcontentloaded", + waitUntil: "load", }); const trigger = page.locator(SEARCH_DIALOG_TRIGGER_SELECTOR).first(); @@ -188,13 +225,113 @@ async function waitForSearchDialogOutcome( dialog: Locator, timeoutMs: number, ): Promise { + const loading = dialog.locator(SEARCH_DIALOG_LOADING_SELECTOR); const results = dialog.locator(SEARCH_RESULT_URL_SELECTOR); const empty = dialog.locator(SEARCH_DIALOG_EMPTY_SELECTOR); await Promise.race([ + loading.waitFor({ state: "visible", timeout: timeoutMs }), results.first().waitFor({ state: "visible", timeout: timeoutMs }), empty.waitFor({ state: "visible", timeout: timeoutMs }), ]); + + await Promise.race([ + results.first().waitFor({ state: "visible", timeout: timeoutMs }), + empty.waitFor({ state: "visible", timeout: timeoutMs }), + ]); +} + +export async function readSearchDialogInputHydrationSnapshot( + dialog: Locator, +): Promise { + const input = dialog.getByRole("textbox"); + + return { + inputVisible: await input.isVisible(), + inputFocused: await input + .evaluate((element) => element === document.activeElement) + .catch(() => false), + inputValue: await readBoundedInputValue(input), + idleVisible: await dialog.locator(SEARCH_DIALOG_IDLE_SELECTOR).isVisible(), + loadingVisible: await dialog + .locator(SEARCH_DIALOG_LOADING_SELECTOR) + .isVisible(), + resultsVisible: + (await dialog.locator(SEARCH_RESULT_URL_SELECTOR).count()) > 0, + emptyVisible: await dialog + .locator(SEARCH_DIALOG_EMPTY_SELECTOR) + .isVisible(), + }; +} + +export function evaluateSearchDialogInputHydrationBeforeQuery( + snapshot: SearchDialogInputHydrationSnapshot, +): string | null { + if (!snapshot.inputVisible) { + return "search input is not visible in header search dialog"; + } + + if (!snapshot.idleVisible) { + return "idle state is not visible before query entry in header search dialog"; + } + + return null; +} + +export function evaluateSearchDialogInputHydrationAfterTyping( + snapshot: SearchDialogInputHydrationSnapshot, + typedQuery: string, +): string | null { + if (!snapshot.inputFocused) { + return "search input did not retain focus after typing in header search dialog"; + } + + if (snapshot.inputValue !== typedQuery) { + return `search input value "${snapshot.inputValue}" did not update to "${typedQuery}" after typing in header search dialog`; + } + + if (snapshot.idleVisible) { + return "idle state remained visible after entering a query in header search dialog"; + } + + return null; +} + +export function evaluateSearchDialogInputHydrationOutcome( + snapshot: SearchDialogInputHydrationSnapshot, +): string | null { + if ( + snapshot.loadingVisible || + snapshot.resultsVisible || + snapshot.emptyVisible + ) { + return null; + } + + return "no loading, results, or empty outcome appeared after entering a query in header search dialog"; +} + +async function waitForSearchDialogInputHydrationBeforeQuery( + dialog: Locator, + timeoutMs: number, +): Promise { + const deadline = Date.now() + timeoutMs; + + while (Date.now() < deadline) { + try { + const snapshot = await readSearchDialogInputHydrationSnapshot(dialog); + const failure = evaluateSearchDialogInputHydrationBeforeQuery(snapshot); + if (!failure) { + return null; + } + } catch { + // React hydration can detach the input between visibility and evaluate. + } + + await sleep(250); + } + + return `search input did not hydrate in header search dialog within ${timeoutMs}ms`; } /** @@ -211,9 +348,26 @@ export async function checkSearchDialogQuery( const activeDialog = dialog ?? (await openHeaderSearchDialog(page, baseUrl, timeoutMs)); + const beforeQuery = await waitForSearchDialogInputHydrationBeforeQuery( + activeDialog, + timeoutMs, + ); + if (beforeQuery) { + return beforeQuery; + } + const input = activeDialog.getByRole("textbox"); await input.fill(""); - await input.fill(query); + await input.focus(); + await input.pressSequentially(query, { delay: 30 }); + + const afterTyping = evaluateSearchDialogInputHydrationAfterTyping( + await readSearchDialogInputHydrationSnapshot(activeDialog), + query, + ); + if (afterTyping) { + return afterTyping; + } try { await waitForSearchDialogOutcome(activeDialog, timeoutMs); @@ -221,6 +375,13 @@ export async function checkSearchDialogQuery( return `timed out waiting for search results in header search dialog for query "${query}" after ${timeoutMs}ms`; } + const hydrationOutcome = evaluateSearchDialogInputHydrationOutcome( + await readSearchDialogInputHydrationSnapshot(activeDialog), + ); + if (hydrationOutcome) { + return hydrationOutcome; + } + const snapshot = await readSearchDialogDomSnapshot(activeDialog); return evaluateSearchDialogDomSnapshot(snapshot, query); } @@ -250,21 +411,54 @@ export async function runPhase1SearchDialogChecks( const browser = await launchBrowser(); try { - const page = await browser.newPage(); - page.setDefaultTimeout(timeoutMs); - - const dialog = await openHeaderSearchDialog(page, baseUrl, timeoutMs); - - for (const query of queries) { - const reason = await checkSearchDialogQuery( - page, - baseUrl, - query, - timeoutMs, - dialog, - ); - if (reason) { - failures.push({ query, surface: "header-dialog", reason }); + const queryFailures = await Promise.all( + queries.map(async (query) => { + for ( + let attempt = 0; + attempt <= SEARCH_DIALOG_QUERY_RETRY_LIMIT; + attempt += 1 + ) { + const context = await browser.newContext(); + try { + const page = await context.newPage(); + page.setDefaultTimeout(timeoutMs); + page.setDefaultNavigationTimeout(timeoutMs); + + const dialog = await openHeaderSearchDialog( + page, + baseUrl, + timeoutMs, + ); + const reason = await checkSearchDialogQuery( + page, + baseUrl, + query, + timeoutMs, + dialog, + ); + + if (!reason) { + return null; + } + + if ( + attempt === SEARCH_DIALOG_QUERY_RETRY_LIMIT || + !shouldRetrySearchDialogQuery(reason) + ) { + return { query, surface: "header-dialog" as const, reason }; + } + } finally { + await Promise.race([context.close(), sleep(timeoutMs)]); + } + } + + return null; + }), + ); + + for (const failure of queryFailures) { + if (failure) { + failures.push(failure); } } } finally { diff --git a/src/lib/verify/search-dialog-checks.test.ts b/src/lib/verify/search-dialog-checks.test.ts index 1b0d8278..545db8d9 100644 --- a/src/lib/verify/search-dialog-checks.test.ts +++ b/src/lib/verify/search-dialog-checks.test.ts @@ -2,11 +2,16 @@ import { describe, expect, test } from "bun:test"; import { PHASE_1_GROUPED_QUERY_ATTENTION_URL } from "./phase-1-search-checks"; import { evaluateSearchDialogDomSnapshot, + evaluateSearchDialogInputHydrationAfterTyping, + evaluateSearchDialogInputHydrationBeforeQuery, + evaluateSearchDialogInputHydrationOutcome, formatPhase1SearchDialogCheckFailure, PHASE_1_SEARCH_DIALOG_QUERIES, resolveSearchDialogCheckOptionsFromEnv, runPhase1SearchDialogChecks, type SearchDialogDomSnapshot, + type SearchDialogInputHydrationSnapshot, + shouldRetrySearchDialogQuery, } from "./phase-1-search-dialog-checks"; function passingSnapshot( @@ -22,6 +27,21 @@ function passingSnapshot( }; } +function passingInputHydrationSnapshot( + overrides: Partial = {}, +): SearchDialogInputHydrationSnapshot { + return { + inputVisible: true, + inputFocused: true, + inputValue: "GQA", + idleVisible: false, + loadingVisible: true, + resultsVisible: false, + emptyVisible: false, + ...overrides, + }; +} + describe("PHASE_1_SEARCH_DIALOG_QUERIES", () => { test("covers GQA, attention, and KV cache manual-gate queries", () => { expect([...PHASE_1_SEARCH_DIALOG_QUERIES]).toEqual([ @@ -105,6 +125,70 @@ describe("evaluateSearchDialogDomSnapshot", () => { }); }); +describe("search dialog hydration checks", () => { + test("pre-query hydration requires a visible input and idle state", () => { + expect( + evaluateSearchDialogInputHydrationBeforeQuery( + passingInputHydrationSnapshot({ + idleVisible: true, + inputValue: "", + loadingVisible: false, + inputFocused: false, + }), + ), + ).toBeNull(); + + expect( + evaluateSearchDialogInputHydrationBeforeQuery( + passingInputHydrationSnapshot({ + inputVisible: false, + idleVisible: true, + inputValue: "", + loadingVisible: false, + inputFocused: false, + }), + ), + ).toContain("search input is not visible"); + }); + + test("post-typing hydration requires the typed value and hidden idle state", () => { + expect( + evaluateSearchDialogInputHydrationAfterTyping( + passingInputHydrationSnapshot(), + "GQA", + ), + ).toBeNull(); + + expect( + evaluateSearchDialogInputHydrationAfterTyping( + passingInputHydrationSnapshot({ + inputValue: "", + idleVisible: true, + }), + "GQA", + ), + ).toContain('did not update to "GQA"'); + }); + + test("post-query hydration accepts loading, results, or empty states", () => { + expect( + evaluateSearchDialogInputHydrationOutcome( + passingInputHydrationSnapshot(), + ), + ).toBeNull(); + + expect( + evaluateSearchDialogInputHydrationOutcome( + passingInputHydrationSnapshot({ + loadingVisible: false, + resultsVisible: false, + emptyVisible: false, + }), + ), + ).toContain("no loading, results, or empty outcome"); + }); +}); + describe("formatPhase1SearchDialogCheckFailure", () => { test("includes surface, encoded query, and reason", () => { expect( @@ -117,6 +201,34 @@ describe("formatPhase1SearchDialogCheckFailure", () => { }); }); +describe("shouldRetrySearchDialogQuery", () => { + test("retries transient hydration and timeout failures", () => { + expect( + shouldRetrySearchDialogQuery( + "search input did not hydrate in header search dialog within 45000ms", + ), + ).toBeTrue(); + expect( + shouldRetrySearchDialogQuery( + 'timed out waiting for search results in header search dialog for query "GQA" after 45000ms', + ), + ).toBeTrue(); + expect( + shouldRetrySearchDialogQuery( + "no loading, results, or empty outcome appeared after entering a query in header search dialog", + ), + ).toBeTrue(); + }); + + test("does not retry deterministic result failures", () => { + expect( + shouldRetrySearchDialogQuery( + 'empty results state in header search dialog for query "GQA" — expected visible result for /docs/modules/grouped-query-attention', + ), + ).toBeFalse(); + }); +}); + describe("resolveSearchDialogCheckOptionsFromEnv", () => { test("returns pass stub when VERIFY_SEARCH_DIALOG_STUB=pass", async () => { const options = resolveSearchDialogCheckOptionsFromEnv({ diff --git a/src/tests/search/search-api.test.ts b/src/tests/search/search-api.test.ts index c9da38fd..08f3a9af 100644 --- a/src/tests/search/search-api.test.ts +++ b/src/tests/search/search-api.test.ts @@ -353,7 +353,13 @@ describe("docs search static client", () => { const results = await client.search("attention"); expect(results.length).toBeGreaterThan(0); - expect(resultsIncludeUrl(results, BIDIRECTIONAL_ATTENTION_URL)).toBe(true); + expect( + results.some( + (result) => + result.url.includes("/docs/modules/") && + result.url.includes("attention"), + ), + ).toBe(true); }); test("orama static client includes grouped-query attention for KV cache", async () => {