ADR 0015 — cross-repo issue orchestration: native cross-repo sub-issues supersede the prose Part of convention
- Status: proposed
- Date: 2026-06-09
- Relates: 0001 (the membership test), 0005 §4 (propagation), 0008 (release-on-merge), 0011 (the dashboard), 0014 (the process this tracks)
- Tracking: atlas#453 / atlas#455 (the unified-process rollout epic)
- Normative spec:
process/SPEC.md§7, and thegovernance/TRACKING.mdmanifest grammar (build work under atlas#454)
Cross-repo work is tracked by prose. A substrate change that requires coordinated edits in N repos is, today, an atlas issue whose body says
constellation: …with same-repo children linked byPart of #Ntext — or nothing at all. GitHub now supports native sub-issues that cross repositories within one organization, with an automatic roll-up; the whole family is one org. The structured graph exists and is unused; the prose mirror is the rot.
Context
Within a repo, the mature members already use native sub-issues (a type:epic/epic
parent with real child links and a sub_issues_summary roll-up). Across repos, there is no
structured link at all: coordination is Part of #N prose, repo#N references, and a human
keeping a checklist current. constellation-the-probe has zero issues because all its
tracking already lives informally in atlas. There is no shared cycle calendar — design and
atlas each run "cycles" and "waves" with divergent label syntax (wave-1 vs wave:1).
Two facts make this tractable now:
- GitHub native sub-issues cross repositories within one organization — same-org only
(the whole family is under
Bitspark), ≤100 children per parent, ≤8 nesting levels, and the actor needs ≥triage on each child's repo. The capability is proven inside atlas (e.g. #65); the cross-repo dimension has never been used. - atlas is already the one checkout that can re-derive the whole-family model offline
(
registry.json+ everyatlas.json→constellation.json) — so it is the one place a cross-repo link graph can be validated, not just asserted.
The membership test (0001) decides where a tracking artifact lives: fleet-wide coordination with no single-repo owner ⇒ atlas.
Decision
1. Fleet epics live in atlas; the membership test decides each issue
| Scenario | Parent lives | Children live |
|---|---|---|
| A change touching ≥2 members (substrate, contract, a fleet sweep) | atlas epic | one native cross-repo child per affected member repo |
| A bug entirely inside one repo's lane | that repo | same-repo native sub-issues |
| A two-repo contract one repo clearly owns | owner repo + a Blocks edge |
n/a |
A dedicated tracker repo (a second coordination convention competing with atlas) and
constellation-the-probe (the umbrella working dir / integration probe, not a registry
member) are both rejected as homes.
2. Native sub-issues are the source of truth
Parent→child, same repo or across repos, is a native sub-issue link — the atlas epic
parents a child filed in the member repo. GitHub's sub_issues_summary {total, completed, percent_completed} is the roll-up; no hand-maintained checklist. The
prose Part of Bitspark/atlas#N line is retained only as a courtesy human-readable
mirror, never as the authority. This supersedes the prose Part of #N convention for
cross-cutting work.
3. The relationship vocabulary
Structured (authoritative, machine-reconciled): native sub-issue links (within- and
cross-repo). Prose edges, only for what GitHub has no native link for, always
fully-qualified Bitspark/<repo>#N:
| Edge | Syntax | Meaning |
|---|---|---|
| containment mirror | Part of Bitspark/atlas#N |
courtesy mirror; the native link is authoritative |
| close-on-merge | Closes #N (same-repo only) |
cross-repo Closes is unsupported — use Resolves Bitspark/<repo>#N |
| blocking | Blocks Bitspark/<repo>#N |
this must land first |
| blocked-by | Blocked by Bitspark/<repo>#N |
inverse |
| dependency | Depends on Bitspark/<repo>#N |
softer than Blocks |
| relation | Related to Bitspark/<repo>#N |
symmetric context |
A bare <repo>#N in a cross-repo edge is a lint error. Bidirectionality is not a
hand-maintained mandate: the native link already gives parent/child both directions;
Blocks/Depends on are declared once (in the track manifest) and the reverse is rendered
in the dashboard, never required as reciprocal prose on the other issue.
4. The constellation-epic / track-manifest pattern
A fleet epic carries type:epic + rollout and one fenced YAML manifest block — the
single source atlas track check reconciles against the live native graph:
<!-- atlas:track -->
epic: Bitspark/atlas#NNN
cycle: 2026.07
children:
- { repo: ontos, issue: 12, prefix: "ontos:", blocks: [] }
- { repo: logos, issue: 88, prefix: "logos:", blocks: [ontos#12] }
<!-- /atlas:track -->
atlas track check asserts: every declared child is a real native sub-issue; no undeclared
children (excepting autonomous-actor issues, §7); each child repo is a ratified member of
constellation.json (§6); titles carry the declared prefix; cross-repo refs are
fully-qualified. It folds into atlas doctor as the non-blocking track-fresh leg; the hard
form atlas track check --strict runs only in atlas's own CI — maintenance, never a
member's required gate. The manifest grammar lives in governance/TRACKING.md; the
epic.yml template references it rather than embedding it, so the tracking schema and the
template-vendoring axis stay decoupled.
5. Honest token + lifecycle scoping
atlas track sync --writeis an author-run-local capability, not a CI capability. Reaching into member repos to create issues and add sub-issue links needsissues:write(≥triage) on each child repo — strictly larger than the receivers'repository_dispatchscope. It runs under a maintainer's own credential, never a workflow secret. The fleet cron may file tracking issues via its own held credential, but routine epic decomposition is a steward action.- GitHub does not auto-close a parent when its sub-issues close. The automatic invariant
is the roll-up percentage; epic closure is a deliberate step (
atlas track sync --close-completeonce the summary hits 100%, or a maintainer).
6. Membership for children: any ratified member, not only substance
A cross-repo child may be filed in any ratified (non-draft) member of
constellation.json, of any layer — substance, downstream, or infrastructure. This
corrects a conflation: the substrate fan-out subscriber set is substance-and-downstream
members with a substrate caller, but the issue-tracking child set is simply "is a member."
A downstream member (the schema-sanctioned layer that consumes the family — e.g. a realizer
like arche-runner once ratified) is a first-class tracking target. A repo absent from
registry.json (constellation-the-probe; an un-ratified arche-runner) cannot be a child
until a steward adds it — which is why onboarding such a repo is gated on a membership PR.
7. Autonomous actors are scoped out of the "no undeclared children" rule
Repos with autonomous routines that file their own issues (arche's cloud routines) mark them
with a filed-by: provenance (or a bot login); atlas track check excludes those from
manifest reconciliation. They remain subject to the label and process gates like any issue.
8. Unified cycles and the issue body template
atlas owns one cycle calendar (governance/cycles.json); members map their own milestone
objects to a cycle by id (no forced shared milestone), and children carry the canonical
wave:N label. The unified issue body — ## Problem / ## Scope / ## Acceptance /
## Grade (canonical labels, not prose) / ## Provenance (filed-by:, parent:,
relationships:) — is specified in process/SPEC.md §7 and seeded by
the vendored task.yml/epic.yml forms.
Consequences
- Cross-repo status is a query, not a stale checklist —
atlas track list --cyclerenders the livesub_issues_summaryroll-up; the dashboard (0011) gains a tracking view. - The prose
Part of #Nconvention retires for cross-cutting work, becoming a courtesy mirror of an authoritative link. - A genuine constraint surfaces honestly: cross-repo issue creation needs a broad credential, so it is a steward-local action — the tooling does not pretend CI auto-creates cross-repo issues.
- The membership boundary becomes load-bearing for tracking — you cannot file a child in a repo the family hasn't ratified, which is the right gate.
Alternatives considered
- Keep prose
Part of #N+ a tracking doc. Rejected: a hand-maintained mirror of a graph GitHub now maintains natively — the rot, with extra steps. - A GitHub Project (v2) board. Rejected as the source of truth: Projects are a view, not a checked artifact in a repo's CI; nothing offline reconciles a board against the topology, and the family deliberately uses no Projects today. (A Project may later render the same native links read-only.)
- A dedicated
trackerrepo. Rejected: a second coordination home competing with atlas's topology authority; atlas is already the only checkout that can validate the link graph. - Cross-repo via the substrate fan-out only (no issue links). Rejected: the fan-out converges pins; it does not express "this human work item in repo A blocks that one in repo B," which is what coordinated multi-repo changes need.
The work that realizes this ADR
atlas track check|sync|list, governance/cycles.json, governance/TRACKING.md, and the
epic.yml manifest reference are built under atlas#454; the first real cross-repo
sub-issue tree is the rollout's own atlas#455 epic (children filed in each ratified
member). See process/SPEC.md.