diff --git a/docs/content/community/join-hive-commons.md b/docs/content/community/join-hive-commons.md new file mode 100644 index 0000000..a2967d3 --- /dev/null +++ b/docs/content/community/join-hive-commons.md @@ -0,0 +1,60 @@ +# Join Hive Commons + +Hive Commons is an umbrella for **like-minded open source projects** that make +working with AI coding agents safer, more observable, and more accountable. +If that describes your project, we invite you to propose joining the family. + +## What we look for + +- **Removes real friction** for people working with coding agents: + orchestration, governance, spec-driven workflows, attribution, session + tooling, observability, safety. +- **Shares our values.** Openness (design and decisions happen in public), + human accountability (every action traces to a named person), and governance + enforced in code rather than in prose. +- **Open source, properly.** Apache 2.0 (or willing to relicense), DCO + sign-off on every commit, CNCF Code of Conduct. +- **Maintained.** At least one active maintainer willing to show up at the + biweekly community meeting while the project settles in. + +Projects do not need to depend on Hive. hotshot, pluk, promptargs and dibs are +all useful entirely on their own — they belong here because they solve +adjacent problems for the same people. + +## What you get + +- A home in the [hivecommons](https://github.com/hivecommons) GitHub + organization with shared governance, security policy, and CI conventions. +- A section on this docs site, synced from your repository, and a card on + [hivecommons.dev](https://hivecommons.dev). +- A slot in the community meeting and the mailing lists to reach Hive + operators and contributors. +- Optionally, a hive of your own: Hive can run governed agent swarms against + your repositories as a spoke of the Hive Commons hub. + +## How to propose a project + +Open a **project proposal** issue — it is a short form: + +**[→ Propose a project to join Hive Commons](https://github.com/hivecommons/.github/issues/new?template=join-hive-commons.yml)** + +The form asks for the repository, what the project does, how it fits the +family, license, maintainers, and adoption. Maintainers decide by lazy +consensus per [GOVERNANCE.md](https://github.com/hivecommons/.github/blob/main/GOVERNANCE.md) +and will reply on the issue; if it's a fit we'll invite you to present at a +community meeting and work through the move together. + +## Other ways to get involved + +Not ready to bring a whole project? You're still welcome: + +- **Run a hive** against your own repositories — see + [Getting started with Hive](/docs/hive/getting-started) and add yourself to + [ADOPTERS.md](https://github.com/hivecommons/hive/blob/v5/ADOPTERS.md). +- **Contribute** to any repository in the organization — + [CONTRIBUTING.md](https://github.com/hivecommons/.github/blob/main/CONTRIBUTING.md) + covers the contributor ladder. +- **Join the conversation** on + [hivecommons-dev@googlegroups.com](https://groups.google.com/g/hivecommons-dev), + [Discord](https://hivecommons.dev/discord), or the biweekly + [community meeting](https://hivecommons.dev/agenda). diff --git a/docs/content/community/what-is-hive-commons.md b/docs/content/community/what-is-hive-commons.md new file mode 100644 index 0000000..d1ee9e7 --- /dev/null +++ b/docs/content/community/what-is-hive-commons.md @@ -0,0 +1,78 @@ +# What is Hive Commons? + +**Hive Commons is the umbrella community for Hive** — an AI-agent fleet +orchestration system that runs governed swarms of coding agents against real +repositories — and for the family of tools that grew up around it. + +Our founding premise: **human judgment is the scarce resource.** Agents are +tooling. Every decision, every merge, and every identity belongs to a named +human, and governance is enforced in code rather than in prose. + +## What Hive does + +Hive is a control layer for running governed fleets of AI coding agents. +Agents pick up issues, open pull requests, review code, repair CI, and answer +contributors — under a six-level maturity model (ACMM, the AI-native +Capability Maturity Model) that decides exactly what they may do and enforces +it with matching least-privilege GitHub token scopes. + +- **Hub and spokes.** A single Go binary that runs as a Kubernetes workload, a + Docker Compose stack, or Podman Quadlet units. An optional hub coordinates + many self-hosted spoke hives, with a public registry and cross-hive + leaderboards. +- **Governance in code.** Trust is dialed up one capability at a time, from + advisory-only (L1) through to merging on green CI (L6). +- **Audited and accountable.** A deterministic pipeline handles filtering, + classification, and merge-gating before any LLM sees the work; agents only + handle judgment calls, and every action lands in the audit log. + +Hive is used in production by KubeStellar Console, tunaos.org, and Project +Bluefin; see [ADOPTERS.md](https://github.com/hivecommons/hive/blob/v5/ADOPTERS.md) +for the current list. + +## The project family + +Hive is the orchestration system and the delivery surface for the family. +Each tool beside it removes a specific piece of friction from working with +agents, and each is useful on its own. + +| Project | What it does | Docs | +|---|---|---| +| [**Hive**](https://github.com/hivecommons/hive) — flagship | A control layer for running governed fleets of AI coding agents against real repositories. | [Hive docs](/docs/hive/overview/introduction) | +| [**Spektacular**](https://github.com/hivecommons/spektacular) — newest member | Spec-driven development for AI coding agents. A markdown spec becomes a reviewed plan and an agent-driven implementation, each step a resumable state machine. | [Spektacular docs](/docs/spektacular/overview/introduction) · [spektacular.dev](https://spektacular.dev) | +| [**hotshot**](https://github.com/hivecommons/hotshot) | Screenshots that land directly in an AI coding assistant's terminal. | [hotshot docs](/docs/hotshot/overview/introduction) | +| [**pluk**](https://github.com/hivecommons/pluk) | Structured event streaming for tmux sessions running AI coding agents. | [pluk docs](/docs/pluk/overview/introduction) | +| [**promptargs**](https://github.com/hivecommons/promptargs) | Template expansion for prompts across Claude Code, Copilot, Goose, Bob, and others. | [promptargs docs](/docs/promptargs/overview/introduction) | +| [**rationguard**](https://github.com/hivecommons/rationguard) | Detects and rebuts rationalization patterns in agent output. | [rationguard docs](/docs/rationguard/overview/introduction) | +| [**dibs**](https://github.com/hivecommons/dibs) | A contributor attribution layer for the AI-agent era. Your idea, your credit, their code. | [README](https://github.com/hivecommons/dibs#readme) | + +### How the pieces fit + +Spektacular handles **one feature at a time**: spec → plan → implement, with +a human review between each step. Hive is where that work is **scaled up** — +it orchestrates fleets of agents across repositories with the governance and +audit trail that running agents at that scale demands. A Spektacular workflow +is the unit of work a fleet orchestrator schedules. hotshot, pluk, promptargs, +rationguard and dibs sit alongside both, making the individual agent session +more observable, more reproducible, and properly attributed. + +## An open community + +Every repository in the organization is Apache 2.0 licensed, requires DCO +sign-off on every commit, and follows the CNCF Code of Conduct. Hive is +maintained by a Maintainer Committee spanning multiple organizations, with a +documented contributor ladder and explicit governance for AI-agent +contributions. Hive Commons has applied for the +[CNCF Sandbox](https://github.com/cncf/sandbox/issues/516). + +- [Governance](https://github.com/hivecommons/.github/blob/main/GOVERNANCE.md) · [Maintainers](https://github.com/hivecommons/.github/blob/main/MAINTAINERS.md) · [Code of Conduct](https://github.com/hivecommons/.github/blob/main/CODE_OF_CONDUCT.md) · [Security policy](https://github.com/hivecommons/.github/blob/main/SECURITY.md) +- **Mailing list:** [hivecommons-dev@googlegroups.com](https://groups.google.com/g/hivecommons-dev) — joining adds the community meeting to your calendar +- **Community meeting:** every other Thursday, 10:00 AM ET — [agenda and notes](https://hivecommons.dev/agenda) · [recordings](https://hivecommons.dev/tv) +- **Chat:** [Discord](https://hivecommons.dev/discord) +- **Website:** [hivecommons.dev](https://hivecommons.dev) + +## Is your project a fit? + +If you maintain an open source project that removes friction from working +with AI coding agents and you share these values, we'd like to hear from you. +See [Join Hive Commons](/docs/community/join-hive-commons). diff --git a/scripts/check-internal-links-helpers.test.ts b/scripts/check-internal-links-helpers.test.ts index e3cdb46..6e7439f 100644 --- a/scripts/check-internal-links-helpers.test.ts +++ b/scripts/check-internal-links-helpers.test.ts @@ -120,17 +120,17 @@ describe("ASSET_EXT", () => { }); describe("PROJECT_FOR_NAV", () => { - it("maps the default KUBESTELLAR nav to bare 'docs' (no project subpath)", () => { - expect(PROJECT_FOR_NAV.KUBESTELLAR).toBe("docs"); + it("maps the shared GENERAL nav to bare 'docs' (no project subpath)", () => { + expect(PROJECT_FOR_NAV.GENERAL).toBe("docs"); }); it("maps each project nav to its base path", () => { expect(PROJECT_FOR_NAV.HIVE).toBe("docs/hive"); - expect(PROJECT_FOR_NAV.CONSOLE).toBe("docs/console"); - expect(PROJECT_FOR_NAV.KUBEFLEX).toBe("docs/kubeflex"); - expect(PROJECT_FOR_NAV.KUBESTELLAR_MCP).toBe("docs/kubestellar-mcp"); - expect(PROJECT_FOR_NAV.A2A).toBe("docs/a2a"); - expect(PROJECT_FOR_NAV.MULTI_PLUGIN).toBe("docs/multi-plugin"); + expect(PROJECT_FOR_NAV.HOTSHOT).toBe("docs/hotshot"); + expect(PROJECT_FOR_NAV.PLUK).toBe("docs/pluk"); + expect(PROJECT_FOR_NAV.RATIONGUARD).toBe("docs/rationguard"); + expect(PROJECT_FOR_NAV.PROMPTARGS).toBe("docs/promptargs"); + expect(PROJECT_FOR_NAV.SPEKTACULAR).toBe("docs/spektacular"); }); }); diff --git a/scripts/check-internal-links-helpers.ts b/scripts/check-internal-links-helpers.ts index dd64578..d5e2115 100644 --- a/scripts/check-internal-links-helpers.ts +++ b/scripts/check-internal-links-helpers.ts @@ -76,13 +76,15 @@ export const ASSET_EXT = * resolution). */ export const PROJECT_FOR_NAV: Record = { - A2A: "docs/a2a", - MULTI_PLUGIN: "docs/multi-plugin", - KUBEFLEX: "docs/kubeflex", - KUBESTELLAR_MCP: "docs/kubestellar-mcp", - CONSOLE: "docs/console", HIVE: "docs/hive", - KUBESTELLAR: "docs", + HOTSHOT: "docs/hotshot", + PLUK: "docs/pluk", + RATIONGUARD: "docs/rationguard", + PROMPTARGS: "docs/promptargs", + SPEKTACULAR: "docs/spektacular", + // Shared sections (Community, …) live under docs/content/
/ and + // are served at /docs/
/. + GENERAL: "docs", }; /** diff --git a/src/__tests__/check-internal-links-helpers.test.ts b/src/__tests__/check-internal-links-helpers.test.ts index 551c937..0bfdc52 100644 --- a/src/__tests__/check-internal-links-helpers.test.ts +++ b/src/__tests__/check-internal-links-helpers.test.ts @@ -273,23 +273,23 @@ describe("resolveInternalLink", () => { describe("PROJECT_FOR_NAV", () => { it("maps every documented project name to its docs base path", () => { expect(PROJECT_FOR_NAV).toEqual({ - A2A: "docs/a2a", - MULTI_PLUGIN: "docs/multi-plugin", - KUBEFLEX: "docs/kubeflex", - KUBESTELLAR_MCP: "docs/kubestellar-mcp", - CONSOLE: "docs/console", HIVE: "docs/hive", - KUBESTELLAR: "docs", + HOTSHOT: "docs/hotshot", + PLUK: "docs/pluk", + RATIONGUARD: "docs/rationguard", + PROMPTARGS: "docs/promptargs", + SPEKTACULAR: "docs/spektacular", + GENERAL: "docs", }); }); - it("uses docs/ for every non-kubestellar project", () => { - // The root Kubestellar project lives at docs/ (no sub-slug); every + it("uses docs/ for every project nav", () => { + // The shared GENERAL nav lives at docs/ (no sub-slug); every // other project must be under docs/. This invariant is what // makes route registration deterministic — breaking it would move // nav aliases to the wrong path and mass-report broken links. for (const [name, base] of Object.entries(PROJECT_FOR_NAV)) { - if (name === "KUBESTELLAR") { + if (name === "GENERAL") { expect(base).toBe("docs"); } else { expect(base.startsWith("docs/")).toBe(true); @@ -449,7 +449,7 @@ expect(sectioned.sectionSlug).toBe("whats-new"); const NAV_STRUCTURE_HIVE = [ { 'Intro': 'intro.md' }, ] - const NAV_STRUCTURE_CONSOLE = [ + const NAV_STRUCTURE_HOTSHOT = [ { 'Home': 'home.md' }, ] `; @@ -460,12 +460,12 @@ expect(sectioned.sectionSlug).toBe("whats-new"); byNav.set(e.navName, list); } expect(byNav.get("HIVE")).toEqual(["/docs/hive/intro"]); - expect(byNav.get("CONSOLE")).toEqual(["/docs/console/home"]); + expect(byNav.get("HOTSHOT")).toEqual(["/docs/hotshot/home"]); }); - it("handles the KUBESTELLAR base (root docs path, no sub-slug)", () => { + it("handles the GENERAL base (root docs path, no sub-slug)", () => { const src = ` - const NAV_STRUCTURE_KUBESTELLAR = [ + const NAV_STRUCTURE_GENERAL = [ { 'Getting Started': 'getting-started.md' }, ] `; diff --git a/src/app/docs/[...slug]/page.tsx b/src/app/docs/[...slug]/page.tsx index 02e644f..392cc16 100644 --- a/src/app/docs/[...slug]/page.tsx +++ b/src/app/docs/[...slug]/page.tsx @@ -5,7 +5,7 @@ import { useMDXComponents as getMDXComponents } from '../../../../mdx-components import { convertHtmlScriptsToJsxComments } from '@/lib/transformMdx' import { sanitizeHtmlForMdx, removeCommentPatterns } from '@/lib/sanitizeHtml' import { rewriteRelativeImagePaths } from '@/lib/rewriteImagePaths' -import { buildPageMap, docsContentPath, getContentPath } from '../page-map' +import { buildPageMap, docsContentPath, getContentPath, isGeneralSectionFile } from '../page-map' import { CURRENT_VERSION, type ProjectId } from '@/config/versions' import fs from 'fs' import path from 'path' @@ -267,6 +267,9 @@ export async function generateStaticParams(): Promise> for (const projectId of STATIC_PROJECTS) { const { routeMap } = buildPageMap(projectId) for (const routeKey of Object.keys(routeMap)) { + // General sections are routed at /docs/
/..., not per project; + // collectParams(docsContentPath) above already covers them. + if (isGeneralSectionFile(routeKey)) continue addParam([projectId, ...routeKey.split('/')]) } } diff --git a/src/app/docs/page-map.ts b/src/app/docs/page-map.ts index b88034c..2ea38ee 100644 --- a/src/app/docs/page-map.ts +++ b/src/app/docs/page-map.ts @@ -176,8 +176,30 @@ const NAV_STRUCTURE_SPEKTACULAR: Array<{ title: string; items: NavItem[] }> = [ } ] +// Shared sections that appear once, below the projects, in every sidebar. +// Files live in docs/content/
/ (not synced from any project) and +// are routed at /docs/
/... — see GENERAL_SECTION_DIRS. +const GENERAL_SECTION_DIRS = ['contributing', 'community', 'news'] as const +const NAV_STRUCTURE_GENERAL: Array<{ title: string; items: NavItem[] }> = [ + { + title: 'Community', + items: [ + { 'What is Hive Commons?': 'community/what-is-hive-commons.md' }, + { 'Join Hive Commons': 'community/join-hive-commons.md' }, + ] + } +] + +export function isGeneralSectionFile(file: string): boolean { + return GENERAL_SECTION_DIRS.some(dir => file.startsWith(`${dir}/`)) +} + // Get navigation structure for a project function getNavStructure(projectId: ProjectId): Array<{ title: string; items: NavItem[] }> { + return [...getProjectNavStructure(projectId), ...NAV_STRUCTURE_GENERAL] +} + +function getProjectNavStructure(projectId: ProjectId): Array<{ title: string; items: NavItem[] }> { switch (projectId) { case 'hotshot': return NAV_STRUCTURE_HOTSHOT @@ -200,7 +222,11 @@ export function buildPageMap(projectId: ProjectId = 'hive') { const projectBasePath = getBasePath(projectId) const navStructure = getNavStructure(projectId) - const allDocFiles = getAllDocFiles(contentPath) + // Project files plus the shared general-section files from docs/content/. + const allDocFiles = [ + ...getAllDocFiles(contentPath), + ...getAllDocFiles(docsContentPath).filter(isGeneralSectionFile), + ] const processedFiles = new Set() const routeMap: Record = {} const _pageMap: PageMapNode[] = []