Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ content-addressed `source_hash`. Prose explanation: `REGISTRY.adoc`.
| Language policy (Stream 2) | `.claude/CLAUDE.md` |
| Protocols | `*-protocol/` (registry stream `protocol`) |
| Readiness grades | `adoption-readiness-grades/`, `foundations-readiness-grades/`, `component-readiness-grades/`, `toolchain-readiness-grades/` |
| Multi-repository task scope | `docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc`; illustrative declaration: `docs/repo-scope.example.toml` |
| Enforcement / CI | `.github/workflows/`, `hooks/` |
| Drift / staleness automation | `REGISTRY.adoc`, `hypatia-rules/` (HYP-S006); reusable-pin freshness: `docs/decisions/ADR-003-workflow-pin-staleness-window.adoc`, `scripts/check-workflow-staleness.sh`, `scripts/propagate-workflow-pins.sh` |
| Derived architecture map | `TOPOLOGY.adoc` (generated — do not edit) |
Expand Down
3 changes: 3 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ Every other "what is this repo" doc is now a thin pointer back to these two
| The **readiness grades** — ARG / FRG / CRG / TRG
| link:adoption-readiness-grades/[ARG], link:foundations-readiness-grades/[FRG], link:component-readiness-grades/[CRG], link:toolchain-readiness-grades/[TRG]

| Scope a bot's work across multiple repositories or estates
| link:docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc[Multi-Repository Scope Standard] + link:docs/repo-scope.example.toml[declaration example]

| **Enforcement / CI** — what blocks bad changes
| link:.github/workflows/[.github/workflows/] + link:hooks/[hooks/] + <<Enforcement>>

Expand Down
129 changes: 129 additions & 0 deletions ULTRAPLAN-2026-09-24.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1534,3 +1534,132 @@ view:
* *The owner's desk* = the DECIDE rows, all batched under #787.
* *The wave that made this plan* = clusters C2–C5 and C7–C14 rows dated
2026-09-21…23.

== 9. Addendum — current triage and two-estate scope (2026-09-28)

This addendum supersedes the *ordering* in section 8 where live state has
changed; it does not rewrite the 2026-09-24 historical census. The open-issue
snapshot was re-read from GitHub on 2026-09-28 with `gh issue list --state open
--limit 1000`. It returned *193 open issues*, including *98 created on or after
2026-09-22* and *72 without labels*. These are triage signals, not proof that
any particular issue is invalid. Recheck state, evidence, and CI at the start
of each execution phase.

=== Scope ruling: both estates are in scope for the standard

The Multi-Repository Scope Standard (`docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc`)
and its illustrative TOML declaration (`docs/repo-scope.example.toml`) now
explicitly name both `hyperpolymath` and `metadatastician`. This is the scope
of the *standard and future explicitly authorized estate work*, not blanket
authority to modify every repository. The live estate board (`docs/ESTATE-BOARD.adoc`)
is a dated measurement and must not be treated as a current complete membership
source without refresh. Resolve canonical `github.com/owner/repo` identities,
record a source/revision and observation time, and surface archived, vendor,
renamed, inaccessible, and unknown entries separately. `The-Metadatastician`
may be an organization login alias; use the canonical `metadatastician` owner
identity used in current estate records, and verify redirects before acting.

=== First-pass disposition: fix, decide, validate, or batch

No issue should be closed merely because it is old, oddly worded, unlabelled,
or estate-wide. Use this four-way triage; every disposition needs current
evidence and a comment that preserves it.

[cols="1,3,5",options="header"]
|===
|Disposition |Examples in the live open snapshot |Next action

|*P0 — reproduce / contain*
|#1050, Hypatia scan emits no SARIF; #1037, open Dependabot PRs reportedly reintroduce the CodeQL startup-killer
|Reproduce against current reusable SHA and a clean runner; check whether the 48 PR population still exists before acting. Preserve last-known-good pins and do not merge risky PRs while verified. Split scanner defect from consumer pin mitigation only if the fixes differ.

|*P1 — contradiction or merge-blocking gate*
|#1032 (ruling vs committed rulesets); #1040 (non-PR-reachable workflow can become a required check); #1031 (default and advanced CodeQL coexist in three metadatastician repos); #1028 (tag creation may be blocked); #1005 (tag spelling vs resolved SHA)
|Read the cited ruling and inspect live platform state. State the conflicting authorities explicitly, identify which has precedence, and get an owner ruling where needed. Do not silently amend one side. Test both organizations, with a positive and negative control, before propagation.

|*P1 — fix control before broad rollout*
|#1036 (scorecard verifier misses job-level refs); #1035 (27 callers omit `actions:read`); #1013 (metadatastician finding is one inherited ruleset, not 67 separate repo defects); #1010 (13-repo dead validation gate)
|Confirm the measured populations remain true. Fix reusable source/checker once where possible, then run a read-only, canonical-identity census across both estates. Use one campaign umbrella and an explicit resolved target list for any write.

|*P2 — owner decision batch*
|#787 remains open; #1023 KYAML scope decision; #903 actions-lock cliff; #975 baseline acknowledgements
|Answer the batched decision register once, recording options, affected scopes, consequences, and chosen disposition. Check dates and owners first; move stale entries out of the urgent lane rather than treating an expired date as a live blocker.

|*P3 — safe batch / low urgency*
|#1049 (35 repos below the seven-topic minimum)
|One issue is the right shape. Re-census both orgs; curate topics from each repository's own README; batch only where descriptions are unambiguous. Do not auto-apply invented topics. Close only when the measured remainder is zero or explicitly excepted.

|*Verify before dismissing*
|Any apparently superseded, duplicate, already-fixed, or out-of-scope issue; particularly older estate audit findings and unlabeled issues
|Search for a canonical surviving issue or landed fix, verify at current default-branch HEAD / live settings, transfer estate-only work to its correct register or campaign, copy unique evidence, then close with a reason and cross-reference. If evidence is stale or access is missing, park as unknown/blocked rather than dismiss.
|===

The issue numbers above are triage examples, not a claim that all remaining 193
have been individually re-audited in this addendum. The per-issue pass must
record at least: current state; repo-local vs estate scope; contradiction vs
ordinary debt vs capacity limit; evidence freshness; duplicate/superseding
reference; owner decision needed; and next action. Issues without a scope label
are untriaged, not automatically wrong.

=== How to get through the spike without another spike

The earlier burst was an audit filing-model failure: many findings were opened
one-by-one without adequate deduplication, scope routing, or a campaign umbrella
(see sections 2–3 and `docs/ISSUE-INTAKE-SPEC.adoc`). The remedy is not a
mass-close and not another full-estate issue dump. Work in this order:

. *Freeze intake shape.* Apply the existing issue-intake rules: search before
filing, one umbrella for a wave over five findings, separate repo-local
source fixes from estate propagation, and keep per-repository evidence in an
attached ledger rather than one issue per repo.
. *Build a current, read-only inventory.* Page through open issues and PRs;
canonicalize redirects; capture labels, dates, evidence, linked commits and
campaigns. Split at least into `scope:repo`, `scope:estate`, owner decision,
duplicate/superseded, and unknown. Include both organizations explicitly.
. *Reconcile contradictions first.* For each conflict, pair the committed
standard/ruling with current implementation and authority precedence. An
unresolved owner choice stays a decision; a proven implementation defect
becomes a bounded fix. Never infer the winner from which document is newer
alone.
. *Contain active failures.* Reproduce P0/P1 risks before broad cleanup. Make
the smallest repo-local correction and test it. For propagation, produce a
dry-run manifest containing exact canonical targets, exclusions, and
expected diff; obtain approval if the task has not already granted that
exact write.
. *Close cheap stale rows with proof.* For each candidate, test the acceptance
criteria, locate the actual landing commit or superseding issue, copy unique
evidence, and add a factual closing comment. Do not batch-close by number
range or age.
. *Move estate work to an estate campaign/register.* Keep one umbrella per
coherent campaign, with a single evidence ledger and per-repo result rows.
Preserve this repo as canonical source where appropriate; do not make it the
inbox for fixes whose source lives elsewhere.
. *Publish a short reconciliation report.* Give totals by disposition and
scope, the unverified/blocked remainder, any new owner decisions, and links
to campaign umbrellas. Re-census after the pass; the ending counts must be
reproducible.

The first execution should be a *triage-only campaign* over the 193 current
open issues, not an estate write campaign. The standards repo issue register is
not evidence that every related estate issue belongs to this repository. The
separate estate workstream explicitly covers `hyperpolymath` *and*
`metadatastician`; a task touching either must declare which estate(s), resolve
its exact target list, and honor read-only default authority.

== 10. Proposed execution gates

Do not call the backlog "sorted" until each open issue has a disposition and
there is no unlabelled or unknown row silently omitted. Do not call an estate
campaign complete until its target list is reconciled against a dated,
canonical membership source for *both* estates and every target has an
individual outcome. Suggested completion evidence:

* every remaining issue has a scope label, owner, next action, or documented
exception;
* every duplicate/superseded close cites its survivor or landed fix and retains
unique evidence;
* contradictions have an explicit authority resolution;
* urgent findings have a current reproduction or reason they no longer apply;
* both estates are represented in scope manifests, and any unmeasured repo is
named rather than counted as clean;
* a subsequent issue census reproduces the reported counts.
109 changes: 109 additions & 0 deletions docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// SPDX-License-Identifier: CC-BY-SA-4.0
= Multi-Repository Scope Standard
:revdate: 2026-09-28
:toc: left
:toclevels: 2

Status: *Draft for review*.

== Purpose

This standard defines how a human or automated agent declares the repositories
covered by a task spanning multiple Git repositories. It separates three things
that are often conflated:

* a *standard* states how work is to be done;
* an *estate declaration* identifies a maintained collection of repositories;
* a *task scope* authorizes a bounded operation on a subset of that collection.

A repository being listed in an estate, visible to a bot, or governed by a
standard does *not* by itself authorize changes to it.

== Normative language

The terms MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY express requirements in
their ordinary standards sense.

== Scope declaration requirements

Every multi-repository task MUST identify:

. the requested operation and its purpose;
. the estate declaration(s) used to resolve repository membership, with a
revision, digest, or other reproducible version where available;
. the exact target set, or a deterministic selector and its resolved target
list before writes;
. allowed actions, such as read, report, propose, or write;
. explicit exclusions and any repositories whose status cannot be established;
. the human authority for approval and the route for reporting results.

A task targeting repositories across multiple organizations MUST name each
organization or estate separately. In the Hyperpolymath context, the two
relevant estates are `hyperpolymath` and `metadatastician`; a request to cover
"both estates" MUST name both. Neither estate is implied by the other. The
word "all" is not a sufficient scope expression unless it is expanded to a
concrete, reviewable set before any write.

== Membership and identity

Repository identity MUST use the canonical hosting service and owner/name (for
GitHub, `github.com/OWNER/REPOSITORY`). Local checkout paths, directory names,
old names, and Git remote strings are hints, not canonical identity. Renames
MUST be resolved before deduplication or reporting.

Estate membership MUST have a source and an observation time or revision. A
census, dashboard, board, or search result can inform membership but MUST NOT
silently be treated as a complete authoritative inventory. Membership records
SHOULD distinguish at least: live, archived, deleted/unavailable,
third-party/vendor, renamed/redirected, and unknown/unmeasured. Unknown status
is reported as unknown, never silently converted to included or excluded.

== Permissions and execution

The default agent authority is *read and report*. An agent MUST NOT infer write
permission from a standard, estate membership, prior task, repository access, or
successful authentication.

Before a batch write, the agent MUST present (or otherwise obtain human approval
for) the resolved repository list, proposed changes, exclusions, and rollback
or recovery approach. Approval MUST cover the listed repositories and action;
material scope changes require renewed approval. An explicit task MAY authorize
writes without a separate prompt when it already names the targets and action.

Agents MUST use a dry run or proposal phase where practicable, operate on one
repository at a time or in bounded batches, and record per-repository outcomes.
A failure or permission gap in one repository MUST NOT be represented as success
for the estate. Partial completion MUST be reported as partial.

Agents MUST NOT:

* expand scope by guessing that similarly named repositories belong to the set;
* write to archived, deleted, vendor, or unknown-status repositories unless
explicitly authorized;
* change repository settings, protections, secrets, permissions, or governance
merely because code changes were authorized;
* conceal skipped targets, errors, or uncertainty in aggregate totals.

== Reporting

A multi-repository result SHOULD include the scope source and revision, time of
observation, resolved canonical target list, action attempted, per-target
outcome, skipped targets with reasons, and any remaining uncertainty. Reports
MUST distinguish *not checked*, *checked and clean*, *changed*, *failed*, and
*not applicable*.

== Minimal machine-readable declaration

The companion `docs/repo-scope.example.toml` is an illustrative template, not a
live inventory or grant of authority. Copy it into a task or orchestration
context, replace placeholders, and resolve selectors to an explicit target
list before writes. Keep secrets and credentials out of scope declarations.

== Adoption and limits

This document is a draft proposal for repository-set and task-scope handling.
It does not define GitHub permissions, discover every repository in an
organization, or make an agent's tooling safe by itself. Each adopting project
must identify its authoritative membership source and human approval authority.
A validator can check declaration shape; only the responsible human can decide
whether the target set and proposed action are appropriate.
50 changes: 50 additions & 0 deletions docs/repo-scope.example.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# SPDX-License-Identifier: CC-BY-SA-4.0
# Illustrative only: this is not a live estate inventory or authorization.
# See MULTI-REPOSITORY-SCOPE-STANDARD.adoc.

schema = "hyperpolymath.repo-scope.v1"
status = "example"

[task]
id = "REPLACE-WITH-TASK-ID"
purpose = "REPLACE-WITH-A-SPECIFIC-OUTCOME"
action = "read-and-report" # read-and-report | propose | write
requested_by = "REPLACE-WITH-HUMAN-AUTHORITY"
approval = "not-granted" # not-granted | granted

# Each estate points to a maintained membership source. Do not treat this
# example, a search result, or an estate board as complete without verification.
[[estates]]
name = "hyperpolymath"
source = "REPLACE-WITH-AUTHORITATIVE-MEMBERSHIP-SOURCE"
source_revision = "REPLACE-WITH-COMMIT-OR-CENSUS-ID"
observed_at = "REPLACE-WITH-UTC-TIMESTAMP"
include = ["github.com/hyperpolymath/REPOSITORY"]
exclude = []

[[estates]]
name = "metadatastician"
source = "REPLACE-WITH-AUTHORITATIVE-MEMBERSHIP-SOURCE"
source_revision = "REPLACE-WITH-COMMIT-OR-CENSUS-ID"
observed_at = "REPLACE-WITH-UTC-TIMESTAMP"
include = ["github.com/metadatastician/REPOSITORY"]
exclude = []

# Use canonical host/owner/repository identities. Resolve selectors from BOTH
# declarations before writing, then place the exact union in resolved_scope.
[resolved_scope]
# This exact list, not the include rule alone, is the write boundary.
targets = ["github.com/OWNER/REPOSITORY"]
excluded = ["github.com/OWNER/ARCHIVED-OR-OUT-OF-SCOPE"]
unknown = []

[execution]
dry_run_required = true
batch_size = 1
allow_repository_settings_changes = false
allow_secrets_or_permissions_changes = false

[reporting]
per_repository_result_required = true
report_skipped_targets = true
report_uncertainty = true