organizations/ASF/ do not trip the placeholder / asf-coupling checks.
September 8, 2026 · View on GitHub
title: Organizations (governance + backend defaults grouped per org) status: experimental kind: feature mode: infra source: > Extends project-agnosticism.md and adapters.md. An organization groups the governance vocabulary and capability→backend defaults shared by every project under one governing body (foundation, company, maintainer collective), so those defaults live once instead of being copied into each project's manifest. Implemented under organizations/ (organizations/ASF/, organizations/independent/, organizations/_template/). acceptance:
- An organization's shared defaults (governance vocabulary + capability
bundle + infra values) live in organizations/
/organization.md, not duplicated across each project's project.md. - A project selects its organization with a single key
(organization:
in project.md) and inherits the rest. - Config resolves project.md -> organizations/
/ -> framework default, first hit wins; skills never branch on the organization. - A new organization can be authored from organizations/_template/ without editing any skill body.
What it does
Introduces a configuration layer between a single project's
<project-config>/ and the framework defaults. An organization captures what a governing organization makes default for all
its projects:
- governance vocabulary — what the governing body is called
(
<governance-body>), how contributors are admitted (contributor_intake: ICLA / DCO / none), the project-lifecycle stages (<project-stage>), role names; and - capability→backend bundle + infrastructure values — which tool adapter fulfils each capability (CVE authority, mail archive, project metadata, forwarder, …) and the concrete URLs / addresses those backends use.
This removes the duplication whereby every ASF project re-declared the
identical "ASF default" values in its own project.md.
Where it lives
organizations/README.md— the entity overview.organizations/ASF/— the reference organization (Apache Software Foundation defaults: PMC governance, Vulnogram, PonyMail,apache-projects-mcp, ASF-security forwarder,*.apache.orginfra).organizations/independent/— the no-formal-org baseline (DCO, GHSA, GitHub Releases, no list/forwarder/metadata backends); inherited byprojects/non-asf-example/.organizations/_template/— authoring skeleton.- Resolution contract:
AGENTS.md§"Configuration resolution order". - Path exempted from placeholder / asf-coupling lint via
ALLOWLIST_PATHS += "organizations/"inskill-and-tool-validator.
Behaviour & contract
- A project names its organization once:
organization: <org>in<project-config>/project.md(defaultindependent). - Every placeholder and dotted config key resolves
project.md → organizations/<org>/organization.md → framework default, first hit wins. This is the only inheritance in the config model. - Skills do not read the
organization:key to branch behaviour; they read capability keys (cve_authority.tool,archive_system.kind,<governance-body>, …) and take the first value the chain yields. - An organization declares only org-wide values. Per-project
values (security-list address, scope labels, product name, roster,
tracker label/body-field vocabulary) stay in
project.md. - The
organizations/ASF/organization.mdkeys mirror the namespaces of the project manifest's Security workflow configuration section so resolution is mechanical. - Organization smoke coverage should exercise more than one family. At minimum, a non-ASF profile must be able to drive security intake backend selection, release backend selection, and contributor-governance defaults without editing skill bodies.
Out of scope
- Removing the ASF default values from
projects/_template/project.md(the reflow to actually inherit) — a follow-up change. - Making the
asf:falseskill families fully agnostic (moving residual PMC/ICLA/incubator vocabulary behind placeholders) — a follow-up. - Replacing the per-family
asf: true/falsemetadata with an optional family-levelorganization:scope — a follow-up. - Any runtime fetch/install of externally-defined adapters (discovery only; see PRINCIPLES §13).
Acceptance criteria
- An organization's shared defaults live in
organizations/<org>/organization.md, not duplicated per project. organization: <org>inproject.mdselects the adapter.- Resolution is
project.md → organization → framework default, first hit wins; no skill branches on the organization. - A new organization can be authored from
organizations/_template/with no skill edits. - Smoke fixtures cover security intake, release backend, and contributor governance defaults for at least one non-ASF profile.
Validation
# Validator passes; organizations/ is allowlisted so ASF terms inside
# organizations/ASF/ do not trip the placeholder / asf-coupling checks.
uv run --project tools/skill-and-tool-validator skill-and-tool-validate
# Doc + link + placeholder hooks green on the new files.
prek run --files organizations/**/*.md docs/vendor-neutrality.md AGENTS.md
Manual resolution check: a project.md with organization: ASF and a
key omitted resolves to the ASF adapter value; organization: independent
resolves to the baseline.
Adapter layout is enforced: validate_organization_structure in
tools/skill-and-tool-validator requires every organizations/<org>/
directory except _template to contain README.md and organization.md.
Omitting either results in a HARD violation, so an incomplete adapter fails
the validator before any skill can resolve against it. It is not a separate
command — the check runs inside the top-level skill-and-tool-validate
sweep above.
Organization references are enforced alongside it: every organization:
value — in a skill's SKILL.md frontmatter, a tool README's
**Organization:** line, a skill-source descriptor, and a
skills/<name>/source.md pointer — must name a directory under
organizations/ (known_organizations(), which excludes _template).
A typo or a dangling adapter name is therefore a HARD violation rather than
a silent fall-through to the framework default.
Known gaps
- The structural check verifies file presence, not manifest content.
validate_organization_structurerequiresREADME.mdandorganization.mdto exist; nothing validates whatorganization.mdactually declares. A present-but-empty manifest passes, and the keys it omits then resolve silently to framework defaults instead of failing loudly. Every other organization check inskill-and-tool-validatoris referential ("is this org name known?"), not schema-level. skill-sources.mdis outside the required set. All three in-tree adapters carry one,organizations/_template/skill-sources.mdtells authors to keep the file with an empty list when the organization curates nothing, and the validator globsorganizations/*/skill-sources.mdwhen collecting source descriptors — but the filename is absent from_ORG_REQUIRED_FILES, so an adapter that drops it is still structurally valid.- The
_templateauthoring path is not covered by an eval.ASFandindependentare the only adapters in the tree, and no eval exercises authoring a fresh organization fromorganizations/_template/, so the "new organization with no skill edits" criterion rests on the two in-tree examples rather than on a test.