diff --git a/0-AI-MANIFEST.a2ml b/0-AI-MANIFEST.a2ml index 6b5134bd..4aa2156b 100644 --- a/0-AI-MANIFEST.a2ml +++ b/0-AI-MANIFEST.a2ml @@ -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) | diff --git a/README.adoc b/README.adoc index 7c302f84..ba18f1e8 100644 --- a/README.adoc +++ b/README.adoc @@ -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/] + <> diff --git a/ULTRAPLAN-2026-09-24.adoc b/ULTRAPLAN-2026-09-24.adoc index 5868b29c..4681547d 100644 --- a/ULTRAPLAN-2026-09-24.adoc +++ b/ULTRAPLAN-2026-09-24.adoc @@ -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. diff --git a/docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc b/docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc new file mode 100644 index 00000000..3e93109d --- /dev/null +++ b/docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc @@ -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. diff --git a/docs/repo-scope.example.toml b/docs/repo-scope.example.toml new file mode 100644 index 00000000..cd800fde --- /dev/null +++ b/docs/repo-scope.example.toml @@ -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