import assert from 'node:assert/strict'; import test from 'node:test'; import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { assertNoOpenHolds, buildPageDefinitions, generateSeoPages, renderMarkdown, renderStaticPage } from './generate-seo-pages.mjs'; const frontendDir = resolve(dirname(fileURLToPath(import.meta.url)), '..'); test('emits a canonical crawlable page for every public route', async () => { const [translationText, useCaseText, guideText, indexHtml] = await Promise.all([ readFile(resolve(frontendDir, 'src/i18n/locales/en.json'), 'utf8'), readFile(resolve(frontendDir, 'src/content/use-cases.json'), 'utf8'), readFile(resolve(frontendDir, 'src/content/guides.json'), 'utf8'), readFile(resolve(frontendDir, 'index.html'), 'utf8'), ]); const translations = JSON.parse(translationText); const useCases = JSON.parse(useCaseText); const guides = JSON.parse(guideText); const pages = buildPageDefinitions({ landing: translations.landing, compare: translations.compare, useCases, guides }); assert.equal(pages.length, 97); assert.deepEqual(pages.map((page) => page.path), [ '/', '/compare/', '/compare/openagents/', '/compare/github-agent-hq/', '/use-cases/team-chat/', '/use-cases/agent-collab/', '/use-cases/research-desk/', '/use-cases/daily-digest/', '/use-cases/community/', '/use-cases/pod-browser/', '/use-cases/app-marketplace/', '/guides/', '/guides/multi-agent-collaboration-platform/', '/guides/ai-agent-workspace/', '/guides/ai-agent-task-management/', '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-memory/', '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-handoffs/', '/guides/how-to-build-an-ai-agent-team/', '/guides/agent-to-agent-messaging/', '/guides/self-hosted-ai-agent-platform/', '/guides/ai-agent-permissions-and-tokens/', '/guides/connect-cursor-shared-workspace/', '/guides/ai-agent-observability/', '/guides/ai-agent-events/', '/guides/multi-agent-vs-single-agent/', '/guides/ai-agent-collaboration-patterns/', '/guides/onboarding-an-ai-agent-to-your-team/', '/guides/ai-agent-discord-integration/', '/guides/what-is-an-ai-agent-runtime/', '/guides/ai-agent-heartbeats-and-scheduled-work/', '/guides/ai-agent-marketplace-roles/', '/guides/connect-a-custom-agent-http-api/', '/guides/what-is-an-agent-pod/', '/guides/connect-openclaw-agent/', '/guides/ai-agent-security-best-practices/', '/guides/ai-agent-cli/', '/guides/ai-agent-orchestration/', '/guides/ai-agent-skills/', '/guides/autonomous-ai-agents/', '/guides/ai-agent-sandboxing/', '/guides/ai-agent-tools/', '/guides/prompt-injection-defense-for-ai-agents/', '/guides/mcp-for-ai-agent-teams/', '/guides/what-is-agentic-ai/', '/guides/what-is-an-ai-agent/', '/guides/context-engineering-for-ai-agents/', '/guides/how-to-evaluate-ai-agents/', '/guides/ai-agent-vs-chatbot/', '/guides/ai-agent-use-cases/', '/guides/human-ai-collaboration/', '/guides/agentic-workflows/', '/guides/ai-agents-for-project-management/', '/guides/how-to-write-ai-agent-instructions/', '/guides/ai-agents-for-research/', '/guides/ai-agents-for-customer-support/', '/guides/what-is-a-multi-agent-system/', '/guides/ai-agent-glossary/', '/guides/ai-agent-governance/', '/guides/ai-agents-for-software-development/', '/guides/ai-agent-roles/', '/guides/ai-agent-escalation/', '/guides/ai-agent-acceptance-criteria/', '/guides/ai-agent-decision-packet/', '/guides/ai-agent-audit-trail/', '/guides/ai-agent-no-op/', '/guides/ai-agent-source-of-record/', '/guides/ai-agent-scope-creep/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-blockers/', '/guides/ai-agent-status-updates/', '/guides/ai-agent-work-contract/', '/guides/ai-agent-follow-on-work/', '/guides/ai-agent-verification-path/', '/guides/ai-agent-resume-conditions/', '/guides/ai-agent-review-decisions/', '/guides/ai-agent-non-goals/', '/guides/ai-agent-evidence-labels/', '/guides/ai-agent-dependency-management/', '/guides/ai-agent-task-intake/', '/guides/ai-agent-decision-owner/', '/guides/ai-agent-artifact-versions/', '/guides/ai-agent-task-closure/', '/guides/ai-agent-context-packet/', '/guides/ai-agent-focused-threads/', '/guides/ai-agent-approval-boundaries/', '/guides/ai-agent-retained-context/', '/guides/ai-agent-revision-loop/', '/guides/ai-agent-task-splitting/', '/guides/ai-agent-interim-results/', '/guides/ai-agent-audience-boundaries/', '/guides/ai-agent-stop-conditions/', '/guides/ai-agent-change-requests/', '/guides/ai-agent-data-boundaries/', '/guides/ai-agent-disagreement-resolution/', '/guides/ai-agent-task-prioritization/', ]); assert.deepEqual(pages[0].schema['@graph'].map((item) => item['@type']), [ 'Organization', 'WebSite', 'SoftwareApplication', 'WebPage', ]); const organization = pages[0].schema['@graph'].find((item) => item['@type'] === 'Organization'); const website = pages[0].schema['@graph'].find((item) => item['@type'] === 'WebSite'); const softwareApplication = pages[0].schema['@graph'].find((item) => item['@type'] === 'SoftwareApplication'); assert.equal(organization['@id'], 'https://commonly.me/#organization'); assert.equal(organization.name, 'Commonly AI'); assert.equal(softwareApplication.name, 'Commonly AI'); assert.deepEqual(organization.alternateName, ['Commonly', 'commonly.me']); assert.deepEqual(organization.sameAs, [ 'https://github.com/Team-Commonly/commonly', 'https://www.npmjs.com/package/@commonlyai/mcp', 'https://discord.gg/NsS3fzsJDw', ]); assert.equal(website['@id'], 'https://commonly.me/#website'); assert.deepEqual(website.publisher, { '@id': organization['@id'] }); assert.deepEqual(softwareApplication.publisher, { '@id': organization['@id'] }); const landingWebPage = pages[0].schema['@graph'].find((item) => item['@type'] === 'WebPage'); assert.equal(landingWebPage.name, pages[0].title); assert.equal(landingWebPage.description, pages[0].description); for (const page of pages) { const graph = page.schema['@graph'] || [page.schema]; const webPage = graph.find((item) => item['@type'] === 'WebPage'); assert.deepEqual(webPage.isPartOf, { '@id': website['@id'] }); } const guidePages = pages.filter((page) => page.path.startsWith('/guides/') && page.path !== '/guides/'); const refreshedGuidePaths = new Set([ '/guides/multi-agent-collaboration-platform/', '/guides/ai-agent-workspace/', '/guides/ai-agent-task-management/', '/guides/connect-claude-codex-shared-workspace/', ]); assert.equal(guidePages.length, 85); for (const guide of guidePages) { assert.equal(guide.ogType, 'article'); const article = guide.schema['@graph'].find((item) => item['@type'] === 'Article'); const webPage = guide.schema['@graph'].find((item) => item['@type'] === 'WebPage'); assert.equal(article.author['@type'], 'Organization'); assert.equal(webPage.reviewedBy['@type'], 'Organization'); assert.match(article.datePublished, /^2026-(?:08|09)-\d{2}$/); assert.match(article.dateModified, /^2026-(?:08|09)-\d{2}$/); if (refreshedGuidePaths.has(guide.path)) { assert.equal(article.dateModified, '2026-08-30'); } } const taskManagementGuide = guidePages.find((page) => page.path === '/guides/ai-agent-task-management/'); assert.equal(taskManagementGuide.title, 'AI Agent Task Management: Humans + Agents | Commonly AI'); const taskManagementArticle = taskManagementGuide.schema['@graph'].find((item) => item['@type'] === 'Article'); assert.equal(taskManagementArticle.datePublished, '2026-08-25'); assert.equal(taskManagementArticle.dateModified, '2026-08-30'); const guideTemplate = '
'; const sharedWorkspaceGuide = guidePages.find((page) => page.path === '/guides/connect-claude-codex-shared-workspace/'); assert.equal(sharedWorkspaceGuide.title, 'Connect Claude Code and Codex to a Shared Workspace | Commonly AI'); const sharedWorkspaceArticle = sharedWorkspaceGuide.schema['@graph'].find((item) => item['@type'] === 'Article'); assert.equal(sharedWorkspaceArticle.datePublished, '2026-08-26'); assert.equal(sharedWorkspaceArticle.dateModified, '2026-08-30'); const taskManagementHtml = renderStaticPage(guideTemplate, taskManagementGuide); assert.match(taskManagementHtml, /By Commonly · Reviewed by Commonly SEO team/); assert.match(taskManagementHtml, /article:published_time" content="2026-08-25"/); assert.match(taskManagementHtml, /article:modified_time" content="2026-08-30"/); assert.match(taskManagementHtml, /href="\/guides\/multi-agent-collaboration-platform\/"/); assert.match(taskManagementHtml, /href="\/guides\/ai-agent-workspace\/"/); assert.doesNotMatch(taskManagementHtml, /document\.documentElement/); assert.doesNotMatch(taskManagementHtml, /popstate/); assert.doesNotMatch(taskManagementHtml, /modulepreload/); assert.doesNotMatch(taskManagementHtml, /type="module"/); assert.doesNotMatch(taskManagementHtml, /src="\/assets\/index-/); assert.match(taskManagementHtml, /#seo-page \{ display: block !important; \}/); assert.match(taskManagementHtml, /#seo-page \{ color: #fff; \}/); const sharedWorkspaceHtml = renderStaticPage(guideTemplate, sharedWorkspaceGuide); assert.match(sharedWorkspaceHtml, /codex mcp add commonly/); assert.match(sharedWorkspaceHtml, /class="language-bash"/); const memoryGuide = guidePages.find((page) => page.path === '/guides/ai-agent-memory/'); assert.equal(memoryGuide.title, 'Shared Memory for AI Agents: Private, Shared, Durable | Commonly AI'); const memoryHtml = renderStaticPage(guideTemplate, memoryGuide); assert.match(memoryHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(memoryHtml, //); assert.match(memoryHtml, /https:\/\/docs\.langchain\.com\/oss\/python\/deepagents\/memory/); assert.match(memoryHtml, /href="\/guides\/connect-claude-codex-shared-workspace\//); assert.match(memoryHtml, /href="\/guides\/human-in-the-loop-ai-agents\//); assert.match(memoryHtml, /href="\/guides\/agent-to-agent-messaging\//); const humanReviewGuide = guidePages.find((page) => page.path === '/guides/human-in-the-loop-ai-agents/'); assert.equal(humanReviewGuide.title, 'Human-in-the-Loop Review for AI Agent Teams | Commonly AI'); const humanReviewHtml = renderStaticPage(guideTemplate, humanReviewGuide); assert.match(humanReviewHtml, /Human-in-the-loop review is a deliberate pause at a meaningful handoff/); assert.match(humanReviewHtml, /It is not a person reading every token an agent produces\./); assert.match(humanReviewHtml, /href="\/guides\/ai-agent-memory\//); assert.match(humanReviewHtml, /https:\/\/learn\.microsoft\.com\/en-us\/agent-framework\/workflows\/human-in-the-loop/); assert.match(humanReviewHtml, /href="\/guides\/ai-agent-handoffs\//); assert.match(humanReviewHtml, /href="\/guides\/agent-to-agent-messaging\//); const handoffsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-handoffs/'); assert.equal(handoffsGuide.title, 'AI Agent Handoffs: Transfer Work Without Losing Context | Commonly AI'); const handoffsHtml = renderStaticPage(guideTemplate, handoffsGuide); assert.match(handoffsHtml, /An AI agent handoff is the transfer of a piece of work to a new owner/); assert.match(handoffsHtml, /href="\/guides\/ai-agent-memory\//); assert.match(handoffsHtml, /href="\/guides\/human-in-the-loop-ai-agents\//); assert.match(handoffsHtml, /https:\/\/openai\.com\/business\/guides-and-resources\/a-practical-guide-to-building-ai-agents\//); assert.match(handoffsHtml, /https:\/\/learn\.microsoft\.com\/en-us\/agent-framework\/workflows\/orchestrations\/handoff/); assert.match(handoffsHtml, /href="\/guides\/how-to-build-an-ai-agent-team\//); assert.match(handoffsHtml, /href="\/guides\/agent-to-agent-messaging\//); const teamGuide = guidePages.find((page) => page.path === '/guides/how-to-build-an-ai-agent-team/'); assert.equal(teamGuide.title, 'How to Build an AI Agent Team: Roles, Handoffs, and Review | Commonly AI'); const teamHtml = renderStaticPage(guideTemplate, teamGuide); assert.match(teamHtml, /An AI agent team is a small group of people and agents with distinct responsibilities/); assert.match(teamHtml, /href="\/guides\/ai-agent-memory\//); assert.match(teamHtml, /href="\/guides\/human-in-the-loop-ai-agents\//); assert.match(teamHtml, /href="\/guides\/ai-agent-handoffs\//); assert.match(teamHtml, /https:\/\/openai\.com\/business\/guides-and-resources\/a-practical-guide-to-building-ai-agents\//); assert.match(teamHtml, /href="\/guides\/agent-to-agent-messaging\//); const messagingGuide = guidePages.find((page) => page.path === '/guides/agent-to-agent-messaging/'); assert.equal(messagingGuide.title, 'Agent-to-Agent Messaging: How AI Agents DM | Commonly AI'); const messagingHtml = renderStaticPage(guideTemplate, messagingGuide); assert.match(messagingHtml, /An agent-to-agent message is a focused, one-to-one request or response/); assert.match(messagingHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(messagingHtml, /commonly_dm_agent/); assert.match(messagingHtml, /href="\/guides\/multi-agent-collaboration-platform\//); assert.match(messagingHtml, /href="\/guides\/connect-claude-codex-shared-workspace\//); assert.match(messagingHtml, /href="\/guides\/ai-agent-handoffs\//); assert.match(messagingHtml, /href="\/guides\/human-in-the-loop-ai-agents\//); assert.match(messagingHtml, /https:\/\/a2a-protocol\.org\//); assert.match(messagingHtml, /Conceptually, the tool flow looks like this:<\/p>\s*
    /); assert.match(messagingHtml, /Use this pattern:<\/p>\s*
    /);
      assert.match(messagingHtml, /

    When a shared thread is better than a DM<\/h2>\s*

    Choose a thread[^<]*<\/p>\s*

      /); assert.match(messagingHtml, /

      When a DM is the better choice<\/h2>\s*

      Choose a DM[^<]*<\/p>\s*

        /); const selfHostedGuide = guidePages.find((page) => page.path === '/guides/self-hosted-ai-agent-platform/'); assert.equal(selfHostedGuide.title, 'Self-Hosted AI Agent Platform: What to Look For | Commonly AI'); const selfHostedHtml = renderStaticPage(guideTemplate, selfHostedGuide); assert.match(selfHostedHtml, /A self-hosted AI agent platform is software you deploy and operate/); assert.match(selfHostedHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(selfHostedHtml, /https:\/\/csrc\.nist\.gov\/pubs\/sp\/800\/190\/final/); assert.match(selfHostedHtml, /https:\/\/docs\.docker\.com\/compose\/trust-model\//); assert.match(selfHostedHtml, /https:\/\/docs\.docker\.com\/compose\/how-tos\/use-secrets\//); assert.match(selfHostedHtml, /https:\/\/docs\.docker\.com\/compose\/how-tos\/production\//); assert.match(selfHostedHtml, /

        Step 1: Map the architecture you are about to run<\/h2>/); assert.match(selfHostedHtml, /You still need to decide:<\/p>\s*
          /); assert.match(selfHostedHtml, /The local path is intentionally short:<\/p>\s*
          /);
            assert.match(selfHostedHtml, /Before installing a public instance[^<]*:<\/p>\s*
            /); assert.match(selfHostedHtml, /Self-hosting Commonly can give[^<]*does not, by itself:<\/p>\s*
              /); assert.match(selfHostedHtml, /

              Choose the responsibility you are ready to operate<\/h2>

              These gaps are not reasons to avoid self-hosting\./); assert.match(selfHostedHtml, /href="\/guides\/connect-claude-codex-shared-workspace\//); assert.match(selfHostedHtml, /href="\/guides\/ai-agent-memory\//); const permissionsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-permissions-and-tokens/'); assert.equal(permissionsGuide.title, 'AI Agent Permissions and Tokens: Scope Runtime Access Safely | Commonly AI'); const permissionsHtml = renderStaticPage(guideTemplate, permissionsGuide); assert.match(permissionsHtml, /An AI agent runtime token is a bearer credential that identifies a specific agent installation/); assert.match(permissionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(permissionsHtml, /

              Separate authentication, authorization, and tool permissions<\/h2>\s*

              These three ideas[^<]*They are different layers:<\/p>\s*

              /); assert.match(permissionsHtml, /

              Why the layers must stay separate<\/h2>/); assert.match(permissionsHtml, /https:\/\/csrc\.nist\.gov\/glossary\/term\/least_privilege/); assert.match(permissionsHtml, /https:\/\/cheatsheetseries\.owasp\.org\/cheatsheets\/Secrets_Management_Cheat_Sheet\.html/); assert.match(permissionsHtml, /It does authorize meaningful work[^<]*<\/p>\s*

              Commonly documents two agent-related token categories[^<]*<\/p>\s*

              /); assert.match(permissionsHtml, /Adding an agent to a pod is also an access decision for its runtime token\.<\/strong>/); assert.match(permissionsHtml, /Before adding an existing agent[^<]*questions:<\/p>\s*
                /); assert.match(permissionsHtml, /Once issued, a runtime request uses the token in the authorization header:<\/p>\s*
                /);
                  assert.match(permissionsHtml, /Commonly’s documentation recommends an environment variable[^<]*:<\/p>\s*
                /);
                  assert.match(permissionsHtml, /Use a controlled test sequence:<\/p>\s*
                  /); assert.match(permissionsHtml, /A practical response sequence is:<\/p>\s*
                    /); assert.match(permissionsHtml, /

                    Sharing a token between installations<\/h2>/); assert.match(permissionsHtml, /

                    Assuming token scope governs local tools<\/h2>/); assert.match(permissionsHtml, /href="\/guides\/connect-claude-codex-shared-workspace\//); assert.match(permissionsHtml, /href="\/guides\/ai-agent-task-management\//); const cursorGuide = guidePages.find((page) => page.path === '/guides/connect-cursor-shared-workspace/'); assert.equal(cursorGuide.title, 'How to Connect Cursor to a Shared Workspace | Commonly AI'); const cursorHtml = renderStaticPage(guideTemplate, cursorGuide); assert.match(cursorHtml, /Connecting Cursor to a shared workspace gives the agent you use in Cursor/); assert.match(cursorHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(cursorHtml, /~\/\.cursor\/mcp\.json/); assert.match(cursorHtml, /@commonlyai\/mcp/); assert.match(cursorHtml, /cm_agent_\.\.\./); assert.match(cursorHtml, /It is not a bundled development environment\.<\/p>\s*
                    /); assert.match(cursorHtml, /In Cursor, invoke the agent with a request like this:<\/p>\s*
                    /);
                      assert.match(cursorHtml, /

                    Verify both sides of the access boundary<\/h2>\s*

                    [^<]*<\/p>\s*

                    Confirm all four:<\/p>\s*

                      /); assert.match(cursorHtml, /

                      Give the first task a boundary<\/h2>/); const observabilityGuide = guidePages.find((page) => page.path === '/guides/ai-agent-observability/'); assert.equal(observabilityGuide.title, 'AI Agent Observability: Make Work, Handoffs, and Decisions Visible | Commonly AI'); const observabilityHtml = renderStaticPage(guideTemplate, observabilityGuide); assert.match(observabilityHtml, /AI agent observability is the ability to answer a practical set of questions/); assert.match(observabilityHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(observabilityHtml, /pending, claimed, blocked, and done/); assert.match(observabilityHtml, /A strong thread update has five parts:<\/p>\s*
                      /);
                        assert.match(observabilityHtml, /Objective: The outcome this work is intended to produce\.[\s\S]*Owner: The person or agent responsible for that action\./);
                        assert.match(observabilityHtml, /The right response is to connect the signals:<\/p>\s*
                      /); const eventsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-events/'); assert.equal(eventsGuide.title, 'AI Agent Events: Mentions, Tasks, Heartbeats, and Safe Handling | Commonly AI'); const eventsHtml = renderStaticPage(guideTemplate, eventsGuide); assert.match(eventsHtml, /An AI agent event is a structured signal/); assert.match(eventsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); for (const eventType of ['chat\\.mention', 'thread\\.mention', 'task\\.assigned', 'heartbeat', 'integration\\.event']) { assert.match(eventsHtml, new RegExp(eventType)); } assert.match(eventsHtml, /When a polled event includes payload\.deliveryId, the acknowledgement must echo that exact value\.[^<]*For example:<\/p>\s*
                      /);
                        assert.match(eventsHtml, /cm_agent_\.\.\./);
                        assert.doesNotMatch(eventsHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const comparisonGuide = guidePages.find((page) => page.path === '/guides/multi-agent-vs-single-agent/');
                        assert.equal(comparisonGuide.title, 'Multi-Agent vs. Single-Agent Systems: How to Choose | Commonly AI');
                        const comparisonHtml = renderStaticPage(guideTemplate, comparisonGuide);
                        assert.match(comparisonHtml, /A single-agent system gives one named agent responsibility/);
                        assert.match(comparisonHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(comparisonHtml, /A useful contract includes:<\/p>\s*
                      /);
                        assert.match(comparisonHtml, /pending, claimed, blocked, and done/);
                        assert.match(comparisonHtml, /A task claim is a visible coordination signal/);
                        assert.doesNotMatch(comparisonHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const patternsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-collaboration-patterns/');
                        assert.equal(patternsGuide.title, 'AI Agent Collaboration Patterns: Leads, Reviewers, Claims, and Races | Commonly AI');
                        const patternsHtml = renderStaticPage(guideTemplate, patternsGuide);
                        assert.match(patternsHtml, /AI agent collaboration patterns are repeatable ways/);
                        assert.match(patternsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(patternsHtml, /Use this task contract:<\/p>\s*
                      /);
                        assert.match(patternsHtml, /returns the existing task rather than creating another one/);
                        assert.match(patternsHtml, /A claim is a coordination signal/);
                        assert.doesNotMatch(patternsHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const onboardingGuide = guidePages.find((page) => page.path === '/guides/onboarding-an-ai-agent-to-your-team/');
                        assert.equal(onboardingGuide.title, 'How to Onboard an AI Agent to Your Team | Commonly AI');
                        const onboardingHtml = renderStaticPage(guideTemplate, onboardingGuide);
                        assert.match(onboardingHtml, /Onboarding an AI agent to a team is the process of/);
                        assert.match(onboardingHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(onboardingHtml, /
                      [\s\S]*codex mcp add commonly/);
                        assert.match(onboardingHtml, /pending, claimed, blocked, and done/);
                        assert.match(onboardingHtml, /cm_agent_…/);
                        assert.doesNotMatch(onboardingHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const discordGuide = guidePages.find((page) => page.path === '/guides/ai-agent-discord-integration/');
                        assert.equal(discordGuide.title, 'AI Agent Discord Integration: Reviewable Work Signals | Commonly AI');
                        const discordHtml = renderStaticPage(guideTemplate, discordGuide);
                        assert.match(discordHtml, /An AI agent Discord integration connects a Discord conversation/);
                        assert.match(discordHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(discordHtml, /\/discord-push/);
                        assert.match(discordHtml, /every hour/);
                        assert.match(discordHtml, /@commonly-bot/);
                        assert.match(discordHtml, /pending, claimed, blocked, and done/);
                        assert.match(discordHtml, /
                      [\s\S]*DISCORD_BOT_TOKEN=\.\.\./);
                        assert.doesNotMatch(discordHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        assert.doesNotMatch(discordHtml, /DISCORD_(?:BOT_TOKEN|CLIENT_ID|CLIENT_SECRET)=(?!\.\.\.)[^\s<]+/);
                        const runtimeGuide = guidePages.find((page) => page.path === '/guides/what-is-an-ai-agent-runtime/');
                        assert.equal(runtimeGuide.title, 'What Is an AI Agent Runtime? | Commonly AI');
                        const runtimeHtml = renderStaticPage(guideTemplate, runtimeGuide);
                        assert.match(runtimeHtml, /An AI agent runtime is the process that receives a trigger/);
                        assert.match(runtimeHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(runtimeHtml, /commonly agent run/);
                        assert.match(runtimeHtml, /
                      [\s\S]*GET \/api\/agents\/runtime\/events/);
                        assert.match(runtimeHtml, /cannot discover or join pods/);
                        assert.match(runtimeHtml, /cm_agent_…/);
                        assert.doesNotMatch(runtimeHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const heartbeatsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-heartbeats-and-scheduled-work/');
                        assert.equal(heartbeatsGuide.title, 'AI Agent Heartbeats and Scheduled Work | Commonly AI');
                        const heartbeatsHtml = renderStaticPage(guideTemplate, heartbeatsGuide);
                        assert.match(heartbeatsHtml, /An AI agent heartbeat is a scheduled trigger/);
                        assert.match(heartbeatsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(heartbeatsHtml, /everyMinutes/);
                        assert.match(heartbeatsHtml, /HEARTBEAT_OK/);
                        assert.match(heartbeatsHtml, /pending, claimed, blocked, and done/);
                        assert.match(heartbeatsHtml, /crash-loops the gateway/);
                        assert.doesNotMatch(heartbeatsHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const marketplaceRolesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-marketplace-roles/');
                        assert.equal(marketplaceRolesGuide.title, 'AI Agent Marketplace Roles: Build a Clear Team | Commonly AI');
                        const marketplaceRolesHtml = renderStaticPage(guideTemplate, marketplaceRolesGuide);
                        assert.match(marketplaceRolesHtml, /AI agent marketplace roles are reusable starting points/);
                        assert.match(marketplaceRolesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(marketplaceRolesHtml, /Theo/);
                        assert.match(marketplaceRolesHtml, /X-Curator/);
                        assert.match(marketplaceRolesHtml, /coordinates tasks, reviews/);
                        assert.match(marketplaceRolesHtml, /pending, claimed, blocked, and done/);
                        assert.match(marketplaceRolesHtml, /AgentInstallation/);
                        assert.doesNotMatch(marketplaceRolesHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const customHttpGuide = guidePages.find((page) => page.path === '/guides/connect-a-custom-agent-http-api/');
                        assert.equal(customHttpGuide.title, 'Connect a Custom AI Agent with the HTTP API | Commonly AI');
                        const customHttpHtml = renderStaticPage(guideTemplate, customHttpGuide);
                        assert.match(customHttpHtml, /Connecting a custom AI agent over HTTP means/);
                        assert.match(customHttpHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(customHttpHtml, /x-commonly-agent-token/);
                        assert.match(customHttpHtml, /deliveryId/);
                        assert.match(customHttpHtml, /sourceRef/);
                        assert.match(customHttpHtml, /runtime\/pods/);
                        assert.match(customHttpHtml, /pending, claimed, blocked, and done/);
                        assert.doesNotMatch(customHttpHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const agentPodGuide = guidePages.find((page) => page.path === '/guides/what-is-an-agent-pod/');
                        assert.equal(agentPodGuide.title, 'What Is an Agent Pod? Shared Workspace for AI Teams | Commonly AI');
                        const agentPodHtml = renderStaticPage(guideTemplate, agentPodGuide);
                        assert.match(agentPodHtml, /An agent pod is a shared workspace/);
                        assert.match(agentPodHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(agentPodHtml, /agent-admin/);
                        assert.match(agentPodHtml, /invite-only/);
                        assert.match(agentPodHtml, /pending, claimed, blocked, and done/);
                        assert.match(agentPodHtml, /AgentInstallation/);
                        assert.match(agentPodHtml, /capped at 10 versions/);
                        assert.doesNotMatch(agentPodHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const openClawGuide = guidePages.find((page) => page.path === '/guides/connect-openclaw-agent/');
                        const openClawHtml = renderStaticPage(guideTemplate, openClawGuide);
                        assert.match(openClawHtml, /Connecting an OpenClaw agent means/);
                        assert.match(openClawHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(openClawHtml, /moltbot\.json/);
                        assert.match(openClawHtml, /heartbeat\.global/);
                        assert.match(openClawHtml, /HEARTBEAT\.md/);
                        assert.match(openClawHtml, /AgentsHub/);
                        assert.doesNotMatch(openClawHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const securityGuide = guidePages.find((page) => page.path === '/guides/ai-agent-security-best-practices/');
                        const securityHtml = renderStaticPage(guideTemplate, securityGuide);
                        assert.match(securityHtml, /AI agent security is the practice of/);
                        assert.match(securityHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(securityHtml, /least privilege/);
                        assert.match(securityHtml, /excessive agency/);
                        assert.match(securityHtml, /installation-scoped/);
                        assert.doesNotMatch(securityHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const cliGuide = guidePages.find((page) => page.path === '/guides/ai-agent-cli/');
                        assert.equal(cliGuide.title, 'AI Agent CLI: Run a Local Agent as a Pod Member | Commonly AI');
                        const cliHtml = renderStaticPage(guideTemplate, cliGuide);
                        assert.match(cliHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-cli\/"/);
                        assert.match(cliHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.match(cliHtml, /commonly agent run/);
                        assert.doesNotMatch(cliHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        const rolesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-roles/');
                        assert.equal(rolesGuide.title, 'AI Agent Roles: Define Work, Boundaries, and Handoffs | Commonly AI');
                        assert.deepEqual(guides['ai-agent-roles'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 8], [3, 6], [3, 7], [3, 6], [4, 8], [2, 4], [2, 7]]);
                        assert.equal(guides['ai-agent-roles'].sections.flatMap((section) => section.links || []).length, 11);
                        const rolesHtml = renderStaticPage(guideTemplate, rolesGuide);
                        assert.match(rolesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-roles\//);
                        assert.match(rolesHtml, /An AI agent role is a bounded responsibility that tells an agent what result it owns/);
                        assert.match(rolesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/);
                        assert.doesNotMatch(rolesHtml, /seo-page-dark/);
                        assert.match(rolesHtml, /stop condition/);
                        assert.doesNotMatch(rolesHtml, /cm_agent_[A-Za-z0-9]{8,}/);
                        assert.equal((rolesHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/what-is-an-ai-agent/', '/guides/how-to-write-ai-agent-instructions/', '/guides/ai-agent-use-cases/', '/guides/ai-agent-tools/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-roles\/"/); } const escalationGuide = guidePages.find((page) => page.path === '/guides/ai-agent-escalation/'); assert.equal(escalationGuide.title, 'AI Agent Escalation: Stop, Hand Off, and Decide | Commonly AI'); assert.deepEqual(guides['ai-agent-escalation'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 5], [3, 9], [3, 9], [3, 6], [3, 4], [3, 6], [2, 8]]); assert.deepEqual(guides['ai-agent-escalation'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-escalation'].sections.flatMap((section) => section.links || []).length, 7); const escalationHtml = renderStaticPage(guideTemplate, escalationGuide); assert.match(escalationHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-escalation\//); assert.match(escalationHtml, /AI agent escalation is a deliberate handoff to a person or role that can make a decision the agent should not make alone/); assert.match(escalationHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(escalationHtml, /seo-page-dark/); assert.match(escalationHtml, /escalation packet/); assert.doesNotMatch(escalationHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((escalationHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-handoffs/', '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-task-management/', '/guides/prompt-injection-defense-for-ai-agents/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-escalation\/"/); } const acceptanceCriteriaGuide = guidePages.find((page) => page.path === '/guides/ai-agent-acceptance-criteria/'); assert.equal(acceptanceCriteriaGuide.title, 'AI Agent Acceptance Criteria: Testable, Reviewable Work | Commonly AI'); assert.deepEqual(guides['ai-agent-acceptance-criteria'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 8], [2, 7], [2, 4], [2, 6], [3, 5], [2, 8]]); assert.deepEqual(guides['ai-agent-acceptance-criteria'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-acceptance-criteria'].sections.flatMap((section) => section.links || []).length, 9); const acceptanceCriteriaHtml = renderStaticPage(guideTemplate, acceptanceCriteriaGuide); assert.match(acceptanceCriteriaHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-acceptance-criteria\//); assert.match(acceptanceCriteriaHtml, /AI agent acceptance criteria are the observable conditions that tell a team whether an agent's result is ready for its next handoff/); assert.match(acceptanceCriteriaHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(acceptanceCriteriaHtml, /seo-page-dark/); assert.match(acceptanceCriteriaHtml, /safe stop/); assert.doesNotMatch(acceptanceCriteriaHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((acceptanceCriteriaHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/how-to-evaluate-ai-agents/', '/guides/ai-agent-roles/', '/guides/ai-agent-escalation/', '/guides/how-to-write-ai-agent-instructions/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-acceptance-criteria\//); } const decisionPacketGuide = guidePages.find((page) => page.path === '/guides/ai-agent-decision-packet/'); assert.equal(decisionPacketGuide.title, 'AI Agent Decision Packet: Evidence, Options, and Ownership | Commonly AI'); assert.deepEqual(guides['ai-agent-decision-packet'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 7], [3, 9], [3, 6], [3, 6], [3, 5], [3, 6], [3, 5], [2, 8]]); assert.deepEqual(guides['ai-agent-decision-packet'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-decision-packet'].sections.flatMap((section) => section.links || []).length, 9); const decisionPacketHtml = renderStaticPage(guideTemplate, decisionPacketGuide); assert.match(decisionPacketHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-decision-packet\//); assert.match(decisionPacketHtml, /An AI agent decision packet is a compact, evidence-backed artifact that gives a named person or role one answerable choice/); assert.match(decisionPacketHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(decisionPacketHtml, /seo-page-dark/); assert.match(decisionPacketHtml, /answerable choice/); assert.doesNotMatch(decisionPacketHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((decisionPacketHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-escalation/', '/guides/ai-agent-handoffs/', '/guides/human-in-the-loop-ai-agents/', '/guides/context-engineering-for-ai-agents/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-decision-packet\//); } const auditTrailGuide = guidePages.find((page) => page.path === '/guides/ai-agent-audit-trail/'); assert.equal(auditTrailGuide.title, 'AI Agent Audit Trail: Make Work and Decisions Inspectable | Commonly AI'); assert.deepEqual(guides['ai-agent-audit-trail'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 8], [3, 6], [3, 6], [3, 6], [3, 6], [3, 5], [3, 6]]); assert.deepEqual(guides['ai-agent-audit-trail'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-audit-trail'].sections.flatMap((section) => section.links || []).length, 10); const auditTrailHtml = renderStaticPage(guideTemplate, auditTrailGuide); assert.match(auditTrailHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-audit-trail\//); assert.match(auditTrailHtml, /An AI agent audit trail is a structured, linked account of a piece of work/); assert.match(auditTrailHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(auditTrailHtml, /seo-page-dark/); assert.match(auditTrailHtml, /source-of-record/); assert.doesNotMatch(auditTrailHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((auditTrailHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-governance/', '/guides/ai-agent-memory/', '/guides/ai-agent-acceptance-criteria/', '/guides/ai-agent-task-management/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-audit-trail\//); } const noOpGuide = guidePages.find((page) => page.path === '/guides/ai-agent-no-op/'); assert.equal(noOpGuide.title, 'AI Agent No-Op: When Doing Nothing Is the Right Result | Commonly AI'); assert.deepEqual(guides['ai-agent-no-op'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 8], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 5], [3, 6]]); assert.deepEqual(guides['ai-agent-no-op'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-no-op'].sections.flatMap((section) => section.links || []).length, 9); const noOpHtml = renderStaticPage(guideTemplate, noOpGuide); assert.match(noOpHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-no-op\//); assert.match(noOpHtml, /An AI agent no-op is a deliberate decision to take no further action/); assert.match(noOpHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(noOpHtml, /seo-page-dark/); assert.match(noOpHtml, /eligibility rule/); assert.doesNotMatch(noOpHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((noOpHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-heartbeats-and-scheduled-work/', '/guides/ai-agent-escalation/', '/guides/ai-agent-acceptance-criteria/', '/guides/how-to-write-ai-agent-instructions/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-no-op\//); } const sourceOfRecordGuide = guidePages.find((page) => page.path === '/guides/ai-agent-source-of-record/'); assert.equal(sourceOfRecordGuide.title, 'AI Agent Source of Record: Which Record Is Authoritative? | Commonly AI'); assert.deepEqual(guides['ai-agent-source-of-record'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[4, 6], [3, 7], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-source-of-record'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-source-of-record'].sections.flatMap((section) => section.links || []).length, 9); const sourceOfRecordHtml = renderStaticPage(guideTemplate, sourceOfRecordGuide); assert.match(sourceOfRecordHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-source-of-record\//); assert.match(sourceOfRecordHtml, /An AI agent source of record is the designated place a team relies on for a specific kind of fact/); assert.match(sourceOfRecordHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(sourceOfRecordHtml, /seo-page-dark/); assert.match(sourceOfRecordHtml, /verification path/); assert.doesNotMatch(sourceOfRecordHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((sourceOfRecordHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-audit-trail/', '/guides/ai-agent-decision-packet/', '/guides/ai-agent-memory/', '/guides/ai-agent-task-management/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-source-of-record\//); } const scopeCreepGuide = guidePages.find((page) => page.path === '/guides/ai-agent-scope-creep/'); assert.equal(scopeCreepGuide.title, 'AI Agent Scope Creep: Keep Work Boundaries Reviewable | Commonly AI'); assert.deepEqual(guides['ai-agent-scope-creep'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[4, 6], [3, 8], [3, 7], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-scope-creep'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-scope-creep'].sections.flatMap((section) => section.links || []).length, 9); const scopeCreepHtml = renderStaticPage(guideTemplate, scopeCreepGuide); assert.match(scopeCreepHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-scope-creep\//); assert.match(scopeCreepHtml, /AI agent scope creep is the unreviewed expansion of an agent’s assigned outcome/); assert.match(scopeCreepHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(scopeCreepHtml, /seo-page-dark/); assert.match(scopeCreepHtml, /non-goals/); assert.doesNotMatch(scopeCreepHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((scopeCreepHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-roles/', '/guides/ai-agent-no-op/', '/guides/ai-agent-decision-packet/', '/guides/ai-agent-acceptance-criteria/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-scope-creep\//); } const reviewPacketGuide = guidePages.find((page) => page.path === '/guides/ai-agent-review-packet/'); assert.equal(reviewPacketGuide.title, 'AI Agent Review Packet: Evidence, Limits, and Reviewer Decision | Commonly AI'); assert.deepEqual(guides['ai-agent-review-packet'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 9], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-review-packet'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-review-packet'].sections.flatMap((section) => section.links || []).length, 9); const reviewPacketHtml = renderStaticPage(guideTemplate, reviewPacketGuide); assert.match(reviewPacketHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-review-packet\//); assert.match(reviewPacketHtml, /An AI agent review packet is a compact, inspectable bundle/); assert.match(reviewPacketHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(reviewPacketHtml, /seo-page-dark/); assert.match(reviewPacketHtml, /requested judgment/); assert.doesNotMatch(reviewPacketHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((reviewPacketHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-decision-packet/', '/guides/ai-agent-acceptance-criteria/', '/guides/human-in-the-loop-ai-agents/', '/guides/how-to-evaluate-ai-agents/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-review-packet\//); } const blockersGuide = guidePages.find((page) => page.path === '/guides/ai-agent-blockers/'); assert.equal(blockersGuide.title, 'AI Agent Blockers: Missing Prerequisites, Effect, and Owner | Commonly AI'); assert.deepEqual(guides['ai-agent-blockers'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 7], [3, 7], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-blockers'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-blockers'].sections.flatMap((section) => section.links || []).length, 9); const blockersHtml = renderStaticPage(guideTemplate, blockersGuide); assert.match(blockersHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-blockers\//); assert.match(blockersHtml, /An AI agent blocker is a precise record that an eligible, in-scope outcome/); assert.match(blockersHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(blockersHtml, /seo-page-dark/); assert.match(blockersHtml, /resume condition/); assert.doesNotMatch(blockersHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((blockersHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-escalation/', '/guides/ai-agent-no-op/', '/guides/ai-agent-task-management/', '/guides/ai-agent-decision-packet/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-blockers\//); } const statusUpdatesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-status-updates/'); assert.equal(statusUpdatesGuide.title, 'AI Agent Status Updates: Report Progress Without Noise | Commonly AI'); assert.deepEqual(guides['ai-agent-status-updates'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 7], [3, 7], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-status-updates'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-status-updates'].sections.flatMap((section) => section.links || []).length, 9); const statusUpdatesHtml = renderStaticPage(guideTemplate, statusUpdatesGuide); assert.match(statusUpdatesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-status-updates\//); assert.match(statusUpdatesHtml, /An AI agent status update is a concise report of a material change/); assert.match(statusUpdatesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(statusUpdatesHtml, /seo-page-dark/); assert.match(statusUpdatesHtml, /material delta/); assert.doesNotMatch(statusUpdatesHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((statusUpdatesHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-blockers/', '/guides/ai-agent-no-op/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-task-management/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-status-updates\//); } const workContractGuide = guidePages.find((page) => page.path === '/guides/ai-agent-work-contract/'); assert.equal(workContractGuide.title, 'AI Agent Work Contract: Outcome, Inputs, Operations, and Stop | Commonly AI'); assert.deepEqual(guides['ai-agent-work-contract'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[4, 6], [3, 9], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-work-contract'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-work-contract'].sections.flatMap((section) => section.links || []).length, 9); const workContractHtml = renderStaticPage(guideTemplate, workContractGuide); assert.match(workContractHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-work-contract\//); assert.match(workContractHtml, /An AI agent work contract is a task-level agreement/); assert.match(workContractHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(workContractHtml, /seo-page-dark/); assert.match(workContractHtml, /permitted operations/); assert.doesNotMatch(workContractHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((workContractHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-roles/', '/guides/how-to-write-ai-agent-instructions/', '/guides/ai-agent-acceptance-criteria/', '/guides/ai-agent-scope-creep/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-work-contract\//); } const followOnWorkGuide = guidePages.find((page) => page.path === '/guides/ai-agent-follow-on-work/'); assert.equal(followOnWorkGuide.title, 'AI Agent Follow-On Work: Turn Adjacent Ideas Into Owned Tasks | Commonly AI'); assert.deepEqual(guides['ai-agent-follow-on-work'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 8], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-follow-on-work'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-follow-on-work'].sections.flatMap((section) => section.links || []).length, 10); const followOnWorkHtml = renderStaticPage(guideTemplate, followOnWorkGuide); assert.match(followOnWorkHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-follow-on-work\//); assert.match(followOnWorkHtml, /AI agent follow-on work is a separately defined task/); assert.match(followOnWorkHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(followOnWorkHtml, /seo-page-dark/); assert.match(followOnWorkHtml, /follow-on task/); assert.doesNotMatch(followOnWorkHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((followOnWorkHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-scope-creep/', '/guides/ai-agent-work-contract/', '/guides/ai-agent-no-op/', '/guides/ai-agent-task-management/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-follow-on-work\//); } const verificationPathGuide = guidePages.find((page) => page.path === '/guides/ai-agent-verification-path/'); assert.equal(verificationPathGuide.title, 'AI Agent Verification Path: Trace Claims to Evidence | Commonly AI'); assert.deepEqual(guides['ai-agent-verification-path'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-verification-path'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-verification-path'].sections.flatMap((section) => section.links || []).length, 9); const verificationPathHtml = renderStaticPage(guideTemplate, verificationPathGuide); assert.match(verificationPathHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-verification-path\//); assert.match(verificationPathHtml, /An AI agent verification path is the explicit route/); assert.match(verificationPathHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(verificationPathHtml, /seo-page-dark/); assert.match(verificationPathHtml, /target-system record/); assert.doesNotMatch(verificationPathHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((verificationPathHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-source-of-record/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-status-updates/', '/guides/ai-agent-acceptance-criteria/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-verification-path\//); } const resumeConditionsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-resume-conditions/'); assert.equal(resumeConditionsGuide.title, 'AI Agent Resume Conditions: Restart Work Safely | Commonly AI'); assert.deepEqual(guides['ai-agent-resume-conditions'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-resume-conditions'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-resume-conditions'].sections.flatMap((section) => section.links || []).length, 9); const resumeConditionsHtml = renderStaticPage(guideTemplate, resumeConditionsGuide); assert.match(resumeConditionsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-resume-conditions\//); assert.match(resumeConditionsHtml, /AI agent resume conditions are the specific, checkable facts/); assert.match(resumeConditionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(resumeConditionsHtml, /seo-page-dark/); assert.match(resumeConditionsHtml, /required state/); assert.doesNotMatch(resumeConditionsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((resumeConditionsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-blockers/', '/guides/ai-agent-no-op/', '/guides/ai-agent-escalation/', '/guides/ai-agent-status-updates/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-resume-conditions\//); } const prioritizationGuide = guidePages.find((page) => page.path === '/guides/ai-agent-task-prioritization/'); assert.equal(prioritizationGuide.title, 'AI Agent Task Prioritization: Choose What’s Next | Commonly AI'); const prioritization = guides['ai-agent-task-prioritization']; assert.deepEqual(prioritization.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(prioritization.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(prioritization.sections.flatMap((section) => section.links || []).length, 9); assert.equal(prioritization.faq.length, 6); assert.equal(prioritization.intro.length, 4); for (const section of prioritization.sections.filter((section) => section.links)) { assert.equal(section.paragraphs.length, 2); } const prioritizationExampleIndex = prioritization.sections.findIndex((section) => section.title === 'A worked example with three eligible tasks'); const prioritizationExample = prioritization.sections[prioritizationExampleIndex]; assert.equal(prioritizationExample.paragraphs.length, 6); assert.equal(prioritizationExample.tables, undefined); assert.equal(prioritizationExample.links, undefined); assert.equal(prioritizationExample.orderedItems, undefined); assert.equal(prioritization.sections.slice(0, prioritizationExampleIndex).filter((section) => section.tables).length, 9); assert.equal(prioritization.sections[prioritizationExampleIndex - 1].title, 'Update the current plan'); assert.equal(prioritization.sections[prioritizationExampleIndex + 1].title, 'Prioritize agent tasks in seven steps'); assert.match(prioritization.sections.find((section) => section.title === 'Use a range').paragraphs[1], /^If uncertainty could reverse the priority choice, a short discovery step may be useful when it is within the assignment\./); for (const [title, tail] of [ ['Build the shortlist', /Dependency management explains what must wait; prioritization compares what can happen now\.$/], ['Identify which choices', /A task claimant owns a contribution, not necessarily the team’s priorities\.$/], ['Describe the expected effect', /without pretending to quantify every benefit\.$/], ['Choose enough of an order', /because another task is more interesting but unavailable\.$/], ['Record unfinished work', /A priority change is a sequencing choice unless the actual stop condition or authority says otherwise\.$/], ['State the missing decision', /“Not selected next” is not, by itself, a blocker\.$/], ['Update the current plan', /need not change what any of those tasks is authorized to do\.$/], ]) { assert.match(prioritization.sections.find((section) => section.title === title).paragraphs[1], tail); } const recordProportionate = prioritization.sections.find((section) => section.title === 'Keep the record proportionate'); assert.equal(recordProportionate.paragraphs.length, 1); assert.equal(recordProportionate.links, undefined); assert.match(recordProportionate.paragraphs[0], /“Return the source correction first to release the waiting review, then finish the brief before its agreed handoff; reassess if the correction requires broader work\.”/); assert.match(prioritization.intro[0], /^AI agent task prioritization is the process of choosing which eligible contribution an agent should make next when several tasks compete for its attention\./); const prioritizationHtml = renderStaticPage(guideTemplate, prioritizationGuide); assert.match(prioritizationHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-task-prioritization\/"/); assert.match(prioritizationHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(prioritizationHtml, /task prioritization/); assert.doesNotMatch(prioritizationHtml, /seo-page-dark/); assert.doesNotMatch(prioritizationHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((prioritizationHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-dependency-management/', '/guides/ai-agent-decision-owner/', '/guides/ai-agent-task-intake/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-task-prioritization\/"/g) || []).length, 1); } assert.ok(!prioritization.sections.some((section) => section.title === prioritization.cta.title)); assert.equal((prioritizationHtml.match(/

                      Choose the next useful contribution<\/h2>/g) || []).length, 1); assert.ok(prioritizationHtml.indexOf('

                      Frequently asked questions

                      ') < prioritizationHtml.indexOf('

                      Choose the next useful contribution

                      ')); assert.equal(prioritization.cta.secondary.label, 'Explore Commonly’s guides'); const disagreementGuide = guidePages.find((page) => page.path === '/guides/ai-agent-disagreement-resolution/'); assert.equal(disagreementGuide.title, 'AI Agent Disagreement Resolution Guide | Commonly AI'); const disagreement = guides['ai-agent-disagreement-resolution']; assert.deepEqual(disagreement.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(disagreement.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(disagreement.sections.flatMap((section) => section.links || []).length, 9); assert.equal(disagreement.faq.length, 6); assert.equal(disagreement.intro.length, 4); for (const section of disagreement.sections.filter((section) => section.links)) { assert.equal(section.paragraphs.length, 2); } const disagreementExampleIndex = disagreement.sections.findIndex((section) => section.title === 'A worked example of conflicting review feedback'); const disagreementExample = disagreement.sections[disagreementExampleIndex]; assert.equal(disagreementExample.paragraphs.length, 6); assert.equal(disagreementExample.tables, undefined); assert.equal(disagreementExample.links, undefined); assert.equal(disagreementExample.orderedItems, undefined); assert.equal(disagreement.sections.slice(0, disagreementExampleIndex).filter((section) => section.tables).length, 9); assert.equal(disagreement.sections[disagreementExampleIndex - 1].title, 'Preserve a material unresolved concern'); assert.equal(disagreement.sections[disagreementExampleIndex + 1].title, 'Resolve agent disagreements in seven steps'); for (const [title, tail] of [ ['Inspect the strongest relevant evidence', /^If the evidence remains incomplete, narrow the statement or keep the uncertainty visible\./], ['Name the decision', /^If two apparently authorized owners give incompatible directions/], ]) { assert.match(disagreement.sections.find((section) => section.title === title).paragraphs[1], tail); } for (const [title, tail] of [ ['Record the reason', /the original outcome may still need another approach or an owner’s explicit decision to stop pursuing it\.$/], ['Keep motives and status out', /A thread can organize a decision without becoming the authority that makes it valid\.$/], ['Revise the affected part', /supplies a required reviewer acceptance\.$/], ['Pause only the affected path', /not the full discussion with an unexplained request to “sort it out\.”$/], ['Preserve a material unresolved concern', /proof that a deployment, transfer, or other external operation occurred\.$/], ]) { assert.match(disagreement.sections.find((section) => section.title === title).paragraphs[1], tail); } const shortestProcess = disagreement.sections.find((section) => section.title === 'Use the shortest process'); assert.equal(shortestProcess.paragraphs.length, 1); assert.equal(shortestProcess.links, undefined); assert.match(disagreement.intro[0], /^AI agent disagreement resolution is the process of turning conflicting claims, review comments, or recommendations about an agent’s work into an evidence-backed correction, a bounded owner decision, or an explicit unresolved condition\./); const disagreementHtml = renderStaticPage(guideTemplate, disagreementGuide); assert.match(disagreementHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-disagreement-resolution\/"/); assert.match(disagreementHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(disagreementHtml, /disagreement resolution/); assert.doesNotMatch(disagreementHtml, /seo-page-dark/); assert.doesNotMatch(disagreementHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((disagreementHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-review-decisions/', '/guides/ai-agent-decision-owner/', '/guides/ai-agent-focused-threads/', '/guides/ai-agent-revision-loop/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-disagreement-resolution\/"/g) || []).length, 1); } assert.ok(!disagreement.sections.some((section) => section.title === disagreement.cta.title)); assert.equal((disagreementHtml.match(/

                      Settle disagreements with evidence and owners<\/h2>/g) || []).length, 1); assert.ok(disagreementHtml.indexOf('

                      Frequently asked questions

                      ') < disagreementHtml.indexOf('

                      Settle disagreements with evidence and owners

                      ')); assert.equal(disagreement.cta.secondary.label, 'Explore Commonly’s guides'); const dataBoundariesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-data-boundaries/'); assert.equal(dataBoundariesGuide.title, 'AI Agent Data Boundaries: Read, Retain, Share | Commonly AI'); const dataBoundaries = guides['ai-agent-data-boundaries']; assert.deepEqual(dataBoundaries.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(dataBoundaries.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(dataBoundaries.sections.flatMap((section) => section.links || []).length, 9); assert.equal(dataBoundaries.faq.length, 6); assert.equal(dataBoundaries.intro.length, 4); const dataWorkedExampleIndex = dataBoundaries.sections.findIndex((section) => section.title === 'A worked example using public reference material'); const dataWorkedExample = dataBoundaries.sections[dataWorkedExampleIndex]; assert.equal(dataWorkedExample.paragraphs.length, 6); assert.equal(dataWorkedExample.tables, undefined); assert.equal(dataWorkedExample.links, undefined); assert.equal(dataWorkedExample.orderedItems, undefined); assert.equal(dataBoundaries.sections.slice(0, dataWorkedExampleIndex).filter((section) => section.tables).length, 9); assert.equal(dataBoundaries.sections[dataWorkedExampleIndex - 1].title, 'State the extent'); assert.equal(dataBoundaries.sections[dataWorkedExampleIndex + 1].title, 'Set task data boundaries in seven steps'); const chooseDestination = dataBoundaries.sections.find((section) => section.title === 'Choose the destination'); assert.equal(chooseDestination.paragraphs.length, 3); assert.match(chooseDestination.paragraphs[1], /^Describe retention expectations in terms someone can act on/); assert.deepEqual(chooseDestination.links.map((link) => link.path), ['/guides/ai-agent-retained-context/']); for (const [title, tail] of [ ['Select before collecting', /A context packet should preserve the route back to evidence without becoming a copy of every available record\.$/], ['Technical availability', /both layers need to support the planned action\.$/], ['Trace important claims', /they neither supply missing evidence nor authorize sharing it\.$/], ['Record an accepted change', /A changed task agreement still does not create access to a new system\.$/], ]) { const section = dataBoundaries.sections.find((section) => section.title === title); assert.match(section.paragraphs[section.paragraphs.length - 1], tail); } const proportionate = dataBoundaries.sections.find((section) => section.title === 'Keep the agreement proportionate'); assert.equal(proportionate.paragraphs.length, 1); assert.equal(proportionate.links, undefined); assert.match(dataBoundaries.intro[0], /^AI agent data boundaries are the task-specific limits on which information an agent may read, use, retain, and share\./); const dataBoundariesHtml = renderStaticPage(guideTemplate, dataBoundariesGuide); assert.match(dataBoundariesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-data-boundaries\/"/); assert.match(dataBoundariesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(dataBoundariesHtml, /data boundar/); assert.doesNotMatch(dataBoundariesHtml, /seo-page-dark/); assert.doesNotMatch(dataBoundariesHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((dataBoundariesHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-work-contract/', '/guides/ai-agent-permissions-and-tokens/', '/guides/ai-agent-retained-context/', '/guides/ai-agent-audience-boundaries/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-data-boundaries\/"/g) || []).length, 1); } assert.ok(!dataBoundaries.sections.some((section) => section.title === dataBoundaries.cta.title)); assert.equal((dataBoundariesHtml.match(/

                      Define what to read, retain, and share<\/h2>/g) || []).length, 1); assert.ok(dataBoundariesHtml.indexOf('

                      Frequently asked questions

                      ') < dataBoundariesHtml.indexOf('

                      Define what to read, retain, and share

                      ')); assert.equal(dataBoundaries.cta.secondary.label, 'Explore Commonly’s guides'); const changeRequestsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-change-requests/'); assert.equal(changeRequestsGuide.title, 'AI Agent Change Requests: Update Scope Clearly | Commonly AI'); const changeRequests = guides['ai-agent-change-requests']; assert.deepEqual(changeRequests.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(changeRequests.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(changeRequests.sections.flatMap((section) => section.links || []).length, 9); assert.equal(changeRequests.faq.length, 6); const workedExampleIndex = changeRequests.sections.findIndex((section) => section.title === 'Work through a change request from proposal to revision'); const workedExample = changeRequests.sections[workedExampleIndex]; assert.equal(workedExample.paragraphs.length, 6); assert.equal(workedExample.tables, undefined); assert.equal(workedExample.links, undefined); assert.equal(workedExample.orderedItems, undefined); assert.equal(changeRequests.sections.slice(0, workedExampleIndex).filter((section) => section.tables).length, 8); assert.equal(changeRequests.sections[workedExampleIndex + 1].title, 'Check whether the change is ready to apply'); const stepsFollowOn = changeRequests.sections.find((section) => section.title === 'This process can fit in a short task update'); assert.equal(stepsFollowOn.paragraphs.length, 1); assert.equal(stepsFollowOn.links, undefined); assert.match(changeRequests.intro[0], /^An AI agent change request is a recorded proposal to alter a task’s outcome, requirements, inputs, permitted operations, audience, or acceptance criteria\./); const changeRequestsHtml = renderStaticPage(guideTemplate, changeRequestsGuide); assert.match(changeRequestsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-change-requests\/"/); assert.match(changeRequestsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(changeRequestsHtml, /change request/); assert.match(changeRequestsHtml, /A second confirmation is unnecessary when the owner’s instruction already specifies the change/); assert.doesNotMatch(changeRequestsHtml, /seo-page-dark/); assert.doesNotMatch(changeRequestsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((changeRequestsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-scope-creep/', '/guides/ai-agent-work-contract/', '/guides/ai-agent-acceptance-criteria/', '/guides/ai-agent-revision-loop/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-change-requests\/"/g) || []).length, 1); } assert.ok(!changeRequests.sections.some((section) => section.title === changeRequests.cta.title)); assert.equal((changeRequestsHtml.match(/

                      Update scope without silent drift<\/h2>/g) || []).length, 1); assert.ok(changeRequestsHtml.indexOf('

                      Frequently asked questions

                      ') < changeRequestsHtml.indexOf('

                      Update scope without silent drift

                      ')); assert.equal(changeRequests.cta.secondary.label, 'Explore Commonly’s guides'); const stopConditionsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-stop-conditions/'); assert.equal(stopConditionsGuide.title, 'AI Agent Stop Conditions: When Agents Should Halt | Commonly AI'); const stopConditions = guides['ai-agent-stop-conditions']; assert.deepEqual(stopConditions.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(stopConditions.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(stopConditions.sections.flatMap((section) => section.links || []).length, 9); const technicalEnforcement = stopConditions.sections.find((section) => section.title === 'Keep the stop condition separate from technical enforcement'); assert.equal(technicalEnforcement.paragraphs.length, 6); assert.equal(technicalEnforcement.tables, undefined); assert.deepEqual(technicalEnforcement.links.map((link) => link.path), ['/guides/ai-agent-acceptance-criteria/']); for (const title of ['An agent that stops precisely can be faster', 'The stop condition should make an agent’s next non-action deliberate']) { const section = stopConditions.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(stopConditions.intro[0], /^AI agent stop conditions are the facts or boundaries that require an agent to halt its current work rather than continue by assumption\./); const stopConditionsHtml = renderStaticPage(guideTemplate, stopConditionsGuide); assert.match(stopConditionsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-stop-conditions\/"/); assert.match(stopConditionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(stopConditionsHtml, /stop condition/); assert.doesNotMatch(stopConditionsHtml, /seo-page-dark/); assert.doesNotMatch(stopConditionsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((stopConditionsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-no-op/', '/guides/ai-agent-blockers/', '/guides/ai-agent-resume-conditions/', '/guides/ai-agent-escalation/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-stop-conditions\/"/g) || []).length, 1); } assert.ok(!stopConditions.sections.some((section) => section.title === stopConditions.cta.title)); assert.equal((stopConditionsHtml.match(/

                      Make stopping a useful, truthful contribution<\/h2>/g) || []).length, 1); assert.ok(stopConditionsHtml.indexOf('

                      Frequently asked questions

                      ') < stopConditionsHtml.indexOf('

                      Make stopping a useful, truthful contribution

                      ')); assert.equal(stopConditions.cta.secondary.label, 'Explore Commonly’s guides'); const audienceBoundariesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-audience-boundaries/'); assert.equal(audienceBoundariesGuide.title, 'AI Agent Audience Boundaries: Who an Agent May Address | Commonly AI'); const audienceBoundaries = guides['ai-agent-audience-boundaries']; assert.deepEqual(audienceBoundaries.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(audienceBoundaries.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(audienceBoundaries.sections.flatMap((section) => section.links || []).length, 9); const boundedReview = audienceBoundaries.sections.find((section) => section.title === 'Use a named reviewer for bounded review, not a general audience'); assert.equal(boundedReview.paragraphs.length, 6); assert.equal(boundedReview.tables, undefined); assert.deepEqual(boundedReview.links.map((link) => link.path), ['/guides/ai-agent-focused-threads/']); for (const title of ['If a test fails', 'The boundary is complete']) { const section = audienceBoundaries.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(audienceBoundaries.intro[0], /^AI agent audience boundaries define who an agent may address, what it may share with each audience, and which messages require a named owner before they become a commitment\./); const audienceBoundariesHtml = renderStaticPage(guideTemplate, audienceBoundariesGuide); assert.match(audienceBoundariesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-audience-boundaries\/"/); assert.match(audienceBoundariesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(audienceBoundariesHtml, /audience boundary/); assert.doesNotMatch(audienceBoundariesHtml, /seo-page-dark/); assert.doesNotMatch(audienceBoundariesHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((audienceBoundariesHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-roles/', '/guides/ai-agent-escalation/', '/guides/ai-agent-permissions-and-tokens/', '/guides/prompt-injection-defense-for-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-audience-boundaries\/"/g) || []).length, 1); } assert.ok(!audienceBoundaries.sections.some((section) => section.title === audienceBoundaries.cta.title)); assert.equal((audienceBoundariesHtml.match(/

                      Keep the right message with the right owner<\/h2>/g) || []).length, 1); assert.ok(audienceBoundariesHtml.indexOf('

                      Frequently asked questions

                      ') < audienceBoundariesHtml.indexOf('

                      Keep the right message with the right owner

                      ')); assert.equal(audienceBoundaries.cta.secondary.label, 'Explore Commonly’s guides'); const interimResultsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-interim-results/'); assert.equal(interimResultsGuide.title, 'AI Agent Interim Results: Useful Work Before Completion | Commonly AI'); const interimResults = guides['ai-agent-interim-results']; assert.deepEqual(interimResults.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(interimResults.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(interimResults.sections.flatMap((section) => section.links || []).length, 9); const preservedInterim = interimResults.sections.find((section) => section.title === 'Preserve an interim result for the next owner without turning it into authority'); assert.equal(preservedInterim.paragraphs.length, 6); assert.equal(preservedInterim.tables, undefined); assert.deepEqual(preservedInterim.links.map((link) => link.path), ['/guides/ai-agent-retained-context/']); assert.ok(interimResults.sections.some((section) => section.title === 'For example, an interim result names its gap')); for (const title of ['If the result fails a test', 'The result is complete']) { const section = interimResults.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(interimResults.intro[0], /^An AI agent interim result is a bounded artifact, finding, check, or status record returned before the primary task is complete\./); const interimResultsHtml = renderStaticPage(guideTemplate, interimResultsGuide); assert.match(interimResultsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-interim-results\/"/); assert.match(interimResultsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(interimResultsHtml, /remaining gap/); assert.doesNotMatch(interimResultsHtml, /seo-page-dark/); assert.doesNotMatch(interimResultsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((interimResultsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-blockers/', '/guides/ai-agent-resume-conditions/', '/guides/ai-agent-no-op/', '/guides/ai-agent-status-updates/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-interim-results\/"/g) || []).length, 1); } const taskSplittingGuide = guidePages.find((page) => page.path === '/guides/ai-agent-task-splitting/'); assert.equal(taskSplittingGuide.title, 'AI Agent Task Splitting: Divide Work Clearly | Commonly AI'); const taskSplitting = guides['ai-agent-task-splitting']; assert.deepEqual(taskSplitting.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(taskSplitting.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(taskSplitting.sections.flatMap((section) => section.links || []).length, 9); const sharedDecision = taskSplitting.sections.find((section) => section.title === 'Do not split work that still needs one shared decision'); assert.equal(sharedDecision.paragraphs.length, 6); assert.equal(sharedDecision.tables, undefined); assert.deepEqual(sharedDecision.links.map((link) => link.path), ['/guides/ai-agent-work-contract/']); assert.match(taskSplitting.sections.find((section) => section.title === 'An @mention').paragraphs[0], /^An @mention, a reaction, or a helpful reply can show participation\./); for (const title of ['If the split fails a test', 'The split is successful']) { const section = taskSplitting.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(taskSplitting.intro[0], /^AI agent task splitting is the practice of turning one broad request into several bounded tasks when the work needs distinct artifacts, owners, dependencies, acceptance criteria, or review points\./); const taskSplittingHtml = renderStaticPage(guideTemplate, taskSplittingGuide); assert.match(taskSplittingHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-task-splitting\/"/); assert.match(taskSplittingHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(taskSplittingHtml, /merge point/); assert.doesNotMatch(taskSplittingHtml, /seo-page-dark/); assert.doesNotMatch(taskSplittingHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((taskSplittingHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-dependency-management/', '/guides/ai-agent-follow-on-work/', '/guides/ai-agent-task-closure/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-task-splitting\/"/g) || []).length, 1); } const revisionLoopGuide = guidePages.find((page) => page.path === '/guides/ai-agent-revision-loop/'); assert.equal(revisionLoopGuide.title, 'AI Agent Revision Loop: Request, Revise, Re-Review | Commonly AI'); const revisionLoop = guides['ai-agent-revision-loop']; assert.deepEqual(revisionLoop.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(revisionLoop.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(revisionLoop.sections.flatMap((section) => section.links || []).length, 9); const revisionDiscussion = revisionLoop.sections.find((section) => section.title === 'Keep the revision discussion focused on the review question'); assert.equal(revisionDiscussion.paragraphs.length, 6); assert.equal(revisionDiscussion.tables, undefined); assert.deepEqual(revisionDiscussion.links.map((link) => link.path), ['/guides/ai-agent-focused-threads/']); for (const title of ['If the artifact fails a test', 'This sequence keeps revision work useful and finite']) { const section = revisionLoop.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(revisionLoop.intro[0], /^An AI agent revision loop is the bounded path from requested changes to a revised artifact and a new review answer\./); const revisionLoopHtml = renderStaticPage(guideTemplate, revisionLoopGuide); assert.match(revisionLoopHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-revision-loop\/"/); assert.match(revisionLoopHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(revisionLoopHtml, /return point/); assert.doesNotMatch(revisionLoopHtml, /seo-page-dark/); assert.doesNotMatch(revisionLoopHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((revisionLoopHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-review-decisions/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-artifact-versions/', '/guides/ai-agent-focused-threads/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-revision-loop\/"/g) || []).length, 1); } const retainedContextGuide = guidePages.find((page) => page.path === '/guides/ai-agent-retained-context/'); assert.equal(retainedContextGuide.title, 'AI Agent Retained Context: Keep Useful Context | Commonly AI'); const retainedContext = guides['ai-agent-retained-context']; assert.deepEqual(retainedContext.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(retainedContext.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(retainedContext.sections.flatMap((section) => section.links || []).length, 9); for (const [title, path] of [ ['Retain the work boundary, not an implied permission', '/guides/ai-agent-work-contract/'], ['Make follow-on work explicit instead of burying it in memory', '/guides/ai-agent-follow-on-work/'], ]) { const section = retainedContext.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 6); assert.equal(section.tables, undefined); assert.deepEqual(section.links.map((link) => link.path), [path]); } for (const title of ['Shared memory can preserve provenance and version history', 'If the note fails a test', 'The resulting note should help a future reader']) { const section = retainedContext.sections.find((section) => section.title === title); assert.equal(section.paragraphs.length, 1); assert.equal(section.links, undefined); } assert.match(retainedContext.intro[0], /^AI agent retained context is the selected information kept after a task so a later person or agent can reuse a sourced conclusion, understand where it applies, and find the record that supersedes or verifies it\./); const retainedContextHtml = renderStaticPage(guideTemplate, retainedContextGuide); assert.match(retainedContextHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-retained-context\/"/); assert.match(retainedContextHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(retainedContextHtml, /successor record/); assert.doesNotMatch(retainedContextHtml, /seo-page-dark/); assert.doesNotMatch(retainedContextHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((retainedContextHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-memory/', '/guides/ai-agent-task-closure/', '/guides/ai-agent-context-packet/', '/guides/ai-agent-artifact-versions/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-retained-context\/"/g) || []).length, 1); } const approvalBoundariesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-approval-boundaries/'); assert.equal(approvalBoundariesGuide.title, 'AI Agent Approval Boundaries: What Review Can Authorize | Commonly AI'); const approvalBoundaries = guides['ai-agent-approval-boundaries']; assert.deepEqual(approvalBoundaries.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(approvalBoundaries.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(approvalBoundaries.sections.flatMap((section) => section.links || []).length, 9); const approvalOwner = approvalBoundaries.sections.find((section) => section.title === 'Give each approval a decision owner'); assert.equal(approvalOwner.paragraphs.length, 8); assert.equal(approvalOwner.tables, undefined); assert.deepEqual(approvalOwner.links.map((link) => link.path), ['/guides/ai-agent-decision-owner/']); const sharedApprovalBoundary = approvalBoundaries.sections.find((section) => section.title === 'Use the same boundary across human and agent work'); assert.equal(sharedApprovalBoundary.paragraphs.length, 3); assert.equal(sharedApprovalBoundary.tables, undefined); assert.equal(sharedApprovalBoundary.links, undefined); const boundedAnswer = approvalBoundaries.sections.find((section) => section.title === 'Start by naming the actual question'); assert.equal(boundedAnswer.paragraphs.length, 2); assert.equal(boundedAnswer.links, undefined); assert.equal(approvalBoundaries.sections.find((section) => section.title === 'If one of these steps is missing').links, undefined); assert.match(approvalBoundaries.intro[0], /^AI agent approval boundaries define what a visible approval changes—and what it does not\./); assert.match(approvalBoundaries.intro[1], /@mentions/); const approvalBoundariesHtml = renderStaticPage(guideTemplate, approvalBoundariesGuide); assert.match(approvalBoundariesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-approval-boundaries\/"/); assert.match(approvalBoundariesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(approvalBoundariesHtml, /continuing limit/); assert.doesNotMatch(approvalBoundariesHtml, /seo-page-dark/); assert.doesNotMatch(approvalBoundariesHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((approvalBoundariesHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-permissions-and-tokens/', '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-governance/', '/guides/ai-agent-review-decisions/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-approval-boundaries\/"/g) || []).length, 1); } const focusedThreadsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-focused-threads/'); assert.equal(focusedThreadsGuide.title, 'AI Agent Focused Threads: One Review or Decision | Commonly AI'); const focusedThreads = guides['ai-agent-focused-threads']; assert.deepEqual(focusedThreads.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(focusedThreads.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(focusedThreads.sections.flatMap((section) => section.links || []).length, 9); const focusedThreadRoles = focusedThreads.sections.find((section) => section.title === 'Use focused threads across human and agent roles'); assert.equal(focusedThreadRoles.paragraphs.length, 5); assert.equal(focusedThreadRoles.tables, undefined); assert.deepEqual(focusedThreadRoles.links.map((link) => link.path), ['/guides/ai-agent-status-updates/']); assert.equal(focusedThreads.sections.find((section) => section.title === 'The thread earns its focus').links, undefined); assert.match(focusedThreads.intro[0], /^AI agent focused threads are dedicated conversations for one review question, decision, or bounded issue\./); assert.match(focusedThreads.intro[1], /@mentions/); const focusedThreadsHtml = renderStaticPage(guideTemplate, focusedThreadsGuide); assert.match(focusedThreadsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-focused-threads\/"/); assert.match(focusedThreadsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(focusedThreadsHtml, /answerable question/); assert.doesNotMatch(focusedThreadsHtml, /seo-page-dark/); assert.doesNotMatch(focusedThreadsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((focusedThreadsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-decision-owner/', '/guides/ai-agent-review-decisions/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-focused-threads\/"/g) || []).length, 1); } const contextPacketGuide = guidePages.find((page) => page.path === '/guides/ai-agent-context-packet/'); assert.equal(contextPacketGuide.title, 'AI Agent Context Packet: Current Context for One Step | Commonly AI'); const contextPacket = guides['ai-agent-context-packet']; assert.deepEqual(contextPacket.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(contextPacket.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(contextPacket.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(contextPacket.sections.find((section) => section.title === 'The source link is part of the field').links.map((link) => link.path), ['/guides/ai-agent-source-of-record/', '/guides/ai-agent-work-contract/']); assert.equal(contextPacket.sections.find((section) => section.title === 'The packet should be short enough to work from').links, undefined); assert.match(contextPacket.intro[0], /^An AI agent context packet is the smallest current, source-linked bundle an agent or reviewer needs to complete one bounded task step\./); const contextPacketHtml = renderStaticPage(guideTemplate, contextPacketGuide); assert.match(contextPacketHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-context-packet\/"/); assert.match(contextPacketHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(contextPacketHtml, /source-linked bundle/); assert.doesNotMatch(contextPacketHtml, /seo-page-dark/); assert.doesNotMatch(contextPacketHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((contextPacketHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/context-engineering-for-ai-agents/', '/guides/ai-agent-source-of-record/', '/guides/ai-agent-task-intake/', '/guides/ai-agent-task-closure/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-context-packet\/"/g) || []).length, 1); } const taskClosureGuide = guidePages.find((page) => page.path === '/guides/ai-agent-task-closure/'); assert.equal(taskClosureGuide.title, 'AI Agent Task Closure: Record What Done Means | Commonly AI'); const taskClosure = guides['ai-agent-task-closure']; assert.deepEqual(taskClosure.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(taskClosure.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(taskClosure.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(taskClosure.sections.find((section) => section.title === 'Closing a path does not erase the reason it existed').links.map((link) => link.path), ['/guides/ai-agent-no-op/', '/guides/ai-agent-blockers/']); assert.equal(taskClosure.sections.find((section) => section.title === 'Closure is a short final accounting').links, undefined); assert.match(taskClosure.intro[0], /^AI agent task closure is the act of recording why a bounded task is done, what artifact or result it produced, what evidence supports that result, which decision or review applies, and what remains outside the task\./); const taskClosureHtml = renderStaticPage(guideTemplate, taskClosureGuide); assert.match(taskClosureHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-task-closure\/"/); assert.match(taskClosureHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(taskClosureHtml, /verification boundary/); assert.doesNotMatch(taskClosureHtml, /seo-page-dark/); assert.doesNotMatch(taskClosureHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((taskClosureHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-artifact-versions/', '/guides/ai-agent-follow-on-work/', '/guides/ai-agent-no-op/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-task-closure\/"/g) || []).length, 1); } const artifactVersionsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-artifact-versions/'); assert.equal(artifactVersionsGuide.title, 'AI Agent Artifact Versions: Make Work Reviewable | Commonly AI'); const artifactVersions = guides['ai-agent-artifact-versions']; assert.deepEqual(artifactVersions.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(artifactVersions.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(artifactVersions.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(artifactVersions.sections.find((section) => section.title === 'Version identity can be a document revision').links.map((link) => link.path), ['/guides/ai-agent-review-packet/', '/guides/ai-agent-source-of-record/']); assert.equal(artifactVersions.sections.find((section) => section.title === 'The goal is not a ceremonial version number').links, undefined); assert.match(artifactVersions.intro[0], /^AI agent artifact versions are stable, identifiable states of a draft, evidence packet, plan, review packet, decision packet, task result, or other work product\./); const artifactVersionsHtml = renderStaticPage(guideTemplate, artifactVersionsGuide); assert.match(artifactVersionsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-artifact-versions\/"/); assert.match(artifactVersionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(artifactVersionsHtml, /superseded/); assert.doesNotMatch(artifactVersionsHtml, /seo-page-dark/); assert.doesNotMatch(artifactVersionsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((artifactVersionsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-review-packet/', '/guides/ai-agent-review-decisions/', '/guides/ai-agent-verification-path/', '/guides/ai-agent-audit-trail/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-artifact-versions\/"/g) || []).length, 1); } const decisionOwnerGuide = guidePages.find((page) => page.path === '/guides/ai-agent-decision-owner/'); assert.equal(decisionOwnerGuide.title, 'AI Agent Decision Owner: Who Can Give the Answer? | Commonly AI'); const decisionOwner = guides['ai-agent-decision-owner']; assert.deepEqual(decisionOwner.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(decisionOwner.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(decisionOwner.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(decisionOwner.sections.find((section) => section.title === 'The question should make ownership legible').links.map((link) => link.path), ['/guides/ai-agent-decision-packet/', '/guides/ai-agent-source-of-record/']); assert.equal(decisionOwner.sections.find((section) => section.title === 'The process makes ownership a property of a defined choice').links, undefined); assert.match(decisionOwner.intro[0], /^An AI agent decision owner is the person, role, or designated authority accountable for answering a specific bounded question\./); const decisionOwnerHtml = renderStaticPage(guideTemplate, decisionOwnerGuide); assert.match(decisionOwnerHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-decision-owner\/"/); assert.match(decisionOwnerHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(decisionOwnerHtml, /accountable owner/); assert.doesNotMatch(decisionOwnerHtml, /seo-page-dark/); assert.doesNotMatch(decisionOwnerHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((decisionOwnerHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-decision-packet/', '/guides/ai-agent-review-decisions/', '/guides/ai-agent-task-intake/', '/guides/ai-agent-escalation/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-decision-owner\/"/g) || []).length, 1); } const intakeGuide = guidePages.find((page) => page.path === '/guides/ai-agent-task-intake/'); assert.equal(intakeGuide.title, 'AI Agent Task Intake: Make Work Eligible | Commonly AI'); const intake = guides['ai-agent-task-intake']; assert.deepEqual(intake.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(intake.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(intake.sections.flatMap((section) => section.links || []).length, 9); const intakeHandoff = intake.sections.find((section) => section.title === 'Preserve intake context in the task and handoff'); assert.equal(intakeHandoff.paragraphs.length, 5); assert.equal(intakeHandoff.tables, undefined); assert.deepEqual(intakeHandoff.links.map((link) => link.path), ['/guides/ai-agent-follow-on-work/']); assert.equal(intake.sections.find((section) => section.title === 'Intake succeeds when the next contribution is clear').links, undefined); assert.match(intake.intro[0], /^AI agent task intake is the process of turning a request, observation, or decision into a bounded task/); const intakeHtml = renderStaticPage(guideTemplate, intakeGuide); assert.match(intakeHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-task-intake\/"/); assert.match(intakeHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(intakeHtml, /first artifact/); assert.doesNotMatch(intakeHtml, /seo-page-dark/); assert.doesNotMatch(intakeHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((intakeHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-work-contract/', '/guides/ai-agent-non-goals/', '/guides/ai-agent-blockers/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-task-intake\/"/g) || []).length, 1); } const dependencyGuide = guidePages.find((page) => page.path === '/guides/ai-agent-dependency-management/'); assert.equal(dependencyGuide.title, 'AI Agent Dependency Management: Required States | Commonly AI'); const dependency = guides['ai-agent-dependency-management']; assert.deepEqual(dependency.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(dependency.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(dependency.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(dependency.sections.find((section) => section.title === 'The distinction makes the board easier to read').links.map((link) => link.path), ['/guides/ai-agent-blockers/', '/guides/ai-agent-follow-on-work/']); assert.equal(dependency.sections.find((section) => section.title === 'This keeps dependencies from becoming a background excuse').links, undefined); assert.match(dependency.intro[0], /^AI agent dependency management is the practice of making one task’s required relationship/); const dependencyHtml = renderStaticPage(guideTemplate, dependencyGuide); assert.match(dependencyHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-dependency-management\/"/); assert.match(dependencyHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(dependencyHtml, /prerequisite owner/); assert.doesNotMatch(dependencyHtml, /seo-page-dark/); assert.doesNotMatch(dependencyHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((dependencyHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-blockers/', '/guides/ai-agent-resume-conditions/', '/guides/ai-agent-task-management/', '/guides/ai-agent-work-contract/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-dependency-management\/"/g) || []).length, 1); } const evidenceLabelsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-evidence-labels/'); assert.equal(evidenceLabelsGuide.title, 'AI Agent Evidence Labels: Facts, Inferences, Decisions | Commonly AI'); const evidenceLabels = guides['ai-agent-evidence-labels']; assert.deepEqual(evidenceLabels.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(evidenceLabels.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(evidenceLabels.sections.flatMap((section) => section.links || []).length, 9); const evidenceHandoff = evidenceLabels.sections.find((section) => section.title === 'Carry labels through handoffs and durable context'); assert.equal(evidenceHandoff.paragraphs.length, 6); assert.deepEqual(evidenceHandoff.links.map((link) => link.path), ['/guides/ai-agent-handoffs/']); assert.equal(evidenceHandoff.tables, undefined); assert.equal(evidenceLabels.sections.find((section) => section.title === 'The labels are a reading aid').links, undefined); assert.match(evidenceLabels.intro[0], /^AI agent evidence labels identify what kind of statement a record makes and how a reviewer should treat it\./); const evidenceLabelsHtml = renderStaticPage(guideTemplate, evidenceLabelsGuide); assert.match(evidenceLabelsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-evidence-labels\/"/); assert.match(evidenceLabelsHtml, /AI agent evidence labels identify what kind of statement/); assert.match(evidenceLabelsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(evidenceLabelsHtml, /seo-page-dark/); assert.match(evidenceLabelsHtml, /reported status/); assert.doesNotMatch(evidenceLabelsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((evidenceLabelsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-verification-path/', '/guides/ai-agent-source-of-record/', '/guides/ai-agent-review-packet/', '/guides/ai-agent-decision-packet/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-evidence-labels\/"/g) || []).length, 1); } const nonGoalsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-non-goals/'); assert.equal(nonGoalsGuide.title, 'AI Agent Non-Goals: Write Clear Task Boundaries | Commonly AI'); const nonGoals = guides['ai-agent-non-goals']; assert.deepEqual(nonGoals.sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(nonGoals.sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(nonGoals.sections.flatMap((section) => section.links || []).length, 9); assert.deepEqual(nonGoals.sections.find((section) => section.title === 'The wording should be testable').links.map((link) => link.path), ['/guides/ai-agent-work-contract/', '/guides/ai-agent-task-management/']); assert.equal(nonGoals.sections.find((section) => section.title === 'The purpose is not to make a task defensive').links, undefined); assert.match(nonGoals.intro[0], /^AI agent non-goals are explicit statements of work a task, role, or review stage will not do\./); const nonGoalsHtml = renderStaticPage(guideTemplate, nonGoalsGuide); assert.match(nonGoalsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-non-goals\/"/); assert.match(nonGoalsHtml, /AI agent non-goals are explicit statements of work/); assert.match(nonGoalsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(nonGoalsHtml, /seo-page-dark/); assert.match(nonGoalsHtml, /excluded work/); assert.doesNotMatch(nonGoalsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((nonGoalsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-work-contract/', '/guides/ai-agent-scope-creep/', '/guides/ai-agent-follow-on-work/', '/guides/ai-agent-no-op/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.equal((html.match(/href="\/guides\/ai-agent-non-goals\/"/g) || []).length, 1); } const reviewDecisionsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-review-decisions/'); assert.equal(reviewDecisionsGuide.title, 'AI Agent Review Decisions: Five Clear Answers | Commonly AI'); assert.deepEqual(guides['ai-agent-review-decisions'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6], [3, 6]]); assert.deepEqual(guides['ai-agent-review-decisions'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-review-decisions'].sections.flatMap((section) => section.links || []).length, 9); assert.equal(guides['ai-agent-review-decisions'].sections.find((section) => section.title === 'Record the decision where the next step can use it').paragraphs.length, 4); const reviewDecisionsHtml = renderStaticPage(guideTemplate, reviewDecisionsGuide); assert.match(reviewDecisionsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-review-decisions\//); assert.match(reviewDecisionsHtml, /AI agent review decisions are the explicit answers/); assert.match(reviewDecisionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(reviewDecisionsHtml, /seo-page-dark/); assert.match(reviewDecisionsHtml, /review stage/); assert.doesNotMatch(reviewDecisionsHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((reviewDecisionsHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/ai-agent-review-packet/', '/guides/ai-agent-acceptance-criteria/', '/guides/ai-agent-decision-packet/', '/guides/ai-agent-escalation/', ]) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agent-review-decisions\//); } for (const guidePath of [ '/guides/what-is-an-ai-agent-runtime/', '/guides/connect-a-custom-agent-http-api/', '/guides/ai-agent-heartbeats-and-scheduled-work/', '/guides/ai-agent-security-best-practices/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-cli\//); } const orchestrationGuide = guidePages.find((page) => page.path === '/guides/ai-agent-orchestration/'); assert.equal(orchestrationGuide.title, 'AI Agent Orchestration: Coordinate Work Through Shared State | Commonly AI'); const orchestrationHtml = renderStaticPage(guideTemplate, orchestrationGuide); assert.match(orchestrationHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-orchestration\/"/); assert.match(orchestrationHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.match(orchestrationHtml, /shared state/); assert.doesNotMatch(orchestrationHtml, /cm_agent_[A-Za-z0-9]{8,}/); const skillsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-skills/'); assert.equal(skillsGuide.title, 'AI Agent Skills: Reusable Workflows for Reliable Agents | Commonly AI'); const skillsHtml = renderStaticPage(guideTemplate, skillsGuide); assert.match(skillsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-skills\/"/); assert.match(skillsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(skillsHtml, /seo-page-dark/); assert.match(skillsHtml, /source-backed-review/); assert.doesNotMatch(skillsHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-memory/', '/guides/ai-agent-handoffs/', '/guides/ai-agent-heartbeats-and-scheduled-work/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-skills\//); } const autonomousGuide = guidePages.find((page) => page.path === '/guides/autonomous-ai-agents/'); assert.equal(autonomousGuide.title, 'Autonomous AI Agents: A Practical Operating Model for Teams | Commonly AI'); const autonomousHtml = renderStaticPage(guideTemplate, autonomousGuide); assert.match(autonomousHtml, /href="https:\/\/commonly\.me\/guides\/autonomous-ai-agents\/"/); assert.match(autonomousHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(autonomousHtml, /seo-page-dark/); assert.match(autonomousHtml, /role contract/); assert.doesNotMatch(autonomousHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-heartbeats-and-scheduled-work/', '/guides/ai-agent-task-management/', '/guides/ai-agent-security-best-practices/', '/guides/human-in-the-loop-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/autonomous-ai-agents\//); } const sandboxingGuide = guidePages.find((page) => page.path === '/guides/ai-agent-sandboxing/'); assert.equal(sandboxingGuide.title, 'AI Agent Sandboxing: Reduce the Blast Radius of Untrusted Input | Commonly AI'); const sandboxingHtml = renderStaticPage(guideTemplate, sandboxingGuide); assert.match(sandboxingHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-sandboxing\/"/); assert.match(sandboxingHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(sandboxingHtml, /seo-page-dark/); assert.match(sandboxingHtml, /blast radius/); assert.doesNotMatch(sandboxingHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-permissions-and-tokens/', '/guides/ai-agent-security-best-practices/', '/guides/what-is-an-ai-agent-runtime/', '/guides/autonomous-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-sandboxing\//); } const toolsGuide = guidePages.find((page) => page.path === '/guides/ai-agent-tools/'); assert.equal(toolsGuide.title, 'AI Agent Tools: What They Are and How to Choose Them | Commonly AI'); const toolsHtml = renderStaticPage(guideTemplate, toolsGuide); assert.match(toolsHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-tools\/"/); assert.match(toolsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(toolsHtml, /seo-page-dark/); assert.match(toolsHtml, /toolset/); assert.doesNotMatch(toolsHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-skills/', '/guides/ai-agent-task-management/', '/guides/ai-agent-memory/', '/guides/ai-agent-cli/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-tools\//); } const promptInjectionGuide = guidePages.find((page) => page.path === '/guides/prompt-injection-defense-for-ai-agents/'); assert.equal(promptInjectionGuide.title, 'Prompt Injection Defense for AI Agents: Contain the Capability | Commonly AI'); const promptInjectionHtml = renderStaticPage(guideTemplate, promptInjectionGuide); assert.match(promptInjectionHtml, /href="https:\/\/commonly\.me\/guides\/prompt-injection-defense-for-ai-agents\/"/); assert.match(promptInjectionHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(promptInjectionHtml, /seo-page-dark/); assert.match(promptInjectionHtml, /capability boundaries/); assert.doesNotMatch(promptInjectionHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-sandboxing/', '/guides/ai-agent-security-best-practices/', '/guides/ai-agent-permissions-and-tokens/', '/guides/human-in-the-loop-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/prompt-injection-defense-for-ai-agents\//); } const mcpGuide = guidePages.find((page) => page.path === '/guides/mcp-for-ai-agent-teams/'); assert.equal(mcpGuide.title, 'MCP for AI Agent Teams: Connect Tools Without Losing Context | Commonly AI'); const mcpHtml = renderStaticPage(guideTemplate, mcpGuide); assert.match(mcpHtml, /href="https:\/\/commonly\.me\/guides\/mcp-for-ai-agent-teams\/"/); assert.match(mcpHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(mcpHtml, /seo-page-dark/); assert.match(mcpHtml, /connection path/); assert.doesNotMatch(mcpHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/connect-a-custom-agent-http-api/', '/guides/what-is-an-ai-agent-runtime/', '/guides/ai-agent-permissions-and-tokens/', '/guides/ai-agent-tools/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/mcp-for-ai-agent-teams\//); } const agenticAiGuide = guidePages.find((page) => page.path === '/guides/what-is-agentic-ai/'); assert.equal(agenticAiGuide.title, 'What Is Agentic AI? A Practical Definition for Teams | Commonly AI'); const agenticAiHtml = renderStaticPage(guideTemplate, agenticAiGuide); assert.match(agenticAiHtml, /href="https:\/\/commonly\.me\/guides\/what-is-agentic-ai\/"/); assert.match(agenticAiHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(agenticAiHtml, /seo-page-dark/); assert.match(agenticAiHtml, /work loop/); assert.doesNotMatch(agenticAiHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/autonomous-ai-agents/', '/guides/ai-agent-tools/', '/guides/ai-agent-task-management/', '/guides/human-in-the-loop-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/what-is-agentic-ai\//); } const aiAgentGuide = guidePages.find((page) => page.path === '/guides/what-is-an-ai-agent/'); assert.equal(aiAgentGuide.title, 'What Is an AI Agent? A Practical Definition for Teams | Commonly AI'); const aiAgentHtml = renderStaticPage(guideTemplate, aiAgentGuide); assert.match(aiAgentHtml, /href="https:\/\/commonly\.me\/guides\/what-is-an-ai-agent\/"/); assert.match(aiAgentHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(aiAgentHtml, /seo-page-dark/); assert.match(aiAgentHtml, /participant/); assert.doesNotMatch(aiAgentHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/what-is-agentic-ai/', '/guides/what-is-an-ai-agent-runtime/', '/guides/what-is-an-agent-pod/', '/guides/ai-agent-task-management/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/what-is-an-ai-agent\/"/); } const contextEngineeringGuide = guidePages.find((page) => page.path === '/guides/context-engineering-for-ai-agents/'); assert.equal(contextEngineeringGuide.title, 'Context Engineering for AI Agents: Give Each Decision the Right State | Commonly AI'); const contextEngineeringHtml = renderStaticPage(guideTemplate, contextEngineeringGuide); assert.match(contextEngineeringHtml, /href="https:\/\/commonly\.me\/guides\/context-engineering-for-ai-agents\/"/); assert.match(contextEngineeringHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(contextEngineeringHtml, /seo-page-dark/); assert.match(contextEngineeringHtml, /context packet/); assert.doesNotMatch(contextEngineeringHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-memory/', '/guides/ai-agent-task-management/', '/guides/prompt-injection-defense-for-ai-agents/', '/guides/what-is-agentic-ai/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/context-engineering-for-ai-agents\//); } const evaluationGuide = guidePages.find((page) => page.path === '/guides/how-to-evaluate-ai-agents/'); assert.equal(evaluationGuide.title, 'How to Evaluate AI Agents: Test the Work, Not Just the Answer | Commonly AI'); const evaluationHtml = renderStaticPage(guideTemplate, evaluationGuide); assert.match(evaluationHtml, /href="https:\/\/commonly\.me\/guides\/how-to-evaluate-ai-agents\/"/); assert.match(evaluationHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(evaluationHtml, /seo-page-dark/); assert.match(evaluationHtml, /acceptance criteria/); assert.doesNotMatch(evaluationHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/context-engineering-for-ai-agents/', '/guides/human-in-the-loop-ai-agents/', '/guides/prompt-injection-defense-for-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/how-to-evaluate-ai-agents\//); } const chatbotGuide = guidePages.find((page) => page.path === '/guides/ai-agent-vs-chatbot/'); assert.equal(chatbotGuide.title, 'AI Agent vs. Chatbot: What Is the Difference? | Commonly AI'); const chatbotHtml = renderStaticPage(guideTemplate, chatbotGuide); assert.match(chatbotHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-vs-chatbot\/"/); assert.match(chatbotHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(chatbotHtml, /seo-page-dark/); assert.match(chatbotHtml, /bounded contribution/); assert.doesNotMatch(chatbotHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/what-is-an-ai-agent/', '/guides/what-is-agentic-ai/', '/guides/multi-agent-vs-single-agent/', '/guides/ai-agent-tools/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-vs-chatbot\//); } const useCasesGuide = guidePages.find((page) => page.path === '/guides/ai-agent-use-cases/'); assert.equal(useCasesGuide.title, 'AI Agent Use Cases: Eight Roles Teams Can Start Safely | Commonly AI'); const useCasesHtml = renderStaticPage(guideTemplate, useCasesGuide); assert.match(useCasesHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-use-cases\/"/); assert.match(useCasesHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(useCasesHtml, /seo-page-dark/); assert.match(useCasesHtml, /reviewable result/); assert.doesNotMatch(useCasesHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/what-is-an-ai-agent/', '/guides/ai-agent-orchestration/', '/guides/human-in-the-loop-ai-agents/', '/guides/how-to-evaluate-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-use-cases\//); } const collaborationGuide = guidePages.find((page) => page.path === '/guides/human-ai-collaboration/'); assert.equal(collaborationGuide.title, 'Human-AI Collaboration: How Teams Work Together With AI Agents | Commonly AI'); const collaborationHtml = renderStaticPage(guideTemplate, collaborationGuide); assert.match(collaborationHtml, /href="https:\/\/commonly\.me\/guides\/human-ai-collaboration\//); assert.match(collaborationHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(collaborationHtml, /seo-page-dark/); assert.match(collaborationHtml, /decision owner/); assert.doesNotMatch(collaborationHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-handoffs/', '/guides/ai-agent-collaboration-patterns/', '/guides/ai-agent-memory/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/human-ai-collaboration\//); } const workflowsGuide = guidePages.find((page) => page.path === '/guides/agentic-workflows/'); assert.equal(workflowsGuide.title, 'Agentic Workflows: How to Design AI Agent Work That Teams Can Trust | Commonly AI'); const workflowsHtml = renderStaticPage(guideTemplate, workflowsGuide); assert.match(workflowsHtml, /href="https:\/\/commonly\.me\/guides\/agentic-workflows\//); assert.match(workflowsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(workflowsHtml, /seo-page-dark/); assert.match(workflowsHtml, /eligible trigger/); assert.doesNotMatch(workflowsHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/what-is-agentic-ai/', '/guides/context-engineering-for-ai-agents/', '/guides/ai-agent-use-cases/', '/guides/ai-agent-handoffs/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/agentic-workflows\//); } const projectManagementGuide = guidePages.find((page) => page.path === '/guides/ai-agents-for-project-management/'); assert.equal(projectManagementGuide.title, 'AI Agents for Project Management: Coordinate Work Without Losing Ownership | Commonly AI'); const projectManagementHtml = renderStaticPage(guideTemplate, projectManagementGuide); assert.match(projectManagementHtml, /href="https:\/\/commonly\.me\/guides\/ai-agents-for-project-management\//); assert.match(projectManagementHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(projectManagementHtml, /seo-page-dark/); assert.match(projectManagementHtml, /decision packet/); assert.doesNotMatch(projectManagementHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-use-cases/', '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-orchestration/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agents-for-project-management\//); } const instructionsGuide = guidePages.find((page) => page.path === '/guides/how-to-write-ai-agent-instructions/'); assert.equal(instructionsGuide.title, 'How to Write AI Agent Instructions: A Practical Role Contract | Commonly AI'); const instructionsHtml = renderStaticPage(guideTemplate, instructionsGuide); assert.match(instructionsHtml, /href="https:\/\/commonly\.me\/guides\/how-to-write-ai-agent-instructions\//); assert.match(instructionsHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(instructionsHtml, /seo-page-dark/); assert.match(instructionsHtml, /role contract/); assert.doesNotMatch(instructionsHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/context-engineering-for-ai-agents/', '/guides/how-to-evaluate-ai-agents/', '/guides/human-ai-collaboration/', '/guides/ai-agent-handoffs/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/how-to-write-ai-agent-instructions\//); } const researchGuide = guidePages.find((page) => page.path === '/guides/ai-agents-for-research/'); assert.equal(researchGuide.title, 'AI Agents for Research: Build Evidence Packets Teams Can Use | Commonly AI'); const researchHtml = renderStaticPage(guideTemplate, researchGuide); assert.match(researchHtml, /href="https:\/\/commonly\.me\/guides\/ai-agents-for-research\//); assert.match(researchHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(researchHtml, /seo-page-dark/); assert.match(researchHtml, /evidence packet/); assert.doesNotMatch(researchHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/ai-agent-use-cases/', '/guides/context-engineering-for-ai-agents/', '/guides/how-to-evaluate-ai-agents/', '/guides/ai-agents-for-project-management/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agents-for-research\//); } const supportGuide = guidePages.find((page) => page.path === '/guides/ai-agents-for-customer-support/'); assert.equal(supportGuide.title, 'AI Agents for Customer Support: Triage, Context, and Safe Handoffs | Commonly AI'); const supportHtml = renderStaticPage(guideTemplate, supportGuide); assert.match(supportHtml, /href="https:\/\/commonly\.me\/guides\/ai-agents-for-customer-support\//); assert.match(supportHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(supportHtml, /seo-page-dark/); assert.match(supportHtml, /triage packet/); assert.doesNotMatch(supportHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((supportHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/prompt-injection-defense-for-ai-agents/', '/guides/ai-agent-use-cases/', '/guides/how-to-write-ai-agent-instructions/', '/guides/human-in-the-loop-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agents-for-customer-support\//); } const multiAgentSystemGuide = guidePages.find((page) => page.path === '/guides/what-is-a-multi-agent-system/'); assert.equal(multiAgentSystemGuide.title, 'What Is a Multi-Agent System? A Practical Definition for Teams | Commonly AI'); assert.deepEqual( guides['what-is-a-multi-agent-system'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 5], [3, 6], [3, 5], [2, 6], [3, 5], [4, 5], [3, 7]], ); assert.deepEqual(guides['what-is-a-multi-agent-system'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [6, 6]); assert.equal(guides['what-is-a-multi-agent-system'].sections.flatMap((section) => section.links || []).length, 6); const multiAgentSystemHtml = renderStaticPage(guideTemplate, multiAgentSystemGuide); assert.match(multiAgentSystemHtml, /href="https:\/\/commonly\.me\/guides\/what-is-a-multi-agent-system\//); assert.match(multiAgentSystemHtml, /A multi-agent system is a coordinated set of two or more AI agents/); assert.match(multiAgentSystemHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(multiAgentSystemHtml, /seo-page-dark/); assert.match(multiAgentSystemHtml, /operating model/); assert.doesNotMatch(multiAgentSystemHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/multi-agent-vs-single-agent/', '/guides/how-to-write-ai-agent-instructions/', '/guides/ai-agent-memory/', '/guides/ai-agent-task-management/', '/guides/ai-agent-handoffs/', '/guides/human-in-the-loop-ai-agents/', ]) { assert.match(multiAgentSystemHtml, new RegExp('href="' + guidePath + '"')); } for (const guidePath of [ '/guides/multi-agent-vs-single-agent/', '/guides/what-is-an-ai-agent/', '/guides/ai-agent-task-management/', '/guides/ai-agent-handoffs/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/what-is-a-multi-agent-system\/"/); } const glossaryGuide = guidePages.find((page) => page.path === '/guides/ai-agent-glossary/'); assert.equal(glossaryGuide.title, 'AI Agent Glossary: Essential Terms for Building Agent Teams | Commonly AI'); const glossaryData = guides['ai-agent-glossary']; assert.deepEqual( glossaryData.sections.filter((section) => !section.paragraphs).map((section) => section.title), ['Core agent terms', 'Collaboration and workspace terms', 'Context and memory terms', 'Capability and safety terms', 'Governance and evaluation terms'], ); assert.equal(glossaryData.sections.filter((section) => section.paragraphs).length, 36); assert.equal(glossaryData.sections.flatMap((section) => section.links || []).length, 19); assert.equal(glossaryData.sections.some((section) => section.tables || section.bullets || section.orderedItems || section.codeBlocks), false); const glossaryHtml = renderStaticPage(guideTemplate, glossaryGuide); assert.match(glossaryHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-glossary\//); assert.match(glossaryHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(glossaryHtml, /seo-page-dark/); assert.match(glossaryHtml, /shared vocabulary/); assert.doesNotMatch(glossaryHtml, /cm_agent_[A-Za-z0-9]{8,}/); for (const guidePath of [ '/guides/what-is-an-ai-agent/', '/guides/what-is-agentic-ai/', '/guides/what-is-a-multi-agent-system/', '/guides/how-to-write-ai-agent-instructions/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-glossary\/"/); } const governanceGuide = guidePages.find((page) => page.path === '/guides/ai-agent-governance/'); assert.equal(governanceGuide.title, 'AI Agent Governance: Roles, Boundaries, and Review | Commonly AI'); assert.deepEqual( guides['ai-agent-governance'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [4, 5], [3, 7], [3, 5], [3, 6], [3, 6], [3, 6], [3, 5]], ); assert.deepEqual(guides['ai-agent-governance'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agent-governance'].sections.flatMap((section) => section.links || []).length, 9); const governanceHtml = renderStaticPage(guideTemplate, governanceGuide); assert.match(governanceHtml, /href="https:\/\/commonly\.me\/guides\/ai-agent-governance\//); assert.match(governanceHtml, /AI agent governance is the operating model that decides who may assign work/); assert.match(governanceHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(governanceHtml, /seo-page-dark/); assert.match(governanceHtml, /review trigger/); assert.doesNotMatch(governanceHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((governanceHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of [ '/guides/human-in-the-loop-ai-agents/', '/guides/ai-agent-permissions-and-tokens/', '/guides/ai-agent-security-best-practices/', '/guides/how-to-evaluate-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-governance\/"/); } const softwareDevelopmentGuide = guidePages.find((page) => page.path === '/guides/ai-agents-for-software-development/'); assert.equal(softwareDevelopmentGuide.title, 'AI Agents for Software Development: Reviewable Changes | Commonly AI'); assert.deepEqual(guides['ai-agents-for-software-development'].sections.flatMap((section) => (section.tables || []).map((table) => [table.headers.length, table.rows.length])), [[3, 6], [3, 8], [3, 6], [3, 7], [3, 6], [3, 6], [2, 8]]); assert.deepEqual(guides['ai-agents-for-software-development'].sections.filter((section) => section.orderedItems).map((section) => section.orderedItems.length), [7]); assert.equal(guides['ai-agents-for-software-development'].sections.flatMap((section) => section.links || []).length, 8); const softwareDevelopmentHtml = renderStaticPage(guideTemplate, softwareDevelopmentGuide); assert.match(softwareDevelopmentHtml, /href="https:\/\/commonly\.me\/guides\/ai-agents-for-software-development\//); assert.match(softwareDevelopmentHtml, /Commonly \(commonly\.me\), the shared workspace where humans and AI agents work together/); assert.doesNotMatch(softwareDevelopmentHtml, /seo-page-dark/); assert.match(softwareDevelopmentHtml, /change contract/); assert.doesNotMatch(softwareDevelopmentHtml, /cm_agent_[A-Za-z0-9]{8,}/); assert.equal((softwareDevelopmentHtml.match(/

                      Frequently asked questions<\/h2>/g) || []).length, 1); for (const guidePath of ['/guides/ai-agent-use-cases/', '/guides/ai-agent-task-management/', '/guides/context-engineering-for-ai-agents/', '/guides/how-to-evaluate-ai-agents/']) { assert.match(renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)), /href="\/guides\/ai-agents-for-software-development\/"/); } for (const guidePath of [ '/guides/what-is-an-agent-pod/', '/guides/ai-agent-handoffs/', '/guides/ai-agent-collaboration-patterns/', '/guides/multi-agent-vs-single-agent/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-orchestration\//); } for (const guidePath of [ '/guides/ai-agent-heartbeats-and-scheduled-work/', '/guides/connect-a-custom-agent-http-api/', '/guides/what-is-an-ai-agent-runtime/', '/guides/connect-claude-codex-shared-workspace/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/connect-openclaw-agent\//); } for (const guidePath of [ '/guides/ai-agent-permissions-and-tokens/', '/guides/ai-agent-memory/', '/guides/ai-agent-handoffs/', '/guides/connect-openclaw-agent/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-security-best-practices\//); } for (const guidePath of [ '/guides/multi-agent-collaboration-platform/', '/guides/ai-agent-workspace/', '/guides/ai-agent-task-management/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/connect-claude-codex-shared-workspace\//); } for (const guidePath of [ '/guides/multi-agent-collaboration-platform/', '/guides/ai-agent-workspace/', '/guides/ai-agent-task-management/', '/guides/connect-claude-codex-shared-workspace/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-memory\//); } for (const guidePath of [ '/guides/multi-agent-collaboration-platform/', '/guides/ai-agent-workspace/', '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-memory/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/self-hosted-ai-agent-platform\//); } for (const guidePath of [ '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-task-management/', '/guides/how-to-build-an-ai-agent-team/', '/guides/self-hosted-ai-agent-platform/', '/guides/agent-to-agent-messaging/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-permissions-and-tokens\//); } for (const guidePath of [ '/guides/ai-agent-workspace/', '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-permissions-and-tokens/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/connect-cursor-shared-workspace\//); } for (const guidePath of [ '/guides/ai-agent-task-management/', '/guides/ai-agent-memory/', '/guides/how-to-build-an-ai-agent-team/', '/guides/agent-to-agent-messaging/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-observability\//); } for (const guidePath of [ '/guides/agent-to-agent-messaging/', '/guides/ai-agent-observability/', '/guides/connect-claude-codex-shared-workspace/', '/guides/connect-cursor-shared-workspace/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-events\//); } for (const guidePath of [ '/guides/multi-agent-collaboration-platform/', '/guides/how-to-build-an-ai-agent-team/', '/guides/ai-agent-handoffs/', '/guides/agent-to-agent-messaging/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/multi-agent-vs-single-agent\//); } for (const guidePath of [ '/guides/multi-agent-vs-single-agent/', '/guides/how-to-build-an-ai-agent-team/', '/guides/ai-agent-handoffs/', '/guides/human-in-the-loop-ai-agents/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-collaboration-patterns\//); } for (const guidePath of [ '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-permissions-and-tokens/', '/guides/how-to-build-an-ai-agent-team/', '/guides/ai-agent-collaboration-patterns/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/onboarding-an-ai-agent-to-your-team\//); } for (const guidePath of [ '/guides/ai-agent-events/', '/guides/onboarding-an-ai-agent-to-your-team/', '/guides/ai-agent-task-management/', '/guides/ai-agent-collaboration-patterns/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-discord-integration\//); } for (const guidePath of [ '/guides/ai-agent-events/', '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-permissions-and-tokens/', '/guides/multi-agent-vs-single-agent/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/what-is-an-ai-agent-runtime\//); } for (const guidePath of [ '/guides/ai-agent-events/', '/guides/what-is-an-ai-agent-runtime/', '/guides/ai-agent-memory/', '/guides/ai-agent-task-management/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-heartbeats-and-scheduled-work\//); } for (const guidePath of [ '/guides/what-is-an-ai-agent-runtime/', '/guides/onboarding-an-ai-agent-to-your-team/', '/guides/how-to-build-an-ai-agent-team/', '/guides/ai-agent-collaboration-patterns/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/ai-agent-marketplace-roles\//); } for (const guidePath of [ '/guides/what-is-an-ai-agent-runtime/', '/guides/connect-claude-codex-shared-workspace/', '/guides/ai-agent-events/', '/guides/ai-agent-permissions-and-tokens/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/connect-a-custom-agent-http-api\//); } for (const guidePath of [ '/guides/ai-agent-workspace/', '/guides/what-is-an-ai-agent-runtime/', '/guides/ai-agent-memory/', '/guides/ai-agent-collaboration-patterns/', ]) { const html = renderStaticPage(guideTemplate, pages.find((page) => page.path === guidePath)); assert.match(html, /href="\/guides\/what-is-an-agent-pod\//); } const guidesIndex = pages.find((page) => page.path === '/guides/'); assert.equal(guidesIndex.title, 'Guides for teams working with AI agents | Commonly AI'); assert.equal(guidesIndex.schema['@graph'].find((item) => item['@type'] === 'WebPage').name, 'Guides for teams working with AI agents'); assert.match(indexHtml, /#seo-page \{[^}]*color: #111827; background: #f8f8fb;/); assert.match(indexHtml, /#seo-page \.seo-code \{[^}]*color: #111827; background: #f4f3f8;/); }); test('puts route content, canonical metadata, and structured data in the document', () => { const page = { path: '/example/', title: 'Example page | Commonly AI', description: 'An example description.', content: '

                      Example page

                      Home
                      ', schema: { '@context': 'https://schema.org', '@type': 'WebPage', name: 'Example page' }, }; const template = '
                      '; const rendered = renderStaticPage(template, page); assert.match(rendered, /

                      Example page<\/h1>/); assert.match(rendered, / { // The landing adds both from React, which crawlers that run no JS never see. Runs the real generator // against a temp build dir seeded with the Vite template, so the production FAQ read is covered too. const outputDir = await mkdtemp(join(tmpdir(), 'seo-faq-')); try { // What Vite emits: the source entry rewritten to a hashed asset (the generator strips it on static-only pages). const source = await readFile(resolve(frontendDir, 'index.html'), 'utf8'); await writeFile(join(outputDir, 'index.html'), source.replace('src="/src/index.tsx"', 'src="/assets/index-test.js"')); const [faqText, faqSource] = await Promise.all([ readFile(resolve(frontendDir, 'src/content/landing-faq.json'), 'utf8'), readFile(resolve(frontendDir, 'src/v2/landing/landingFaq.ts'), 'utf8'), ]); const landingFaq = JSON.parse(faqText); const pages = await generateSeoPages({ outputDir }); const rendered = await readFile(join(outputDir, 'index.html'), 'utf8'); assert.equal(landingFaq.length, 6); assert.ok(rendered.includes('"@type":"FAQPage"')); // The landing effect finds this tag by id and reuses it rather than adding a second FAQPage. assert.ok(faqSource.includes("FAQ_JSONLD_ID = 'landing-faq-jsonld'")); assert.equal(rendered.match(/id="landing-faq-jsonld"/g).length, 1); const faqLd = JSON.parse(rendered.match(/id="landing-faq-jsonld">([^<]*)<\/script>/)[1]); assert.deepEqual(faqLd.mainEntity.map((q) => [q.name, q.acceptedAnswer.text]), landingFaq.map((item) => [item.question, item.answer])); const escape = (value) => value.replaceAll('&', '&').replaceAll('"', '"').replaceAll("'", '''); for (const item of landingFaq) { assert.ok(rendered.includes(`
                      ${escape(item.question)}
                      `), item.question); assert.ok(rendered.includes(`
                      ${escape(item.answer)}
                      `), item.answer); } // Every other page stays without it. assert.ok(pages.filter((page) => page.path !== '/').every((page) => !page.faqSchema)); } finally { await rm(outputDir, { recursive: true, force: true }); } }); test('the compare page is unlisted: noindex, out of the sitemap, and linked from nothing', async () => { const [translationText, useCaseText, guideText, llmsText] = await Promise.all([ readFile(resolve(frontendDir, 'src/i18n/locales/en.json'), 'utf8'), readFile(resolve(frontendDir, 'src/content/use-cases.json'), 'utf8'), readFile(resolve(frontendDir, 'src/content/guides.json'), 'utf8'), readFile(resolve(frontendDir, 'public/llms.txt'), 'utf8'), ]); const translations = JSON.parse(translationText); const useCases = JSON.parse(useCaseText); const guides = JSON.parse(guideText); const pages = buildPageDefinitions({ landing: translations.landing, compare: translations.compare, useCases, guides }); const template = '
                      '; const compare = pages.find((page) => page.path === '/compare/'); assert.equal(compare.noindex, true); assert.match(renderStaticPage(template, compare), //); for (const page of pages.filter((item) => item.path !== '/compare/')) { assert.match(renderStaticPage(template, page), //, page.path); assert.doesNotMatch(renderStaticPage(template, page), /href="\/compare\/"/, page.path); } assert.doesNotMatch(guideText, /"\/compare\/"/); assert.doesNotMatch(llmsText, /\/compare\//); const outputDir = await mkdtemp(resolve(tmpdir(), 'seo-compare-')); await writeFile(resolve(outputDir, 'index.html'), template); await generateSeoPages({ outputDir }); const sitemap = await readFile(resolve(outputDir, 'sitemap.xml'), 'utf8'); assert.doesNotMatch(sitemap, /https:\/\/commonly\.me\/compare\/<\/loc>/); assert.match(sitemap, /https:\/\/commonly\.me\/compare\/openagents\/<\/loc>/); assert.match(sitemap, /https:\/\/commonly\.me\/use-cases\/team-chat\/<\/loc>/); }); test('a compare page renders GTM markdown and refuses to build while a HOLD is open', () => { const html = renderMarkdown([ '# Title', '', 'A **bold** claim with `code` and [a link](https://example.com/x) and https://example.org/y.', '', '| | Left | Right |', '|---|---|---|', '| **Row** | one [1] | two |', '', '- first', '- second', '', '1. step one', '', '', ].join('\n')); assert.match(html, /

                      Title<\/h1>/); assert.match(html, /

                      A bold<\/strong> claim with code<\/code> and a link<\/a> and https:\/\/example\.org\/y<\/a>\.<\/p>/); assert.match(html, /

Row<\/strong><\/th>one \[1\]<\/td>two<\/td>/); assert.match(html, /
  • first<\/li>
  • second<\/li><\/ul>/); assert.match(html, /
    1. step one<\/li><\/ol>/); assert.doesNotMatch(html, /internal note/); assert.doesNotThrow(() => assertNoOpenHolds('/compare/example/', 'Walked claims only.')); assert.throws(() => assertNoOpenHolds('/compare/example/', 'Claim. [HOLD: walk pending]'), /1 open bracketed marker/); assert.throws(() => assertNoOpenHolds('/compare/example/', 'Claim. [HOLD]'), /\[HOLD\]/); assert.throws(() => assertNoOpenHolds('/compare/example/', 'Source note. [re-check at publish and update this date]'), /re-check at publish/); assert.throws(() => assertNoOpenHolds('/compare/example/', 'Claim. [TODO: confirm the price]'), /TODO/); assert.throws(() => assertNoOpenHolds('/compare/example/', 'Empty [] marker'), /\[\]/); assert.doesNotThrow(() => assertNoOpenHolds('/compare/example/', 'Cited [1][5] and [a link](https://example.com/x).')); });