diff --git a/package.json b/package.json index 5813599..1891a8d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "dev": "vocs dev", - "lint": "tsc --noEmit", + "lint": "tsc --noEmit && node scripts/check-status-badges.mjs", "build": "vocs build && node scripts/copy-markdown-routes.mjs", "preview": "vocs preview" }, diff --git a/scripts/check-status-badges.mjs b/scripts/check-status-badges.mjs new file mode 100644 index 0000000..850d36d --- /dev/null +++ b/scripts/check-status-badges.mjs @@ -0,0 +1,70 @@ +import { readdir, readFile } from 'node:fs/promises' +import { join, relative } from 'node:path' +import { fileURLToPath } from 'node:url' + +const pagesRoot = fileURLToPath(new URL('../src/pages/', import.meta.url)) +const expectedStyle = { + Shipped: 'success', + Partial: 'warning', + Planned: undefined, +} + +async function collectMdxFiles(directory) { + const entries = await readdir(directory, { withFileTypes: true }) + const nested = await Promise.all( + entries.map((entry) => { + const path = join(directory, entry.name) + if (entry.isDirectory()) return collectMdxFiles(path) + return entry.isFile() && entry.name.endsWith('.mdx') ? [path] : [] + }), + ) + return nested.flat() +} + +const files = await collectMdxFiles(pagesRoot) +const errors = [] +let badgedPageCount = 0 +let unbadgedPageCount = 0 + +for (const file of files) { + const source = await readFile(file, 'utf8') + const matches = [ + ...source.matchAll(/:badge\[(Shipped|Partial|Planned)\](?:\{([^}]+)\})?/g), + ] + const page = relative(pagesRoot, file).replaceAll('\\', '/') + const expectsBadge = page !== 'index.mdx' && !page.startsWith('use-bloom/') + + if (!expectsBadge) { + unbadgedPageCount += 1 + if (matches.length !== 0) { + errors.push(`${page}: homepage and Use Bloom pages must not have status badges`) + } + continue + } + + badgedPageCount += 1 + if (matches.length !== 1) { + errors.push(`${page}: expected exactly one status badge, found ${matches.length}`) + continue + } + + const [, status, style] = matches[0] + if (style !== expectedStyle[status]) { + const expected = expectedStyle[status] ?? 'no style' + errors.push(`${page}: ${status} must use ${expected}`) + } + + const firstLines = source.split('\n').slice(0, 15).join('\n') + if (!firstLines.includes(matches[0][0])) { + errors.push(`${page}: status badge must appear near the top of the page`) + } +} + +if (errors.length > 0) { + console.error(errors.join('\n')) + process.exitCode = 1 +} else { + console.log( + `Verified ${badgedPageCount} badged pages and ${unbadgedPageCount} intentionally unbadged pages.`, + ) +} diff --git a/src/pages/_root.css b/src/pages/_root.css index 96fb988..16f374f 100644 --- a/src/pages/_root.css +++ b/src/pages/_root.css @@ -13,6 +13,19 @@ } } +/* Keep implementation status at the far edge of the page-title box. */ +[data-v-content] > h1:has(> [data-v-badge]) { + display: flex; + align-items: baseline; + flex-wrap: wrap; + gap: 0.75rem; +} + +[data-v-content] > h1 > [data-v-badge] { + flex: 0 0 auto; + margin-inline-start: auto; +} + .bloom-expected-output { display: inline-flex; align-items: center; diff --git a/src/pages/integrators/agent-setup.mdx b/src/pages/integrators/agent-setup.mdx index 4fafd12..eebe3f2 100644 --- a/src/pages/integrators/agent-setup.mdx +++ b/src/pages/integrators/agent-setup.mdx @@ -1,4 +1,4 @@ -# Agent setup +# Agent setup :badge[Shipped]{success} The preferred user prompt is: diff --git a/src/pages/integrators/integrating.mdx b/src/pages/integrators/integrating.mdx index 7e203db..2271506 100644 --- a/src/pages/integrators/integrating.mdx +++ b/src/pages/integrators/integrating.mdx @@ -1,4 +1,4 @@ -# Integrating Bloom +# Integrating Bloom :badge[Planned] Bloom and walletFS can help you achieve your agentic use cases safely and quickly. diff --git a/src/pages/integrators/quickstart.mdx b/src/pages/integrators/quickstart.mdx index 84a03b2..f6ab052 100644 --- a/src/pages/integrators/quickstart.mdx +++ b/src/pages/integrators/quickstart.mdx @@ -1,4 +1,4 @@ -# Quickstart +# Quickstart :badge[Shipped]{success} This walkthrough uses the mounted `/bloom` filesystem. Bloom’s command-specific fallbacks exist for constrained environments, but normal shell tools against the mount are the default interface. diff --git a/src/pages/introduction/benefits.mdx b/src/pages/introduction/benefits.mdx index 240c21e..ba20d86 100644 --- a/src/pages/introduction/benefits.mdx +++ b/src/pages/introduction/benefits.mdx @@ -1,4 +1,4 @@ -# Benefits +# Benefits :badge[Partial]{warning} Bloom is designed around the operating model agents already understand: files. Our initial hypothesis is confirmed from early testing (not public yet): a filesystem based approach to agentic tool use spends less tokens while achieving higher tool call reliability. We plan to publish our findings soon. Other benefits include: diff --git a/src/pages/introduction/core-concepts.mdx b/src/pages/introduction/core-concepts.mdx index f0191d2..320731e 100644 --- a/src/pages/introduction/core-concepts.mdx +++ b/src/pages/introduction/core-concepts.mdx @@ -1,4 +1,4 @@ -# Core concepts +# Core concepts :badge[Shipped]{success} ## Virtual filesystem diff --git a/src/pages/introduction/demos.mdx b/src/pages/introduction/demos.mdx index 05dab9b..35389a9 100644 --- a/src/pages/introduction/demos.mdx +++ b/src/pages/introduction/demos.mdx @@ -1,4 +1,4 @@ -# Demos +# Demos :badge[Shipped]{success} ## x402 Paid HTTP Request diff --git a/src/pages/introduction/what-is-bloom.mdx b/src/pages/introduction/what-is-bloom.mdx index ed162d2..a9f2df9 100644 --- a/src/pages/introduction/what-is-bloom.mdx +++ b/src/pages/introduction/what-is-bloom.mdx @@ -1,4 +1,4 @@ -# What is Bloom? +# What is Bloom? :badge[Partial]{warning} Bloom is a framework for creating agent-safe software components. The first application of Bloom is an agentic Ethereum wallet. We call this walletFS. diff --git a/src/pages/petals/authoring.mdx b/src/pages/petals/authoring.mdx index 545bc7c..bd3dff0 100644 --- a/src/pages/petals/authoring.mdx +++ b/src/pages/petals/authoring.mdx @@ -1,4 +1,4 @@ -# Authoring Petals +# Authoring Petals :badge[Partial]{warning} The petal authoring surface is a small Rust framework. diff --git a/src/pages/petals/model.mdx b/src/pages/petals/model.mdx index eda7fe0..0016c11 100644 --- a/src/pages/petals/model.mdx +++ b/src/pages/petals/model.mdx @@ -1,4 +1,4 @@ -# Petal Model +# Petal Model :badge[Partial]{warning} Bloom-native petals are deterministic wasm modules called by the chain executor. They are not ordinary off-chain plugins and they do not have ambient access to diff --git a/src/pages/petals/overview.mdx b/src/pages/petals/overview.mdx index e0a99c7..ff49ce2 100644 --- a/src/pages/petals/overview.mdx +++ b/src/pages/petals/overview.mdx @@ -1,4 +1,4 @@ -# Petals +# Petals :badge[Partial]{warning} ## ⚠️ WARNING - EARLY / UNFINISHED diff --git a/src/pages/petals/ptbs-and-pipes.mdx b/src/pages/petals/ptbs-and-pipes.mdx index 16268dc..ac4e625 100644 --- a/src/pages/petals/ptbs-and-pipes.mdx +++ b/src/pages/petals/ptbs-and-pipes.mdx @@ -1,4 +1,4 @@ -# PTBs And Pipes +# PTBs And Pipes :badge[Partial]{warning} Petals are called through programmable transaction blocks. A PTB is an ordered list of commands plus signer, gas, and expiry metadata. diff --git a/src/pages/petals/quickstart.mdx b/src/pages/petals/quickstart.mdx index ad06e99..9a7bdb8 100644 --- a/src/pages/petals/quickstart.mdx +++ b/src/pages/petals/quickstart.mdx @@ -1,4 +1,4 @@ -# Quickstart +# Quickstart :badge[Partial]{warning} This guide shows the shape of a minimal Bloom-native petal, then a slightly more involved object petal. The examples are intentionally small; the standard diff --git a/src/pages/petals/testing.mdx b/src/pages/petals/testing.mdx index 3955f06..6591138 100644 --- a/src/pages/petals/testing.mdx +++ b/src/pages/petals/testing.mdx @@ -1,4 +1,4 @@ -# Testing Petals +# Testing Petals :badge[Partial]{warning} Petal testing usually happens at three levels. diff --git a/src/pages/reference/development.mdx b/src/pages/reference/development.mdx index 59cbb21..578cc59 100644 --- a/src/pages/reference/development.mdx +++ b/src/pages/reference/development.mdx @@ -1,4 +1,4 @@ -# Development +# Development :badge[Shipped]{success} ## Build diff --git a/src/pages/reference/limitations.mdx b/src/pages/reference/limitations.mdx index 0974922..8974333 100644 --- a/src/pages/reference/limitations.mdx +++ b/src/pages/reference/limitations.mdx @@ -1,4 +1,4 @@ -# Limitations +# Limitations :badge[Partial]{warning} Bloom is useful today, but several boundaries are explicit. diff --git a/src/pages/reference/project-map.mdx b/src/pages/reference/project-map.mdx index b5e98b8..0c331a6 100644 --- a/src/pages/reference/project-map.mdx +++ b/src/pages/reference/project-map.mdx @@ -1,4 +1,4 @@ -# Project map +# Project map :badge[Partial]{warning} This map connects public docs concepts to the Bloom source files that currently implement them. diff --git a/src/pages/reference/supported-chains.mdx b/src/pages/reference/supported-chains.mdx index c53eaba..6915efe 100644 --- a/src/pages/reference/supported-chains.mdx +++ b/src/pages/reference/supported-chains.mdx @@ -1,4 +1,4 @@ -# Supported chains +# Supported chains :badge[Shipped]{success} `bloom init` ships read-ready defaults for: diff --git a/src/pages/reference/technical-architecture.mdx b/src/pages/reference/technical-architecture.mdx index ecbd825..7900d56 100644 --- a/src/pages/reference/technical-architecture.mdx +++ b/src/pages/reference/technical-architecture.mdx @@ -1,4 +1,4 @@ -# Technical architecture +# Technical architecture :badge[Partial]{warning} Bloom is a Rust workspace split into focused crates around a daemon, virtual filesystem, wallet transaction engine, and chain integrations. diff --git a/src/pages/wallet/defi-intents.mdx b/src/pages/wallet/defi-intents.mdx index ca55b71..a8f4427 100644 --- a/src/pages/wallet/defi-intents.mdx +++ b/src/pages/wallet/defi-intents.mdx @@ -1,4 +1,4 @@ -# DeFi intents +# DeFi intents :badge[Partial]{warning} Bloom exposes DeFi routing under `/bloom/defi/intents//`. The current implementation uses Enso Shortcuts. diff --git a/src/pages/wallet/filesystem-guide.mdx b/src/pages/wallet/filesystem-guide.mdx index 8ffac34..9e30e29 100644 --- a/src/pages/wallet/filesystem-guide.mdx +++ b/src/pages/wallet/filesystem-guide.mdx @@ -1,4 +1,4 @@ -# Filesystem guide +# Filesystem guide :badge[Partial]{warning} Bloom’s VFS is normally mounted at `/bloom`. Use standard shell tools against that mount: reads are `cat`/`ls`, writes are file writes. diff --git a/src/pages/wallet/security-model.mdx b/src/pages/wallet/security-model.mdx index 948e17b..ea6addd 100644 --- a/src/pages/wallet/security-model.mdx +++ b/src/pages/wallet/security-model.mdx @@ -1,4 +1,4 @@ -# Security model +# Security model :badge[Shipped]{success} Bloom is built around explicit control points between an agent and user funds. diff --git a/src/pages/wallet/use-cases.mdx b/src/pages/wallet/use-cases.mdx index 8e9f9ad..09efbf3 100644 --- a/src/pages/wallet/use-cases.mdx +++ b/src/pages/wallet/use-cases.mdx @@ -1,6 +1,6 @@ import { ExpectedOutput } from '../../components/ExpectedOutput' -# Use cases +# Use cases :badge[Shipped]{success} Bloom’s filesystem model lets Ethereum power users compose chain reads, wallet state, encoding helpers, and transaction staging with ordinary shell tooling. The examples below assume Bloom is mounted at `/bloom` and that you review every generated plan before signing. diff --git a/src/pages/wallet/wallets-and-transactions.mdx b/src/pages/wallet/wallets-and-transactions.mdx index f02a4f9..46edc90 100644 --- a/src/pages/wallet/wallets-and-transactions.mdx +++ b/src/pages/wallet/wallets-and-transactions.mdx @@ -1,4 +1,4 @@ -# Wallets and transactions +# Wallets and transactions :badge[Shipped]{success} Bloom wallets are local encrypted keys or watch-only addresses exposed through the filesystem. diff --git a/src/pages/wallet/watches-and-simulation.mdx b/src/pages/wallet/watches-and-simulation.mdx index f351304..1e434a3 100644 --- a/src/pages/wallet/watches-and-simulation.mdx +++ b/src/pages/wallet/watches-and-simulation.mdx @@ -1,4 +1,4 @@ -# Watches and simulation +# Watches and simulation :badge[Shipped]{success} ## Watches