Skip to content

Feat/.DesignDocs : A Proposal for Synchronized Documentation Across the Hummingbot Ecosystem #612

@VeXHarbinger

Description

@VeXHarbinger

Feature Suggestion

Why .DesignDocs — A Proposal for Synchronized Documentation Across the Hummingbot Ecosystem

Overview

The Hummingbot project spans several independent repositories — gateway, hummingbot-api, dashboard, and others under the Hummingbot GitHub organization. Each of these repos currently maintains its own copies of foundational documents like README.md, AGENTS.md, CODE_OF_CONDUCT.md, and CONTRIBUTING.md. Over time, these documents inevitably drift out of sync: policy updates get applied to one repo and forgotten in others, links rot, contributor guidelines diverge, and the project presents an inconsistent face to the community.

This document proposes the creation of a central .DesignDocs repository (or a top-level folder in an existing monorepo) that serves as the single source of truth for all shared documentation, and a GitHub Actions workflow that automatically publishes those documents into every tagged downstream repo.


The Problem: Documentation Drift

Symptom Impact
CONTRIBUTING.md differs between gateway and core New contributors receive conflicting instructions
CODE_OF_CONDUCT.md updated in one repo, forgotten elsewhere Inconsistent community standards
AGENTS.md / CLAUDE.md AI guidance files diverge AI agents behave differently per repo
TERMS_OF_USE.md is stale in some repos Legal and compliance risk
README.md AI directives aren't highlighted In this usage, an AI focused Read Me with directions. Not the repo readme

All of these are symptoms of the same root cause: no single authoritative source for shared documents.


The Solution: A Shared .DesignDocs Directory

Concept

  1. A dedicated repository (e.g., hummingbot/design-docs) — or the .DesignDocs folder within an existing repo — holds the canonical versions of all cross-project documents.
  2. Any repo that should receive those files is tagged with a GitHub topic: hummingbot-design-docs.
  3. A GitHub Actions workflow on the .DesignDocs repo watches for merges to main and automatically opens a Pull Request in every tagged downstream repo, placing the updated files inside a .DesignDocs/ directory.
  4. Each downstream repo can still maintain repo-specific .md files inside its own .DesignDocs/ folder alongside the synced ones. The publish step only overwrites the files it owns (tracked via a .managed manifest shipped with the sync). Repo-specific files — like GATEWAY_RULES.md — are never touched by the central sync.

Folder Structure (example)

design-docs/                  ← central source repo
├── README.md                 ← AI directives index: lists every .DesignDocs file
│                               and explains its purpose for easy AI prompt inclusion
│                               (NOT the repo's public-facing README)
├── AGENTS.md                 ← AI coding agent guidance (all repos)
├── CLAUDE.md                 ← Claude-specific guidance
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── TERMS_OF_USE.md
├── CHANGELOG_TEMPLATE.md
├── MANAGED_FILES             ← plain-text manifest listing every file this repo owns
.github/
    └── workflows/
        └── publish.yml       ← the automation workflow

Each downstream repo after sync:

gateway/
├── .DesignDocs/
│   ├── README.md               ← managed by design-docs (AI directives index)
│   ├── AGENTS.md               ← managed by design-docs
│   ├── CODE_OF_CONDUCT.md      ← managed by design-docs
│   ├── CONTRIBUTING.md         ← managed by design-docs
│   ├── TERMS_OF_USE.md         ← managed by design-docs
│   ├── MANAGED_FILES           ← manifest shipped by design-docs; lists lines above
│   └── GATEWAY_RULES.md        ← gateway-owned; never touched by the central sync
└── src/
    └── ...

The MANAGED_FILES manifest (a simple newline-delimited text file) is what allows both the publish workflow and the downstream protection check to know exactly which files belong to the central repo and which belong to the downstream repo.

Documents Worth Sharing — and Why

File Reason to centralize
README.md AI directives index — lives inside .DesignDocs/ only; lists every file in the folder with a short description so AI agents can reference it as a table of contents. This is not the public repo README.
AGENTS.md AI coding agent guidance — must be uniform so agents behave predictably
CLAUDE.md / CURSOR_VSCODE_SETUP.md Tool-specific AI context files; benefits every contributor
CODE_OF_CONDUCT.md Legal/community obligation — one version, enforced everywhere
CONTRIBUTING.md Onboarding document — inconsistency is the #1 contributor friction point
TERMS_OF_USE.md Legal document — must be identical everywhere for compliance
CHANGELOG_TEMPLATE.md Standardizes the format of release notes across the ecosystem

Automating the Publish Step with GitHub Actions

Overview of the Flow

Push/merge to main (design-docs repo)
        │
        ▼
GitHub Actions: publish.yml
        │
        ├─► Discover all repos tagged `hummingbot-design-docs` via GitHub API
        │
        ├─► For each downstream repo:
        │     ├── Checkout repo
        │     ├── Copy updated files into .DesignDocs/
        │     └── Open Pull Request against main (or develop in GitFlow)
        │
        └─► Notify via Slack / GitHub Discussions (optional)

Sample Workflow: publish.yml

# .github/workflows/publish.yml
# Runs on every push to main in the design-docs repository.
# Opens a Pull Request in every repo tagged `hummingbot-design-docs`.

name: Publish DesignDocs

on:
  push:
    branches:
      - main
  workflow_dispatch:           # allow manual trigger

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: read           # read this repo
      pull-requests: write     # not used here — PRs are opened via PAT below

    steps:
      - name: Checkout source (design-docs)
        uses: actions/checkout@v4

      - name: Discover tagged repositories
        id: discover
        env:
          GH_TOKEN: ${{ secrets.ORG_PUBLISH_PAT }}   # PAT with repo + PR scope
        run: |
          # Fetch all repos in the org tagged with our sync topic
          repos=$(gh api \
            "orgs/hummingbot/repos?per_page=100" \
            --jq '[.[] | select(.topics[] | contains("hummingbot-design-docs")) | .full_name] | @json')
          echo "repos=$repos" >> "$GITHUB_OUTPUT"

      - name: Publish to each downstream repo
        env:
          GH_TOKEN: ${{ secrets.ORG_PUBLISH_PAT }}
          REPOS: ${{ steps.discover.outputs.repos }}
        run: |
          BRANCH="chore/sync-design-docs-$(date +%Y%m%d%H%M%S)"
          echo "$REPOS" | jq -r '.[]' | while read -r repo; do
            echo "▶ Processing $repo"

            # Clone the downstream repo (shallow)
            git clone --depth 1 "https://x-access-token:${GH_TOKEN}@github.com/${repo}.git" downstream
            cd downstream

            # Copy only the files listed in MANAGED_FILES — never touches repo-specific docs
            mkdir -p .DesignDocs
            while IFS= read -r managed_file || [ -n "$managed_file" ]; do
              [[ -z "$managed_file" || "$managed_file" == \#* ]] && continue   # skip blanks/comments
              cp "../${managed_file}" ".DesignDocs/${managed_file}"
            done < ../MANAGED_FILES
            cp ../MANAGED_FILES .DesignDocs/MANAGED_FILES   # always ship the manifest itself

            # Skip if there are no changes
            if git diff --quiet; then
              echo "  No changes for $repo — skipping"
              cd ..
              rm -rf downstream
              continue
            fi

            # Commit and push feature branch
            git config user.name  "github-actions[bot]"
            git config user.email "github-actions[bot]@users.noreply.github.com"
            git checkout -b "$BRANCH"
            git add .DesignDocs/
            git commit -m "chore: sync .DesignDocs from design-docs@$(git -C .. rev-parse --short HEAD)"
            git push origin "$BRANCH"

            # Open Pull Request targeting `develop` (GitFlow) or `main`
            gh pr create \
              --repo "$repo" \
              --head "$BRANCH" \
              --base "develop" \
              --title "chore: sync .DesignDocs shared documentation" \
              --body "Automated sync from the [design-docs](https://github.com/hummingbot/design-docs) repository.

          **Do not edit files inside \`.DesignDocs/\` directly** — changes will be overwritten on the next sync.
          To propose changes to shared documents, open a PR in the design-docs repo instead." \
              --label "documentation,automated"

            cd ..
            rm -rf downstream
          done

Required Setup

Item Details
ORG_PUBLISH_PAT A fine-grained PAT with Contents: write and Pull Requests: write on all tagged repos. Store as an org-level Actions secret.
Repo topics Each downstream repo must have the hummingbot-design-docs topic set under Settings → General → Topics.
Branch protection Target branch (develop or main) should allow the bot to push via the PAT, or use a bypass rule for the Actions user.
MANAGED_FILES manifest A newline-delimited file at the root of the design-docs repo listing every file the central repo owns. Shipped into .DesignDocs/MANAGED_FILES on every sync. Both the publish workflow and the downstream protection check use this file.

Protecting Managed Files in Downstream Repos

A valid concern: what happens if a contributor in the gateway repo opens a PR that accidentally (or intentionally) edits a centrally-managed file like AGENTS.md? The next sync would overwrite their change, silently discarding work.

The best-practice solution is a PR guard workflow that reads the MANAGED_FILES manifest and fails the PR immediately if any of those files are touched. The contributor is redirected to the design-docs repo to make the change there.

protect-design-docs.yml (deploy to every downstream repo)

# .github/workflows/protect-design-docs.yml
# Fails any PR that modifies a file managed by the central design-docs repository.
# Distribute this workflow via the design-docs sync (add it to MANAGED_FILES).

name: Protect Managed DesignDocs Files

on:
  pull_request:
    paths:
      - '.DesignDocs/**'

jobs:
  check-managed-files:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Fail if managed files are modified
        run: |
          MANIFEST=".DesignDocs/MANAGED_FILES"
          if [ ! -f "$MANIFEST" ]; then
            echo "No MANAGED_FILES manifest found — skipping check."
            exit 0
          fi

          # Files changed in this PR that are inside .DesignDocs/
          CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \
            | grep '^\.DesignDocs/')

          VIOLATIONS=""
          while IFS= read -r managed_file || [ -n "$managed_file" ]; do
            [[ -z "$managed_file" || "$managed_file" == \#* ]] && continue
            if echo "$CHANGED" | grep -qF ".DesignDocs/${managed_file}"; then
              VIOLATIONS="$VIOLATIONS\n  - .DesignDocs/${managed_file}"
            fi
          done < "$MANIFEST"

          if [ -n "$VIOLATIONS" ]; then
            echo "❌ This PR modifies files that are owned by the design-docs repository:"
            printf "$VIOLATIONS\n"
            echo ""
            echo "To update these files, open a PR in https://github.com/hummingbot/design-docs."
            echo "Changes will be automatically synced to this repo on the next publish cycle."
            exit 1
          fi

          echo "✅ No managed files were modified."

Tip: Add protect-design-docs.yml itself to MANAGED_FILES so every downstream repo gets the guard workflow automatically on the first sync.

CODEOWNERS (belt-and-suspenders)

Add the following to each downstream repo's CODEOWNERS file to require review from a documentation team even if the guard workflow is somehow bypassed:

# Files managed by the central design-docs repo — reviews must come from the docs team
.DesignDocs/README.md             @hummingbot/docs
.DesignDocs/AGENTS.md             @hummingbot/docs
.DesignDocs/CODE_OF_CONDUCT.md    @hummingbot/docs
.DesignDocs/CONTRIBUTING.md       @hummingbot/docs
.DesignDocs/TERMS_OF_USE.md       @hummingbot/docs
.DesignDocs/MANAGED_FILES         @hummingbot/docs

Combining the CI guard + CODEOWNERS gives two independent layers of protection: the PR fails fast with a clear message, and a human reviewer is required even if the check is bypassed (e.g., by an admin).


GitFlow Publication Style

The workflow above targets develop (not main) in downstream repos — this is intentional and aligned with GitFlow.

Why GitFlow for Document Sync?

GitFlow defines a strict branching model:

main        ← production-ready, tagged releases
develop     ← integration branch, next release candidate
feature/*   ← new features, branched from develop
release/*   ← release preparation, branched from develop → merged to main + develop
hotfix/*    ← urgent fixes, branched from main → merged to main + develop
chore/*     ← maintenance (our sync PRs land here)

By targeting develop, the sync follows the normal review cycle before any change reaches main. This means:

  • A human can review the incoming docs update.
  • It gets picked up in the next release/* branch automatically.
  • main is never written to directly by an automated process — a core GitFlow principle.

Enforcing GitFlow Naming Conventions at the Organization Level

GitHub does not enforce branch naming natively, but the following mechanisms work well together:

1. Branch Protection Rules (per repo)

In Settings → Branches, restrict direct pushes to main and develop and require PRs:

// Example via GitHub API or Terraform
{
  "required_pull_request_reviews": { "required_approving_review_count": 1 },
  "restrict_pushes": true,
  "allowed_push_teams": ["release-managers"]
}

2. Required Branch Name Checks via GitHub Actions

Add this check to every repo via a reusable workflow (stored in, e.g., hummingbot/.github):

# .github/workflows/enforce-branch-naming.yml
name: Enforce Branch Naming

on:
  pull_request:
    branches: [main, develop]

jobs:
  check-branch-name:
    runs-on: ubuntu-latest
    steps:
      - name: Validate branch name
        run: |
          BRANCH="${{ github.head_ref }}"
          PATTERN="^(feature|bugfix|release|hotfix|chore|docs|refactor|test)\/[a-z0-9._-]+$"
          if [[ ! "$BRANCH" =~ $PATTERN ]]; then
            echo "❌ Branch name '$BRANCH' does not follow GitFlow conventions."
            echo "   Allowed prefixes: feature/, bugfix/, release/, hotfix/, chore/, docs/, refactor/, test/"
            exit 1
          fi
          echo "✅ Branch name '$BRANCH' is valid."

3. Repository Rulesets (GitHub Enterprise / Free Org)

GitHub's newer Rulesets (available to all orgs) allow you to define rules at the organization level that apply to all repos automatically — no per-repo configuration needed:

  • Organization Settings → Rules → Rulesets → New ruleset
  • Target: all repositories (or filtered by topic/name pattern)
  • Rules: "Require pull request", "Restrict creations" to pattern ^(feature|bugfix|release|hotfix|chore|docs)\/.*

This is the most powerful enforcement method because it applies before the branch is even created, and cannot be bypassed without explicit admin override.

4. Optional: commitlint + Husky

For commit message enforcement (Conventional Commits style) add to each repo:

pnpm add -D @commitlint/cli @commitlint/config-conventional husky
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

Distribute this config via .DesignDocs/ so every repo stays in sync.


Additional Notes and Benefits

Discoverability for AI Agents

Files like AGENTS.md and CLAUDE.md are increasingly used to give AI coding agents (GitHub Copilot, Cursor, Claude Code, etc.) context about a project. If these files diverge across repos, agents produce inconsistent results. Centralizing them in .DesignDocs/ and syncing automatically means every agent working in any Hummingbot repo gets the same baseline guidance.

Reducing Contributor Friction

The number-one complaint from first-time open source contributors is unclear or inconsistent onboarding. A single canonical CONTRIBUTING.md — always up to date in every repo — directly reduces this friction. Pair it with a CHANGELOG_TEMPLATE.md to standardize release notes format across the ecosystem.

Compliance and Legal Consistency

CODE_OF_CONDUCT.md and TERMS_OF_USE.md are legal documents. Having multiple slightly-different versions across repos is a compliance liability. Centralizing them ensures that any legal updates (e.g., updated contact email, new license clause) propagate everywhere within one PR cycle.

Making the Pattern Reusable Beyond Hummingbot

This paradigm is not unique to Hummingbot. Any GitHub organization with multiple related repos benefits from it. The workflow above is generic — only the topic name (hummingbot-design-docs) and the target branch (develop) need to change for another organization to adopt it.

The pattern could be published as a GitHub Actions reusable workflow or even a GitHub App to make adoption even easier across the open source community.

Versioning and Rollback

Because the sync happens via Pull Requests (not direct pushes), there is a complete audit trail. If a document update causes problems in a downstream repo, rolling back is as simple as reverting the merge commit — the same as any other code change.

Suggested Next Steps

  1. Create the hummingbot/design-docs repository and seed it with the current best-version of each shared document.
  2. Tag the initial set of downstream repos (gateway, hummingbot-api, dashboard) with the hummingbot-design-docs topic.
  3. Add the ORG_PUBLISH_PAT as an org-level Actions secret.
  4. Deploy the enforce-branch-naming.yml workflow as an org-level reusable workflow so new repos inherit it automatically.
  5. Add a CODEOWNERS entry in the design-docs repo requiring review from a documentation maintainer team before any merge to main.
  6. Open a GitHub Discussion in the main hummingbot org to gather community feedback on the naming convention (DesignDocs vs SharedDocs vs .hummingbot) before committing to it.

This document is itself a candidate for the .DesignDocs repository — it should be kept in sync across all tagged Hummingbot repos.

Impact

Not hard to set-up, as long as you have global permissions.
Large benefit in keeping key documentation in sync across all repos.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions