Upstream contributions within the shared package pipeline
Status: proposed implementation, reviewed 2026-09-13 against Praetor commit 76832ee75c8964f2ffeac338a6a3aa9473c23eda. The development MCP probe passed 35 checks with source digest 6aedd54101efe1fbc1e5951dcde413c00a63aac3953cef301ce7286356966d4f. The checkout also contained unrelated work; inspected source hashes and bounded local reproductions were retained privately. This audit did not contact an upstream forge, execute a model, publish anything, or establish end-to-end contribution readiness.
Extend the package development pipeline, whose reuse decisions already include upstream contribution. Use its common policy, evidence relations, stage planner, executor admission and adapter capabilities. A contribution is a path through that pipeline, not another issue database, framework, bot, or per-IDE implementation.
Existing implementation and concrete gaps
| Surface | Implemented behavior and source | Missing contribution contract |
|---|---|---|
| Forge transport | internal/forge/forge.go:31-58 supplies common issue/PR creation; github.go:455,547,581,666 performs GitHub HTTP creation, bounded issue listing, and issue labels/state updates. Explicit repository and endpoint injection exist. |
PR requests have no draft field. There is no PR search/read/update/merge-status or fixed-release capability. Authentication checks a nonempty token, not remotely verified permissions. A local draft must not call ordinary PR creation. |
| Other forges | internal/forge/gitea.go:78-103, gitlab.go:76-101, and forge.go:61-74 return explicit unsupported errors for enforcement; Forgejo shares the Gitea driver. |
Keep unsupported stages blocked. Configured credentials or recognized provider names must not imply working issue/PR support or silently select GitHub. |
| Existing issue dedupe | internal/forge/issues.go:119-165 indexes trimmed titles, then creates or updates. |
The index ignores returned entries after 1,000; newly created items are not added to the index; duplicate remote titles are ambiguous; title identity is insufficient for a finding. github.go:593-612 stops after 20 pages without marking a full last page incomplete. Listing also removes PRs. These paths cannot establish a complete duplicate search. |
| Review validation | internal/forge/pr.go:37-44,71-80,150-185 verifies receipt contents, optionally binding a pinned key and head SHA; :198-220 derives reviewer candidates from CODEOWNERS. |
Unpinned receipt consistency is weaker than an authenticated gate. These checks neither review a remote PR nor authorize publication. Upstream contribution rules/templates apply; Praetor-specific checkboxes, bots and receipts must not be imposed on an unrelated upstream. |
| Project/discussion projections | internal/forge/project.go:53-55,90-107 distinguishes local cache items and remote observations. discussions.go:100 transcribes a supplied accepted discussion into a local ADR, once per discussion. |
Useful projections, not upstream acceptance evidence or a generic contribution lifecycle. An issue being closed, a cached status, or supplied discussion status does not prove a fix merged. |
| Public dogfood | internal/dogfood/public_git.go admits explicit canonical pinned GitHub repositories with bounded, isolated Git operations. public_verify.go:59-91 verifies effective policy, lock/context, baseline, scan and ratchet. |
This is Praetor governance verification. It does not execute upstream application tests or prove an upstream product bug. Public-repository enrollment does not authorize arbitrary scripts, builds, fork creation or publication. |
| Local repair | internal/repairrun/config.go:18-33, run_execute.go:58-79,99-167, and workspace_patch.go:51-113 retain source-bound reproduction, candidate changes and scoped verification. |
Reuse isolation, attempt accounting, bounded commands, source hashes and evidence. Current repair supports explicitly allowed Go source and existing tests; workspace_ast.go:21-38 rejects changed declarations/imports/signatures/calls. It is not a general upstream patch or regression-test generator. No upstream promotion is implemented. |
| Dependency updates | internal/bump/types.go:17-24 identifies package/current/target/channel/module; Go and Node scanners and update commands are real. catalog.go contains static version information. |
No contribution ID, affected source range, accepted upstream commit, released-fix provenance or downstream patch-retirement relation. Catalog values are not live evidence that a fix was released. |
| Canary and patch outputs | internal/bump/canary.go:50-54 marks a dry-run successful and certified; :121-128 writes diagnostic text with a .patch suffix; :133-154 applies a requested update and optional existing patch. |
Certification without execution is false evidence. The generated file is not an applicable fix. Apply does not consume verified canary/source/patch identity, and a missing named patch can be skipped. Do not reuse these outputs as contribution or retirement admission until corrected. |
| Changelog/release | internal/changelog/render.go:18-107 and journal.go bind recoverable rendering/cleanup to exact hashes. internal/release/release.go:25-55 checks SemVer, cleanliness and gates, then renders. |
Reuse atomic snapshot and recovery primitives, not a second ad-hoc journal format. Preparing a changelog is not publishing a release, observing upstream acceptance, or verifying an installed downstream fix. Skip options cannot supply required evidence. |
| Attribution/provenance | internal/supplychain/sbom.go:39 builds Go dependency inventory; slsa.go:54-95 constructs a statement from supplied values. Contribution requirements exist in docs/guides/contributing.md. |
Inventory and unsigned statement construction do not establish license compatibility, rights to contribute, a signed build, or upstream consent. Record exact upstream LICENSE/NOTICE/CONTRIBUTING/CLA/DCO requirements and copied-code origin. Conflicting or missing licensing evidence remains unresolved. |
| Policy and entry points | internal/config/effective_load.go resolves explicit fleet/org/deployment/workstation/repository sources with provenance. Existing CLI bump/reconcile and MCP repair-status adapters call shared modules. |
Current effective-policy implementation primarily resolves complexity, not the proposed contribution settings. No shared upstream contribution tool exists. Extend one typed policy slice with real consumers; do not expose inert settings or separate CLI/MCP business logic. |
Four hermetic observation probes reproduced current failures: 20 full issue pages returned 2,000 issues and nil error; two identical new titles in one batch created two issues; existing issue 1,001 was ignored and created again; an empty-candidate dry-run on a non-repository reported Success=true and CanaryCertified=true. These probes deliberately observe defects; their passing results are not acceptance tests. No external HTTP requests or model calls were made.
One contribution record in the shared evidence graph
Relate the existing Finding/ReuseDecision -> PackageTask -> Change -> Verification objects to one contribution record. Retain separate evidence for upstream identity, publication and downstream maintenance:
finding -> upstream reproduction -> candidate patch -> local reviewed draft -> authorized publication -> upstream acceptance -> released fix -> downstream verification without patch -> patch retirement
The record needs stable IDs and references, not duplicated artifact bodies:
- Finding ID, originating consumer/replay IDs, classification, affected package coordinate/version and exact source commit. Distinguish Praetor integration defects, upstream application defects, environment/toolchain failures and unsupported coverage.
- Canonical upstream forge/host/repository identity; exact reproduction base; optional fork identity and proposed head/base. A Git remote name, module-name heuristic or ambient
GITHUB_REPOSITORYmust not choose the publication target. - Search observations with query scope, timestamps, pagination/completeness, matching issue/PR IDs, head/merge commits and uncertainty. Candidate matches are reviewed before linking; similar titles alone do not merge findings.
- Reproducer, toolchain/command identity, expected failing assertion, before/after source and artifact hashes, actual result counts, omitted gates and coverage. Observed failure is distinct from a source-verified regression.
- Patch artifact, allowed paths, original license/attribution references, local draft body, review decision, and evidence bundle digest. Exported text is a separately reviewed sanitized projection.
- Publication authorization bound to the exact target, operation, patch/head and rendered body digest; durable attempt/idempotency identity; remote issue/PR IDs and readback. Token presence, ownership, a policy setting or an agent's choice cannot substitute for explicit external-publication authorization.
- Upstream merge/release observations and each downstream consumer's patch/bump state. Model upstream resolution (
open,duplicate,declined,accepted,released,reverted,unknown) separately from local preparation/execution state. A failed or declined contribution remains useful evidence.
Deduplicate one compatible upstream cause across consumers while retaining each affected version and reproducer. Different causes, incompatible versions or licensing/runtime constraints must remain separate. A changed source pin, patch, target, or required toolchain invalidates dependent verification and publication admission. A content digest proves integrity relative to captured bytes; source authenticity requires its own verified binding.
Configurable policy, with one resolver and explicit capabilities
Extend the package policy's existing owner/org/forge/repository/stage inputs rather than introducing a new config store. Resolve once, preserve source provenance and pass the same immutable digest to planning, execution, CLI, MCP and future IDE/bot adapters.
| Setting group | Required behavior |
|---|---|
| Identity | Explicit upstream target, optional contributor fork/destination, package coordinate and policy owner. Public examples use example/upstream and example-contributor/upstream; operational settings supply actual bindings. Credentials remain private references. |
| Stage admission | Independently enable read-only discovery, local reproduction, local patch preparation, publication, follow-up and downstream retirement. Governance constraints only tighten; operational destination precedence is documented. Missing explicitly selected config errors; unknown capability blocks its stage. |
| Native execution | Exact source/toolchain pins, admitted commands, filesystem/network scope, time/output/attempt/cost limits, applicable hook adapter and coverage requirements. Keep upstream execution separate from public governance scanning. Use the shared executor and current router admission work; do not add a parallel dispatcher. |
| Contribution requirements | Pinned upstream contributing/license/notice/template references, attribution and DCO/CLA requirements, reviewer policy and report visibility. Check actual declared requirements; do not forge signatures or attest a CLA on another person's behalf. |
| Publication | Allowed operation and target policy, remote draft requirement where selected, sanitized export rules, authorization/readback and retry limits. Publish remains unavailable when a driver cannot satisfy the requested contract. |
| Maintenance | Recheck cadence/budget, expected release channel, downstream consumer bindings and patch retirement conditions. No blanket fleet schedule is activated by adding a contribution record. |
Prefer small additive capability interfaces backed by the existing internal/forge transport for contribution search/status and draft publication, rather than making every driver fake all methods. Declare which operations each adapter implements. The application service uses these interfaces and the existing bounded storage/execution primitives; adapters format results only. Preserve existing public signatures and add explicit versioned fields. Corrections to misleading certification or previously accepted incomplete evidence need a documented migration requiring fresh evidence.
Stage contract
- Discover and classify. Import retained finding evidence and inspect the selected upstream's current contribution rules. Search both open and closed issues and PRs and relevant merge/release history. Bound requests/results; exhaustion, authentication failure, rate limits or stale results mean partial/unknown, never “no duplicate exists.” Refresh relevant matches before publication. Read-only discovery may stop at a linked existing report, upstream fix, invalid finding or unsupported environment.
- Reproduce on exact upstream source. Preserve a clean immutable base and run the upstream's actual documented commands in a disposable admitted environment. Record native failing tests, prerequisites and failure controls; do not replace upstream tests with a Praetor audit. A new reproducer must fail on the unchanged base and avoid the observed failure mechanism on the candidate. Environment failures do not establish an upstream defect. Unavailable native execution leaves a report candidate with an explicit limitation.
- Prepare a minimal local change. Reuse the bounded repair/command infrastructure where its current contract fits. Extend through reviewed language adapters when it does not; do not loosen the narrow repair API silently. Keep the patch minimal and avoid unrelated governance adoption. Verify exact-base application, regression tests, relevant upstream gates and source cleanliness. Keep original-corpus/consumer replay separate from scoped patch verification. Reuse a reviewed upstream fix when it already exists and record its attribution.
- Build the reviewable draft. Produce a local bundle with problem, minimal reproduction, expected/actual behavior, affected source/version, search matches, patch, verification and omitted gates, attribution, target and rendered issue/PR text. Report-only contributions can omit a fix but cannot claim fix verification. Keep raw transcripts, private settings, cluster guides, workstation paths and credentials out of exports. An LLM may draft text; deterministic validation and review establish the admitted artifact. Local draft creation does not create a remote draft PR.
- Publish only the authorized artifact. Present the concrete bundle for explicit approval of external mutation. Recheck target/head/digest and duplicate status immediately before execution. Read back the exact issue/PR identity, draft state and head. Branch/fork creation and push are separate external operations and must be included in the authorization scope. Preserve normal hooks. Persist attempted/confirmed/ambiguous outcomes; after timeout or crash, inspect remote state before retrying so one accepted create cannot become two submissions. Creating an issue and PR is not an atomic transaction; retain partial success. No merge or unsolicited comment is implied.
- Observe acceptance and maintain downstream. Read current upstream review/merge status and propose requested changes through the same candidate/review path. Do not equate closed with merged or merged with released. Bind accepted fix to its actual merge/squash/cherry-pick result and released artifact/version, accounting for backports or reverts. A downstream bump is prepared and tested in isolation without the local patch. Remove only the exact unchanged retained patch after that consumer passes the required checks; protect changed files with snapshot comparison and keep rollback/provenance. Partial fleet success retires patches per consumer, not globally.
Smallest implementation slices and acceptance
| Slice | Deliverable using existing modules | Required proof |
|---|---|---|
| 0 Truthful prerequisites | Correct the issue listing/index/batch defects and canary evidence labels in their existing modules. This extends stage 0 of the package plan. | Red/green tests for full-page exhaustion, issue 1,001, same-batch duplicates, duplicate existing titles, dry-run certification and diagnostic-only patch output. Partial discovery cannot authorize creation. No disabled lint/security gates. |
| 1 Shared local contribution plan | Add the contribution relation/policy slice to the shared package application service; bounded import and local sanitized draft projection through CLI/MCP. | The same finding from two consumers produces one contribution with two origins; conflicting causes remain separate. Source/policy/digest tampering, private data export and absent selected config fail. Repeated local preparation is idempotent; no forge mutation/provider dispatch occurs. |
| 2 GitHub read-only observations | Add complete-or-explicitly-partial issue/PR/status capabilities to existing forge transport. | Hermetic HTTP contract tests for pagination, rate/auth errors, ambiguous matches, renamed repositories, closed-unmerged PRs and stale snapshots. Missing Gitea/GitLab/Forgejo capabilities fail visibly. Then a specifically selected live read-only target proves actual behavior. |
| 3 One native reproduction and patch | Prove one admitted Go upstream fixture using existing isolation, command execution and evidence; retain a rejected negative control. | Exact base fails the intended assertion, candidate passes, patch applies only to allowed paths, required native gates run, source/toolchain identities and costs are retained. A changed base or test-only false success blocks verification. All adapters expose the same evidence and limits. |
| 4 Authorized remote draft | Extend existing GitHub publication with the selected draft contract, target binding, durable attempt journal and readback. | No authorization means zero mutations. Changed reviewed digest/target rejects. Lost response after successful create is recovered without duplicate publication. Wrong head/non-draft readback blocks confirmation. Test against a synthetic owned repository only after concrete authorization. |
| 5 Acceptance and patch retirement | Bind upstream acceptance/release observation to existing bump candidate and downstream verification records. | Closed-unmerged, merged-unreleased, reverted fix, wrong release source, failed consumer and changed patch all retain the patch. Verified fixed release plus clean no-patch consumer checks permit one exact retirement. Resume after partial failure neither duplicates nor drops another consumer's work. |
Keep these slices on the existing package pipeline backlog and shared interconnect initiative. Local evidence artifacts remain private; only reviewed source-based plans and sanitized contribution bundles are public. Completion requires real CLI/MCP parity and relevant source-bound execution/readback, normal Lefthook and verification gates, plus explicit published-state evidence for any publication claim. A unit test suite or catalog declaration alone does not establish a working upstreaming loop.