From e8da4a511827f04f4a6d8ae460ba7965ba2e5bab Mon Sep 17 00:00:00 2001 From: Clay Good Date: Tue, 4 Aug 2026 10:15:54 -0500 Subject: [PATCH 1/5] docs(workflows): add lifecycle diagrams --- docs/workflows.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/docs/workflows.md b/docs/workflows.md index b63f7f7491..f4b33b8ca4 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -28,6 +28,57 @@ OPSX (fluid actions): > **Customization:** OPSX workflows are driven by schemas that define artifact sequences. See [Customization](customization.md) for details on creating custom schemas. +## Workflow at a Glance + +The default workflow stays fluid: exploration and verification are optional, and +you can update planning artifacts whenever implementation reveals something new. + +```mermaid +flowchart LR + Idea["Idea or problem"] --> Explore["/opsx:explore
(optional)"] + Idea --> Propose["/opsx:propose"] + Explore --> Propose + Propose --> Review{"Planning artifacts
ready?"} + Review -->|"Refine"| Update["/opsx:update"] + Update --> Review + Review -->|"Implement"| Apply["/opsx:apply"] + Apply --> Verify["/opsx:verify
(optional, expanded profile)"] + Apply --> Sync["/opsx:sync
(optional before archive)"] + Verify --> Sync + Verify --> Archive["/opsx:archive"] + Sync --> Archive +``` + +The AI assistant drives the workflow, while the CLI provides deterministic +scaffolding, status, and artifact instructions: + +```mermaid +sequenceDiagram + actor Human + participant Assistant as AI assistant + participant CLI as OpenSpec CLI + participant Files as Project files + + Human->>Assistant: /opsx:propose "change" + Assistant->>CLI: openspec new change + CLI->>Files: Scaffold change metadata + Assistant->>CLI: Request status and artifact instructions + CLI-->>Assistant: Build order, paths, and templates + Assistant->>Files: Write proposal, specs, design, and tasks + Assistant-->>Human: Present artifacts for review + + Human->>Assistant: /opsx:apply + Assistant->>CLI: Request apply instructions + CLI-->>Assistant: Context files and task state + Assistant->>Files: Implement tasks and update checkboxes + Assistant-->>Human: Report implementation status + + Human->>Assistant: /opsx:archive + Assistant->>CLI: Check artifact and task status + Assistant->>Files: Sync accepted spec changes and archive the change + Assistant-->>Human: Report archive location and sync result +``` + ## Two Modes ### Default Quick Path (`core` profile) From 1857603c35f6a93a2ebe2270bfb05aba894e1075 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Tue, 4 Aug 2026 10:24:07 -0500 Subject: [PATCH 2/5] docs(workflows): clarify optional archive paths --- docs/workflows.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/workflows.md b/docs/workflows.md index f4b33b8ca4..075a9345a2 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -42,10 +42,11 @@ flowchart LR Review -->|"Refine"| Update["/opsx:update"] Update --> Review Review -->|"Implement"| Apply["/opsx:apply"] + Apply --> Archive["/opsx:archive"] Apply --> Verify["/opsx:verify
(optional, expanded profile)"] Apply --> Sync["/opsx:sync
(optional before archive)"] Verify --> Sync - Verify --> Archive["/opsx:archive"] + Verify --> Archive Sync --> Archive ``` @@ -75,8 +76,20 @@ sequenceDiagram Human->>Assistant: /opsx:archive Assistant->>CLI: Check artifact and task status - Assistant->>Files: Sync accepted spec changes and archive the change + CLI-->>Assistant: Paths, completion state, and delta specs + opt Delta specs exist + Assistant-->>Human: Offer to sync before archiving + alt Sync accepted + Human->>Assistant: Confirm sync + Assistant->>Files: Merge accepted delta specs + else Sync skipped + Human->>Assistant: Archive without syncing + end + end + Assistant->>Files: Move the change into the archive Assistant-->>Human: Report archive location and sync result + + Note over Human,CLI: Non-interactive: openspec archive change-name --yes accepts prompts and syncs ``` ## Two Modes From ddab90b8d5c86142054419c1d327ca727b394da9 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Tue, 4 Aug 2026 10:44:38 -0500 Subject: [PATCH 3/5] docs(workflows): correct lifecycle diagrams --- docs/workflows.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/workflows.md b/docs/workflows.md index 075a9345a2..78d27a32c0 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -34,7 +34,7 @@ The default workflow stays fluid: exploration and verification are optional, and you can update planning artifacts whenever implementation reveals something new. ```mermaid -flowchart LR +flowchart TD Idea["Idea or problem"] --> Explore["/opsx:explore
(optional)"] Idea --> Propose["/opsx:propose"] Explore --> Propose @@ -42,11 +42,15 @@ flowchart LR Review -->|"Refine"| Update["/opsx:update"] Update --> Review Review -->|"Implement"| Apply["/opsx:apply"] + Apply -->|"Plan changed"| Update Apply --> Archive["/opsx:archive"] - Apply --> Verify["/opsx:verify
(optional, expanded profile)"] + Apply --> Verify["/opsx:verify
(optional, custom selection)"] Apply --> Sync["/opsx:sync
(optional before archive)"] - Verify --> Sync - Verify --> Archive + Verify --> Verified{"Ready to archive?"} + Verified -->|"Fix implementation"| Apply + Verified -->|"Revise plan"| Update + Verified -->|"Ready"| Sync + Verified -->|"Ready"| Archive Sync --> Archive ``` @@ -58,14 +62,14 @@ sequenceDiagram actor Human participant Assistant as AI assistant participant CLI as OpenSpec CLI - participant Files as Project files + participant Files as Planning and implementation files Human->>Assistant: /opsx:propose "change" Assistant->>CLI: openspec new change CLI->>Files: Scaffold change metadata Assistant->>CLI: Request status and artifact instructions CLI-->>Assistant: Build order, paths, and templates - Assistant->>Files: Write proposal, specs, design, and tasks + Assistant->>Files: Write schema-defined planning artifacts Assistant-->>Human: Present artifacts for review Human->>Assistant: /opsx:apply @@ -75,13 +79,14 @@ sequenceDiagram Assistant-->>Human: Report implementation status Human->>Assistant: /opsx:archive - Assistant->>CLI: Check artifact and task status - CLI-->>Assistant: Paths, completion state, and delta specs + Assistant->>CLI: Request archive inputs and artifact status + CLI-->>Assistant: Planning paths and artifact completion + Assistant->>Files: Read task state and compare delta specs opt Delta specs exist Assistant-->>Human: Offer to sync before archiving alt Sync accepted Human->>Assistant: Confirm sync - Assistant->>Files: Merge accepted delta specs + Assistant->>Files: Merge delta specs into main specs else Sync skipped Human->>Assistant: Archive without syncing end @@ -89,7 +94,7 @@ sequenceDiagram Assistant->>Files: Move the change into the archive Assistant-->>Human: Report archive location and sync result - Note over Human,CLI: Non-interactive: openspec archive change-name --yes accepts prompts and syncs + Note over Human,CLI: CLI alternative: openspec archive change-name --yes skips confirmation prompts; it still validates, then applies any delta specs and archives ``` ## Two Modes From 2e06da9f7a8ed8073ffa92bde60018bd1440c903 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Tue, 4 Aug 2026 11:07:15 -0500 Subject: [PATCH 4/5] docs(website): render Mermaid diagrams --- website/components/mdx.tsx | 2 ++ website/components/mermaid.tsx | 37 ++++++++++++++++++++++++++++++++++ website/lib/source.ts | 12 ++++++++++- website/package.json | 1 + website/pnpm-lock.yaml | 22 ++++++++++++++++++++ website/source.config.ts | 7 +++++-- 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 website/components/mermaid.tsx diff --git a/website/components/mdx.tsx b/website/components/mdx.tsx index a407f51f42..d638e730f4 100644 --- a/website/components/mdx.tsx +++ b/website/components/mdx.tsx @@ -2,6 +2,7 @@ import defaultMdxComponents from 'fumadocs-ui/mdx'; import { Tab, Tabs } from 'fumadocs-ui/components/tabs'; import { Step, Steps } from 'fumadocs-ui/components/steps'; import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; +import { Mermaid } from '@/components/mermaid'; import type { MDXComponents } from 'mdx/types'; export function getMDXComponents(components?: MDXComponents) { @@ -13,6 +14,7 @@ export function getMDXComponents(components?: MDXComponents) { Steps, Accordion, Accordions, + Mermaid, ...components, } satisfies MDXComponents; } diff --git a/website/components/mermaid.tsx b/website/components/mermaid.tsx new file mode 100644 index 0000000000..3d8b8537ae --- /dev/null +++ b/website/components/mermaid.tsx @@ -0,0 +1,37 @@ +import { renderMermaidSVG } from 'beautiful-mermaid'; +import { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock'; + +export function Mermaid({ chart }: { chart: string }) { + try { + // beautiful-mermaid injects remote font imports; the site already provides Inter. + const svg = renderMermaidSVG(chart, { + bg: 'var(--color-fd-background)', + fg: 'var(--color-fd-foreground)', + transparent: true, + }).replace(/\s*@import url\([^)]*\);\s*/g, ''); + + return ( +
+
+ +
Mermaid diagram source: {chart}
+
+ ); + } catch { + return ( + +
{chart}
+
+ ); + } +} diff --git a/website/lib/source.ts b/website/lib/source.ts index a480d10a99..e40147f089 100644 --- a/website/lib/source.ts +++ b/website/lib/source.ts @@ -1,4 +1,5 @@ import { docs } from 'collections/server'; +import { renderPlaceholder } from 'fumadocs-core/mdx-plugins/remark-llms.runtime'; import { loader } from 'fumadocs-core/source'; import { icons } from 'lucide-react'; import { createElement } from 'react'; @@ -37,8 +38,17 @@ export function getPageMarkdownUrl(page: (typeof source)['$inferPage']) { export async function getLLMText(page: (typeof source)['$inferPage']) { const processed = await page.data.getText('processed'); + const markdown = await renderPlaceholder(processed, { + Mermaid({ attributes }) { + if (typeof attributes.chart !== 'string') return ''; + + return `\`\`\`mermaid +${attributes.chart} +\`\`\``; + }, + }); return `# ${page.data.title} (${page.url}) -${processed}`; +${markdown}`; } diff --git a/website/package.json b/website/package.json index 15b473faf3..6bc26c4cf6 100644 --- a/website/package.json +++ b/website/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@orama/orama": "^3.1.18", + "beautiful-mermaid": "^1.1.3", "fumadocs-core": "^16.12.1", "fumadocs-mdx": "^15.2.1", "fumadocs-ui": "^16.12.1", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index f9766b7e0d..53a752ce50 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -16,6 +16,9 @@ importers: '@orama/orama': specifier: ^3.1.18 version: 3.1.18 + beautiful-mermaid: + specifier: ^1.1.3 + version: 1.1.3 fumadocs-core: specifier: ^16.12.1 version: 16.12.1(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.18)(lucide-react@1.27.0(react@19.2.8))(next@16.2.12(@types/node@26.1.2)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) @@ -1133,6 +1136,9 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + beautiful-mermaid@1.1.3: + resolution: {integrity: sha512-TItrtrAyHp1vwFfFVYauWGrquouk/6SS21Aq3RsxindSYZODcN4xYrPZD6BiZRU+o5mKJzDPz9MUSMvELdylyg==} + boxen@7.0.0: resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} engines: {node: '>=14.16'} @@ -1285,6 +1291,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + elkjs@0.11.1: + resolution: {integrity: sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1299,6 +1308,10 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} @@ -3211,6 +3224,11 @@ snapshots: baseline-browser-mapping@2.11.11: {} + beautiful-mermaid@1.1.3: + dependencies: + elkjs: 0.11.1 + entities: 7.0.1 + boxen@7.0.0: dependencies: ansi-align: 3.0.1 @@ -3341,6 +3359,8 @@ snapshots: eastasianwidth@0.2.0: {} + elkjs@0.11.1: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -3352,6 +3372,8 @@ snapshots: entities@6.0.1: {} + entities@7.0.1: {} + esast-util-from-estree@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 diff --git a/website/source.config.ts b/website/source.config.ts index 628513c667..b3c9a76773 100644 --- a/website/source.config.ts +++ b/website/source.config.ts @@ -1,5 +1,6 @@ import { defineConfig, defineDocs } from 'fumadocs-mdx/config'; import { metaSchema, pageSchema } from 'fumadocs-core/source/schema'; +import { remarkMdxMermaid } from 'fumadocs-core/mdx-plugins'; import { z } from 'zod'; // You can customize Zod schemas for frontmatter and `meta.json` here @@ -12,7 +13,9 @@ export const docs = defineDocs({ // page" link opens the real source rather than the generated mirror. schema: pageSchema.extend({ githubSource: z.string().optional() }), postprocess: { - includeProcessedMarkdown: true, + includeProcessedMarkdown: { + mdxAsPlaceholder: ['Mermaid'], + }, }, }, meta: { @@ -22,6 +25,6 @@ export const docs = defineDocs({ export default defineConfig({ mdxOptions: { - // MDX options + remarkPlugins: [remarkMdxMermaid], }, }); From 4c74f4079b329f6a03264d32331cb7932ed15d72 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Tue, 4 Aug 2026 11:23:57 -0500 Subject: [PATCH 5/5] fix(website): preserve Mermaid label text --- website/components/mermaid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/components/mermaid.tsx b/website/components/mermaid.tsx index 3d8b8537ae..62cc61ebb4 100644 --- a/website/components/mermaid.tsx +++ b/website/components/mermaid.tsx @@ -8,7 +8,7 @@ export function Mermaid({ chart }: { chart: string }) { bg: 'var(--color-fd-background)', fg: 'var(--color-fd-foreground)', transparent: true, - }).replace(/\s*@import url\([^)]*\);\s*/g, ''); + }).replace(/^\s*@import url\(['"]https:\/\/fonts\.googleapis\.com\/[^)]*\);\s*$/m, ''); return (