Skip to content

[Feature] Release V3: source resolver, manifest, GitHub + Local providers (PR-4) #165

Description

@Rwanbt

Problem

The update path knows one remote provider (GitHub Releases via
ReleaseApiProvider) and one local mirror format. Multi-Forge requires a single
resolve_release_source(), a ReleaseProvider contract, an externally anchored
ReleaseManifest V3 with an exact version chain, and GitHub + Local providers —
without weakening any fail-closed behavior.

Source: Multi-Forge v1.3.2-final §33–43 (PR-4, PR-4A–4E).

Expected outcome

update, update check, status and doctor resolve their source through one
function with conflict validation before precedence; V3 manifests are verified
against externally supplied digest + size before anything is parsed; GitHub and
Local providers implement the same logical verification chain.

Acceptance criteria

  • Blocked until PR-0A merged AND ADR-MF-03 accepted. PR-0B need not block
    coding but MUST be shipped in a V2-compatible bridge release before the
    first V3 publication.
  • PR-4A — ReleaseProviderEndpointConfig; ~/.ai-native/release-providers.json
    machine config; reserved provider names; resolve_release_source() with
    source diagnostics; no project-local provider trust config.
  • PR-4A selector rules exactly as frozen: AINATIVE_UPDATE_PROVIDER=local +
    AINATIVE_UPDATE_LOCAL_DIR → LocalDirectoryProvider;
    AINATIVE_UPDATE_LOCAL_DIR without explicit provider=local →
    UPDATE_SOURCE_CONFLICT; AINATIVE_UPDATE_URL mixed with provider/local
    selectors → UPDATE_SOURCE_CONFLICT; AINATIVE_UPDATE_URL alone →
    anonymous release API; named provider → machine config/built-in; nothing
    selected → machine default_provider or built-in GitHub.com. No
    last-selector-wins. Identical behavior across update, update check,
    status, doctor.
  • Per-command observability: effective source, selection reason, authenticated
    yes/no, auth origin if applicable — never secret values.
  • PR-4B — ReleaseQuery, ReleaseCandidate, EnumerationResult,
    ReleaseProvider.enumerate()/fetch_manifest()/fetch_artifact();
    complete=false → RELEASE_ENUMERATION_INCOMPLETE; complete compatible
    channel with zero candidates → RELEASE_NO_CANDIDATE.
  • PR-4B — SemVer policy: installable releases 1.2.3, 1.2.3-rc.1; reject
    1.2.3+build1 with RELEASE_BUILD_METADATA_UNSUPPORTED; explicit release
    precedence key; same canonical precedence with conflicting identities →
    RELEASE_DUPLICATE_VERSION.
  • PR-4C — ReleaseManifest V3: schema, protocol, version, channel,
    compatibility, artifacts, provenance; V1 compatibility mode
    exact-runtime.
  • PR-4C — Trust chain sequence enforced: provider metadata → manifest SHA-256
    + size → download → verify → parse manifest → select lifecycle artifact →
    download → verify size + SHA-256. Trust-bearing artifact declarations are
    never parsed before the manifest is verified.
  • PR-4C — Exact version chain equality: candidate.version ==
    manifest.version == compatibility.runtime_version == artifact.version ==
    artifact filename version == lifecycle-protocol.json.release_version;
    failure → UPDATE_VERSION_MISMATCH.
  • PR-4D — GitHub.com provider: bounded enumeration, release asset metadata,
    manifest digest/size anchor, private assets (PR-0A transport), API version
    header, authenticated API request, anonymous CDN redirect. Declares support
    for GitHub.com only — not GHES.
  • PR-4E — Local provider adapted to V3 without weakening integrity:
    releases.json provides manifest locator + size + sha256; the local
    provider executes the same logical verification chain as network providers.
  • Anonymous release API compatibility: AINATIVE_UPDATE_URL stays HTTPS,
    anonymous, GitHub-Release-API-compatible metadata; missing V3 integrity
    metadata fails closed.
  • Any uncertainty (auth origin, redirect origin, manifest digest, artifact
    digest, ambiguity, selection, enumeration completeness) → REFUSE UPDATE,
    never warning-and-continue.

Out of scope

Context

  • ainative/lifecycle/provider.py, updater.py, machine.py, docs/RELEASING.md.
  • PR-0A (transport), ADR-MF-03 (frozen contract), PR-0B (must ship before V3
    publication).
  • Split into PR-4A/4B/4C/4D/4E if the logical PR exceeds 400 changed LOC.

Dependencies

Activity

  1. added
    type:featureA new capability or improvement
    priority:P1Major user-facing defect or release blocker
    on Sep 16, 2026
  2. self-assigned this
    on Sep 16, 2026
  3. Rwanbt commented on Sep 16, 2026

    @Rwanbt
    OwnerAuthor

    Claiming this Issue; PR-4A starts on \multiforge\ (local, CI at the end).

  4. Rwanbt commented on Sep 16, 2026

    @Rwanbt
    OwnerAuthor

    Multi-Forge implementation merged into dev (squash f0101fc via PR #172), full CI matrix green (52/52: Linux/Windows/macOS, py3.11/3.13). The Issue stays open until the final dev -> main promotion, per the maintainer rule that main is untouched until everything is tested and integrated.

  5. Rwanbt commented on Sep 16, 2026

    @Rwanbt
    OwnerAuthor

    The follow-up increment (mandatory secret-pattern floor, scenarios J/M/P, documentation parity) is merged into dev (squash a8e1fb6 via PR #174, CI 76/76 green). The Issue stays open until the final dev -> main promotion.

  6. Rwanbt commented on Sep 17, 2026

    @Rwanbt
    OwnerAuthor

    Done: the work is merged into main (squash 8f319ad via PR #176, full CI matrix green including the Production Gate). Closed as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

priority:P1Major user-facing defect or release blockertype:featureA new capability or improvement

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions