# GitHub Repository Conventions

A collection of conventions used for the QuantEcon GitHub organization.

## Naming Repositories

Please use the following naming conventions

1. Always use characters that do **not** require the use of `shift` key (i.e. '-' rather than '_')

## Repository types at a glance

The prefix of a repository name encodes what the repo is *for*. Use this table to pick the right home for new work; the sections below give the details for each type.

| Type | One-line test | Lifecycle | Main author | Visibility |
|------|---------------|-----------|-------------|------------|
| `lecture-{name}` | a published lecture series | ongoing | humans | public |
| `book-{name}` | a textbook project | ongoing | humans | private |
| `project-{name}` | *"we are planning and deciding"* — the narrative home for an initiative or program | **goal-scoped** — lives and dies with its goal (initiatives end; programs run long) | humans | private |
| `status-{domain}` | *"we are measuring"* — a living dashboard of facts about a domain | **ongoing** — outlives any project | automation | public (typically) |
| `workspace-{collection}` | *"we are operating across a repo family"* — a cross-repo tooling bench | ongoing | humans | private |
| `workflow-{name}` | *"the org does this on a schedule"* — automation that acts | ongoing | automation | public/private |
| `action-{name}` | a reusable GitHub Action consumed by other repos' workflows | ongoing | humans | public |

The four org-level types map onto verbs: `project-*` **decides** (plans, records why), `workspace-*` **operates** (humans executing across a repo family, by hand), `workflow-*` **automates** (machines acting on a schedule), and `status-*` **measures** (machines reporting the resulting state).

### Choosing a type: four questions

When a new piece of work needs a repo (or an existing artifact needs a home), ask:

1. **Does it live and die with a goal?** Work organized around a goal — an initiative that ends, or a program that runs long → `project-*`. Work tied to a domain, repo family or routine that persists regardless of any particular goal → `status-*`, `workspace-*`, `workflow-*`, or `action-*`.
2. **Who writes most of the commits?** Humans writing narrative, plans and decisions → `project-*` or `workspace-*`. A scheduled collector or bot → `status-*` or `workflow-*`.
3. **Who is the audience?** The team (candid notes, unannounced plans) → private (`project-*`, `workspace-*`). Anyone, linkable from public pages → public (`status-*`, `action-*`).
4. **If the repo were deleted, what is lost?** Decisions and rationale that exist nowhere else → `project-*`. State that a collector can recompute (minus history) → `status-*`.

### `project-*` vs `status-*`

These two are the easiest to confuse, because every project wants a dashboard. The split rule:

> **`status-*` holds the numbers; `project-*` holds the narrative.**

A `project-*` repo answers *"what are we doing and why?"* — roadmap, decision register, research findings, dated reports. A `status-*` repo answers *"what is true right now?"* — coverage, freshness, configuration, health — collected by automation on a cadence.

Three reasons to keep them separate rather than putting the dashboard inside the project repo:

- **Lifecycle.** A project ends (or goes dormant); the domain it worked on still needs monitoring in maintenance mode. The dashboard is precisely the artifact that must survive the project's archival.
- **Commit traffic.** A nightly collector writes data commits that would drown a project repo's decision history. Machine-written and human-written repos age differently.
- **Visibility.** Project repos are private (candid planning); dashboards are typically public facts computed from public state, published via GitHub Pages and linkable from anywhere.

**Graduation rule.** Dashboards typically start life *inside* a `project-*` repo as hand-maintained tables — that is fine for incubation. Once the numbers are collected automatically on a cadence, they graduate to a `status-*` repo. The project repo keeps a narrative layer (interpretation, phase context, campaign notes) that links to the live dashboard rather than duplicating its numbers.

**Worked example.** The translation program: [project-translation](https://github.com/QuantEcon/project-translation) (private) holds the i18n roadmap, decision register, research and dated program reports; [status-translations](https://github.com/QuantEcon/status-translations) (public) holds the collector, the versioned data (`data/latest.json` + append-only `data/history/`) and the Pages dashboard tracking coverage and freshness per language edition. Whether the i18n project is one day archived or runs on indefinitely as a program, `status-translations` continues independently as the maintenance dashboard.

**Not project management.** `status-*` repos measure the *product* (the state of the world); they do not track the *work*. Work tracking — issues, phases, on-track/at-risk — lives in GitHub Issues/Projects (see [meta#332](https://github.com/QuantEcon/meta/issues/332)). The curated [dashboard](https://github.com/QuantEcon/dashboard) hub links out to `status-*` pages; it does not host their data.

### `project-*` vs `workspace-*`

Both are private, human-authored, and can operate across multiple repos — so this is the easiest pair to blur. The test is what the repo is *organized around*:

> **A `project-*` repo is organized around a goal; a `workspace-*` repo is organized around a fleet.**

Remove the goal and a project repo is pointless, even though its member repos still exist. Remove the repo family and a workspace is pointless, even if every current initiative is still running. A project can change *which repos it touches* without changing identity; a workspace can change *what work flows through it* without changing identity — but never its family.

Lifecycle differences follow from this rather than defining it: goals end (initiatives) or run long (programs), so `project-*` repos are archived when — and only when — their goal is achieved or absorbed; fleets persist, so a workspace never archives while its family lives.

**Overlap is allowed, with a boundary rule.** A project repo *may* carry a minimal command bench (a manifest plus sync) for the repos it is changing — the bench serves the goal, and dies with the project. But the moment the bench becomes the point, or a second initiative wants to use the same bench, it belongs in a `workspace-*`: the workspace is the *shared* operating layer that inherits goals from many projects (and from routine maintenance) rather than owning one.

**When a family is workspace-ready.** A `workspace-*` earns its existence when the member repos are mature: membership is stable, the repos are structurally homogeneous, coordination tasks recur mechanically, and development happens *upstream* of the family (e.g. the lecture repos are mature delivery surfaces consuming changes from `quantecon-book-theme`, `mystmd` and `actions`; `workspace-lectures` coordinates the downstream effects). A family still being actively designed is better served by the owning project repo until it stabilizes.

## Lectures

| Name | Description | Visibility |
|------|---------------------------| --------- |
| lecture-{name} | A repository that contains an official QuantEcon lecture series | public |
| lecture-{name}.notebooks | A companion repository that contains notebooks for an official QuantEcon lecture series | public |

## Books

| Name | Description | Visibility |
|------|---------------------------| --------- |
| book-{name}    | A QuantEcon associated textbook repo | private |
| book-{name}.public    | A QuantEcon textbook companion site | public |
| quantecon-book-{name} | (optional) A QuantEcon companion software package to support an official textbook project | public |

## Projects

| Name | Description | Visibility |
|------|---------------------------| --------- |
| project-{name} | The planning and decision home for a QuantEcon initiative or program (e.g. `project-translation`, `project-monorepo`) | private |

A `project-*` repo is the durable, human-authored record of an initiative or program that spans multiple repositories: no single code repo can hold the program-level picture, so the project repo is that picture. It holds **no production code** — engines, actions and content live in their own repos.

**Anatomy** (reference model: `project-translation`):

| Path | Role |
|------|------|
| `README.md` | purpose, repo map, the program at a glance, related repos |
| `ROADMAP.md` | the phased plan |
| `NEXT-STEPS.md` | immediate actions and the **decision register** (date, decision, why / alternatives) |
| `research/` | dated, verified point-in-time findings (audits, inventories) |
| `reports/` | dated program status reports |
| `status/` or notes dirs | narrative status layer — interpretation and context, linking to the live `status-*` dashboard for numbers |
| `CLAUDE.md` / `AGENTS.md` | session orientation for AI-assisted work |

**Lifecycle.** Projects are goal-scoped: the repo lives and dies with its goal, not with any repo family. Some goals are *initiatives* with phases and an intended end state; others are *programs* that run indefinitely (a translation program coordinates language editions for as long as they exist). Archive the repo when — and only when — the goal is achieved or absorbed into routine maintenance: its decision register remains the historical record, while any dashboard it incubated lives on as a `status-*` repo and any command bench it carried is retired or promoted to a `workspace-*`.

Note: some older repos use the dot form `project.{name}` (e.g. `project.lecture-mojo`); new project repos use the dash form `project-{name}`.

## Status dashboards

| Name | Description | Visibility |
|------|---------------------------| --------- |
| status-{domain} | A long-lived, automatically updated dashboard reporting the current state of a domain (e.g. `status-lectures`, `status-translations`) | public (typically) |

A `status-*` repo is a **living reporter**: data store + collector + static dashboard, named for the *domain it measures* (not for the project that created it), because it keeps running long after any project ends.

**Anatomy** (reference models: `status-lectures`, `status-translations`):

| Path | Role |
|------|------|
| `collector/` | the script that computes the numbers, plus `config.json` for editorial facts the collector cannot compute (titles, phase labels, pipeline notes) |
| `data/latest.json` | the current snapshot — the versioned **data contract** that the site and any external consumer read |
| `data/history/` | dated snapshots, append-only — trend views come free later |
| `site/` | the dashboard: a static, dependency-free page deployed to GitHub Pages |
| `.github/workflows/` | `collect` (cron → commit fresh data) and `publish` (deploy `site/` + `data/` to Pages) |

**Principles**

- **Domain-scoped, not project-scoped.** The repo monitors a thing QuantEcon maintains (lecture builds, translations); it is not a project deliverable and does not close with a project.
- **Usually public.** Most dashboards compute every fact from public GitHub state (no credentials beyond `GITHUB_TOKEN`) and publish via Pages so anyone can link to them. This is a norm rather than a hard rule — a dashboard over sensitive facts (e.g. costs) can be private.
- **Machine-written.** Commit history is dominated by the collector; humans touch only the collector, config and site.
- **Data, not narrative.** Numbers plus minimal labels. Interpretation, decisions and plans belong in the owning `project-*` repo or `meta`.
- **Self-contained and relocatable.** The static site plus the versioned data contract means the dashboard can move (e.g. under a future reporting hub) by moving files and updating one URL.
- **Canonical counting rules live here.** When a status repo and hand-maintained project notes disagree on a metric, the status repo's documented rule is canonical for reporting.

## Workspaces

| Name | Description | Visibility |
|------|---------------------------| --------- |
| workspace-{collection} | A cross-repo development workspace for operating across a collection of related QuantEcon repositories (e.g. `workspace-lectures`) | private |

A `workspace-*` repo is distinct from `project-*`: a `project-*` repo plans and tracks an initiative, whereas a `workspace-*` repo operates across an existing family of repositories (clone-all, run commands across the set, coordinate multi-repo changes).

**Scope and lifecycle.** A workspace is scoped to the *repo family*, not to any initiative — hence `workspace-{collection}`, never `workspace-{project}`. It serves two kinds of work equally: routine maintenance sweeps (dependency bumps, config normalization) and the execution of project rollouts (the project decides a change; the workspace is where the multi-repo branch/edit/PR cycle actually happens). Like a `status-*` repo, it outlives every project that passes through it: it persists as long as the collection does. See *`project-*` vs `workspace-*`* in the decision guide above for the goal-vs-fleet test and the conditions under which a family is workspace-ready.

**Graduation rule.** The workspace is also where cross-repo procedures are rehearsed by hand; once a procedure becomes routine and mechanical, it graduates into `workflow-*` or `action-*` automation — the same incubation relationship `project-*` has to `status-*` dashboards.

**Anatomy.** A workspace holds tooling and configuration only — it never vendors lecture/book content:

| Path | Role |
|------|------|
| `manifest.yml` | the member repos, in [`tsrc`](https://tsrc.readthedocs.io/) schema — the source of truth for "which repos are in the family" |
| `bin/` | the runner (`sync`, `foreach`, `tidy`, `doctor`) |
| `Makefile` | task entrypoints (`make sync` / `status` / `pull` / `tidy` / `foreach`) |
| `.claude/` | workspace-scoped Claude Code rules + workspace-only skills |
| `docs/` | ADRs recording design decisions |
| `repos/` | the clone target — **gitignored; member content is never committed here** |

**How they work.** `make sync` clones every repo named in `manifest.yml` into `repos/`; each cloned repo keeps its own remote, history, and PRs (the workspace never vendors content). `bin/foreach` runs a command across the whole set. A coordinated change is *the same branch in each repo → edit → commit per repo → one PR per repo* — there is no aggregate PR — tracked as a workspace issue that links up to the relevant `meta` issue. `make tidy` returns every repo to a clean, up-to-date default branch.

## Workflows and Actions

| Name | Description | Visibility |
|------|---------------------------| --------- |
| workflow-{name} | A repository that **runs** automation on a schedule for the organization — it acts on the world (e.g. `workflow-backups` pushes backups to S3) | public/private |
| action-{name} | A repository that **packages** a reusable GitHub Action consumed by other repos' workflows (e.g. `action-translation`, `action-style-guide`, `action-link-checker`) | public |
| actions | Shared reusable actions and workflows for lecture builds (monorepo of small building blocks) | public |

The test: if the repo's workflow does the job itself on a cron (backup, report generation), it is a `workflow-*`; if other repositories reference it in *their* workflows (`uses: QuantEcon/action-x@v1`), it is an `action-*`.

## Reserved names

Singleton repos with an org-wide role:

| Name | Description |
|------|---------------------------|
| meta | Cross-repo issues and discussion — proposals start here |
| qeps | QuantEcon Enhancement Proposals — durable records of cross-repo and governance decisions |
| dashboard | Curated presentation hub for stakeholders — links out to `status-*` dashboards; does not host their data |
| manual (QuantEcon.manual) | This manual — operations, style guide, conventions |
| grant-admin | Grant administration |
| grant-fundraising | Proposal development for funding opportunities |
| admin, vault, governance | Private organizational administration and knowledge |
| projects | Private dev-history vault (decisions and rationale across software projects) — not to be confused with the `project-*` prefix |

## Other prefixes in use

Lighter conventions, listed for completeness:

| Name | Description |
|------|---------------------------|
| test-{name} | Disposable test doubles and CI targets for actions/tooling (e.g. `test-translation-sync`); archive when the pilot ends |
| template-{name} | Template repositories (e.g. `template-lecture-repo`) |
| contractor-{name} | Payment artifacts for an individual RA/contractor (private) |
| audit.{yyyy-mm}.{topic} | A dated, point-in-time audit (e.g. `audit.2026-05.style-guide`) — frozen once published, unlike a living `status-*` dashboard |
| benchmark.{topic} | Benchmark datasets and evaluation harnesses (e.g. `benchmark.translate-zh-cn`) |
