Skip to content

Gallery-only retries preserve the original owned release version - #549

Open
Marius Storhaug (MariusStorhaug) wants to merge 31 commits into
mainfrom
gallery-recovery
Open

Marius Storhaug (MariusStorhaug) wants to merge 31 commits into
mainfrom
gallery-recovery

Conversation

@MariusStorhaug

@MariusStorhaug Marius Storhaug (MariusStorhaug) commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Standalone Publish-PSModule callers must pass the resolver's FullVersion as ReleaseTag and provide repository-scoped contents-write GH_TOKEN. Standalone Publish/Release calls using a non-default tag prefix must also pass their existing VersionPrefix; its default is v. Normal Process-PSModule callers retain their existing inputs, settings, secrets, permissions, and artifact layout; no configuration, code, or invocation changes are required beyond selecting a compatible published framework delivery containing publication preflight and this recovery fix.

Gallery-only retries retain the original version only when source, context, prefix, shared module/version ownership, and raw package proof agree; completion needs the original proven tested artifact. Supported omitted-GUID full-run recovery remains blocked on approved artifact selection/test provenance. The observed v8.0.7 framework-archive-to-candidate range includes earlier documentation-link corrections and the unmerged Major preflight changes, not just the Patch recovery delta. Original release-time provenance is unavailable, so full release coverage and readiness remain provisional; merging a prerequisite without publishing it does not remove its consumer impact.

Breaking: Standalone publication requires resolved coordinates and repository write access

The publication-preflight prerequisite requires standalone Publish-PSModule callers to pass the resolver's FullVersion as ReleaseTag and repository-scoped contents-write GH_TOKEN. Standalone Publish/Release callers with a prefix other than the default v must pass that existing configured value as VersionPrefix to both actions. The prefix and tested module version must form the exact resolved tag; do not construct a different tag from numeric equality, a release name, or a moving branch.

Preserve the original tested artifact and supply its source through CommitSha or the original-workflow GITHUB_SHA fallback. Pass one normalized producing PR object, empty only for a genuine direct release, and the same prefix/source/context/artifact to Release-PSModule; arrays are not context. Normal reusable-workflow callers receive these values/token internally and require no caller, settings, permission, metadata, or invocation changes beyond selecting the compatible published delivery containing preflight and recovery. Consumers compose applicable release notes without installing every intermediate version; no intermediate installation or run is required for an unaffected caller.

Technical details

This section retains prerequisite #548's Major standalone-publisher, prefix, authentication, and unproven-publication compatibility effects. The release-bearing comparison starts from the actual observed published framework archive, not the scoped main PR base or prerequisite head. The original publication receipt is not available, so the verified current archive/source comparison does not establish immutable release-time provenance or final release compatibility.

Publication baseline and comparison

Field Evidence
Product scope Process-PSModule's versioned reusable workflows/actions and bundled guidance, distributed through the repository's GitHub release/source archive, Stable channel. Consumer modules published to Gallery and live Pages deployments are separate targets; neither supplies this framework-artifact baseline.
Published artifact v8.0.7, release ID 386444646, published 2026-09-10T16:20:37Z, not draft/prerelease. The complete inventory contains 143 published stable records; this is its latest observed publication entry, not an assumed highest version or GitHub Latest hint. It has no attached package assets.
Artifact readback The authoritative version ZIP archive was read back; SHA-256 a0d91371788d60bf0b2c55ca41e8c462a925170eabe1077277a1f6343f23d361. All 336 regular entries match the exact source Git blobs without extraction or code execution. This pins the observed archive bytes, not a permanent digest of future regenerated archives.
Published source PSModule/Process-PSModule commit 105e4dcefe1946782066aa50a5c7d3658319895a, tree 37093e61f57bbef368cb0f996891e0558167bc9b, established by exact archive/blob comparison and current version-tag readback. Moving v8/v8.0 aliases and target_commitish: main are not source proof.
Publication receipt gap The release is mutable (immutable: false) and the tag is lightweight. Metadata for the original Release run remains, but its log endpoint returns HTTP 410. Its successful status/PR head is not a retained publication-time source/digest attestation. Historical immutable artifact-to-producer provenance remains unresolved.
Candidate source PSModule/Process-PSModule commit a015792b20054275ed7defe5726e9bc003d51a09, the live PR head on gallery-recovery; its complete tree equals owner-authored ba1359d4ccc0e0bd9a994ab2abb607021f1521e4.
Full publication-to-candidate comparison Direct source-tree diff 105e4dcefe1946782066aa50a5c7d3658319895a to a015792b20054275ed7defe5726e9bc003d51a09: 27 files, 4,848 insertions and 279 deletions. Published source is an ancestor. No merge base or main PR base is substituted. The inventory includes the previously merged documentation-link correction absent from this observed archive.
Scoped PR comparison Main 64ffb1d87f86bd5d487891fdb140b78385a00531 to candidate a015792b20054275ed7defe5726e9bc003d51a09: 22 files, 4,839 insertions and 270 deletions. This describes implementation/reviewer scope and contains the unmerged prerequisite; it does not define release-note coverage.
Own recovery comparison Prerequisite eb3eb0cb8fb6f0b7822c79ad9b2781d17127dcd4 to the same candidate: 11 files, 964 insertions and 46 deletions. Patch describes only this compatible implementation delta, not the complete next published artifact.
Freshness and readiness Re-read the target's publication inventory, current archive/source identity, and exact candidate before readiness or a release-bound snapshot. Any changed baseline/head requires a new full comparison, consumer inventory, actions, and compatibility decision. The expired original receipt, current review gaps, artifact-provenance and native decision gates remain explicit holds.

The complete observed artifact range contains four reader outcomes: required standalone coordinates/token/prefix adoption, fail-explicit source/context/artifact safeguards, original-version exact-artifact recovery and its limits, and corrected framework guidance links. Those results are classified below; their presence in full release coverage does not turn previously merged work into this PR's implementation.

Identifier / surface Before After Applicability / prerequisites Consumer action Verification
PUB-STANDALONE / Publish and Release actions Gallery publication does not require resolved GitHub coordinates; configured tags lack explicit prefix/artifact binding. ReleaseTag, immutable source, and repository access are required; optional VersionPrefix defaults to v and binds the tested version. Standalone integrations, especially non-default prefixes; preflight prerequisite. Pass FullVersion, matching configured prefix, original CommitSha/GITHUB_SHA, tested bytes, positive producing context, and scoped GH_TOKEN. Missing-input/source, mismatched-version/prefix, custom-prefix, and zero-write fixtures.
PUB-CALLER / reusable workflow Existing settings, resolved version, source, and scoped token supply publication. The same caller interface wires Resolution.FullVersion, Context.CommitSha, and Publish.Module.VersionPrefix internally. Existing normal framework callers. No configuration, code, permissions, or invocation edit beyond selecting the compatible published release. Complete caller/settings comparison with the immutable main baseline.
Changed surface Standards checked Framework docs checked Result
Publisher action inputs and reusable caller GitHub Actions, YAML, Dependencies Publish-PSModule inputs; complete Settings/FullVersion/Context.CommitSha contract Fixed in this PR
Standalone publisher guidance Markdown, Natural Language Publisher and release action contracts Fixed in this PR

No external integration template or consumer fleet is changed. The default/with-manifest fixtures retain their existing settings and artifact layout. Their exact-head hosted verification is required below; no unmerged production pin or consumer metadata rewrite is introduced. The closing delivery leaf is #513, not the prerequisite Bug; #548 remains the separate delivery of #547.

Related references

Fixed: Framework guidance points to the canonical documentation site

The bundled README, repository guidance, plugin homepage, repository-standard references, and site URL configuration point to https://psmodule.io/Process-PSModule/ instead of the retired documentation routes. Use that canonical site root for framework guidance; former deep-link references now open the root because a replacement deep path is not guaranteed. This is a guidance/link correction, not new module publication behavior or evidence that a Pages deployment occurred.

No workflow configuration, code, or invocation change is required for this correction beyond selecting a compatible published framework release. Existing normal reusable-workflow inputs/settings are unchanged across the complete observed artifact range. Old bookmarks may still need the canonical destination; no redirect guarantee is added.

Technical details

This earlier result was merged in #539 as 64ffb1d87f86bd5d487891fdb140b78385a00531, after the observed v8.0.7 source 105e4dcefe1946782066aa50a5c7d3658319895a. Its nine URL replacements in five source files are absent from the verified v8.0.7 archive and present in candidate a015792b20054275ed7defe5726e9bc003d51a09. The complete published-source comparison therefore includes them even though the scoped main-to-PR comparison does not.

The prior PR body and successful workflow statuses do not prove a separate artifact or website publication. This record covers bundled source guidance; it does not claim a new live Pages transition or require consumers to infer upgrade instructions from that historical PR.

Changed surface Standards checked Framework docs checked Result
Bundled README, repository-standard guidance, plugin homepage, and site URL configuration Markdown, Natural Language Canonical Process-PSModule documentation destination Aligned

The closing implementation remains #513. The earlier documentation change is non-closing context, not a second implementation issue delivered by this PR.

Related references

Fixed: Ownership conflicts stop before Gallery publication

Publication verifies the repository, immutable source, exact resolved prefix/tag/version, producing context, tested file tree, and canonical release ZIP before taking a Gallery version. The prefix-independent PSModule-Publication/<escaped-lowercase-module>/<lowercase-version> coordinate and configured release tag must reference one immutable annotated claim. Module-coordinate dots are escaped as %2e without changing Gallery names or consumer metadata. Another prefix cannot claim the same package for a different source or context.

An observed tag must remain unchanged through shared coordinate creation. Disappearance or replacement, including a tag first observed after initial preflight, stops before release-reference recreation or Gallery publication. Competing claims, foreign or unreadable terminal provenance, differing assets, malformed context, and authentication/API failures remain explicit errors. Version and prerelease reads distinguish verified package absence from unavailable or malformed metadata; they do not invent a baseline or counter.

Retain the original source, prefix, resolved coordinates, context, and tested bytes. Proven identical Gallery payload and GitHub ZIP bytes are retained; a missing upload can resume. Published bytes are never replaced and existing tags are not retargeted. A historical package without its shared ownership coordinate is unproven: do not fabricate that record, import package code as proof, edit metadata, replace tags/assets, or guess a version. Incomplete legacy publication needs reviewed forward-only reconciliation. Normal callers need no additional configuration or invocation change beyond the compatible release selection above.

Supply one normalized producing-context object, not a JSON array; malformed arrays no longer collapse into an absent or valid context. Artifacts with a literal filename backslash on Unix fail before hashing or ZIP creation instead of being silently renamed in the proof. Correct invalid source paths only as a new reviewed forward-only candidate; do not rename or replace the original tested or published artifact to make a retry pass.

Original event context and versioned provenance are validated before fields are projected; required proof fields must be scalar values, not singleton arrays. The ZIP's exact bytes and module payload must agree together with the tested file tree before a claim, Gallery write, GitHub creation, or upload. A self-consistent ZIP checksum alone cannot authorize an archive containing different tested payload bytes. These checks add no consumer metadata or Build rewrite.

An existing release must explicitly report scalar boolean draft: false, and its asset name, state, and digest must be strings before proof comparison. Missing or malformed published status/asset proof stops publication; it is not verified absence. PR-produced stable and prerelease releases also require the same final producing-repository/PR/source footer. Unknown legacy context requires reviewed forward-only reconciliation, not footer fabrication or metadata edits; malformed terminal markers fail even when indented or inline.

Technical details

These are the prerequisite's results, retained because it remains unmerged in this main-targeting draft. Bounded owner corrections add shared module/version ownership, configured-prefix binding, malformed terminal/JSON-shape rejection, and a shared NuGet path classifier. The canonical archive proof reads exact ZIP bytes and payload through one open stream and compares both with the tested tree/asset claim before each mutation boundary. Literal Unix backslashes fail rather than changing tested paths. Existing immutable-tag/footer/file-tree helpers are reused; there is no second paginator, checksum bump authority, or general lifecycle journal.

The original delivery record preserves mutation-order and false-baseline RED evidence. This host also reproduced all three late reservation races before the guard: each old case made one simulated Gallery write; both valid partial-claim controls passed. The exact owner guard then made all five cases pass. Raw package proof reads ZIP/nuspec streams without installation or package import; complete notes precede the final producing-context footer.

The next two ordinary owner test commits reproduced 21 intended failures among 32 bounded raw-shape/event/archive cases. An inconsistent ZIP payload/file-tree tuple made one simulated Gallery write; three malformed original-event projections bypassed rejection, while the valid producing-PR control passed. The canonical source correction now makes the complete suite pass. This experiment changes no live package, tag, release, or consumer data.

Changed surface Standards checked Framework docs checked Result
Source/tag/provenance and ZIP/nupkg proof helpers PowerShell, Functions, Error Handling, Testing Resolved source/tag/artifact and complete-notes contracts Fixed in this PR
Gallery publisher and GitHub release rechecks PowerShell, Error Handling, Testing Publish-PSModule and Release-PSModule interfaces Fixed in this PR
Gallery version/prerelease read boundaries PowerShell, Error Handling, Testing Plan resolver and verified-absence contracts Fixed in this PR
Ownership/read-error controller fixtures Pester, Testing Locally runnable action suites Aligned
Publication and recovery guidance Markdown, Natural Language Versioning and release guide/action contracts Fixed in this PR

The scoped issue-convergence sweep examined Gallery/publication/recovery issues and the adjacent decision, self-test, artifact, and cleanup work. #547 belongs to the prerequisite PR; #530, #443, #359, #524, and #541 are not delivered here. The existing publication split is not a new closing delivery. No additional issue is closed and no native dependency edge is added or removed.

Related references

Fixed: Gallery-only retries keep the original owned version

Plan searches both configured release-tag and shared module/version claims for the original source, module, prefix, and producing context. Aliases for the same proven immutable claim are deduplicated. Exact raw Gallery payload and any GitHub release/asset evidence must agree. Even a shared-only claim without a published package stops Plan for original-job retry before newer hints can select another version. Original normalized/event PR context is validated before projection; a producing PR is not converted into direct-release identity 0.

A new source verifies baseline completeness through the actual historical tag/release, including when its configured prefix changes or contains digits with or without a separator. A matching version suffix discovers a candidate only; exact release metadata, module/version assets, and immutable source still establish completeness. Recovery/new claims bind the current prefix exactly, ambiguous completed baselines fail explicitly, and the configured bump policy is not replaced.

Only the proven duplicate Gallery upload is skipped; GitHub creation or a missing upload completes from the original tested bytes. The existing Build/test path still runs when enabled, and changed rebuilt bytes stop at the claim check. Version selection does not make a same-source rebuild identical or deliver original-artifact promotion.

Select a compatible published delivery containing preflight and recovery; normal caller inputs/settings remain unchanged. Retain the original immutable source, producing context, prefix/coordinates, and tested artifact. An original failed Publish-job retry can use surviving original bytes/settings only when that original runtime already contains the safety behavior and its artifact and completed-test evidence remain verifiable. Retrying an old run does not inject this unmerged code. If a source claim exists but Gallery publication did not succeed, retain its version/artifact and rerun the original failed job.

Supported manifests may omit GUID. Their clean rebuilds can generate different manifest, file-tree, and canonical ZIP bytes, so a full/new-run retry cannot claim completed recovery from those fresh bytes. Wait for separately approved immutable original-artifact selection and source/context/completed-test provenance; selecting a current run or artifact name alone is not that proof. Missing/expired artifacts or proof stop recovery. Do not insert or replace consumer GUID/metadata, weaken byte checks, or reconstruct a package as an implicit promotion path.

Missing, foreign, ambiguous, malformed, or unavailable proof and API failures stop resolution explicitly. Incomplete legacy publication needs reviewed forward-only reconciliation. New-source releases after completed legacy publication and non-publishing previews retain the existing configured decision policy; no scalar DefaultBump or replacement bump authority is added.

Technical details

Consumer change record

Identifier / surface Before After Applicability / prerequisites Consumer action Verification
GAL-RESOLVE / Plan version selection Numeric equality or skipped shared-only claims can allow a new number after hints advance. Release/shared refs are deduplicated by proven immutable identity; raw package proof selects the original version, and unpublished original claims stop before another bump. Preflight claim, shared module/version coordinate, and original source/context. Preserve original coordinates, prefix, context, and tested bytes; use the original failed job for an unpublished claim, not a new guessed version. Exact-version/shared-only/alias proof, foreign/missing proof, and later-hint cases.
GAL-RESUME / Gallery and GitHub completion Numeric equality can skip an unrelated package or strand a missing GitHub upload. Only the proven duplicate Gallery upload is skipped; missing GitHub work completes without replacing bytes. The same tested package and release context. Retry the original job/source/artifact; retain any identical existing package and ZIP. Gallery-success/GitHub-failure/retry and existing-release/missing-upload compositions.
GAL-FAIL / incomplete legacy publication Missing ownership can silently select an unrelated version or fallback bump. Missing/foreign/ambiguous proof, changed bytes, and API failures are explicit errors. Legacy or conflicting incomplete publication. Reviewed forward-only reconciliation; no guessed version, retagging, package import, or metadata edits. Zero additional Gallery/GitHub writes after changed rebuilt bytes; proof and API-error fixtures.
GAL-POLICY / supported settings Existing labels/default behavior supplies the configured bump. The same policy remains for new releases and non-publishing previews. Existing Settings and normalized source/producing context. No settings or invocation-level bump edit. Existing decision suite and completed-legacy/new-source cases.
GAL-BASELINE / configured prefix changes A completed historical baseline can be queried using the new prefix and mistaken for a Gallery-only gap. New-source completeness uses actual historical tag/release proof; ambiguous baselines stop. Recovery/new claims retain current-prefix binding. Completed historical publication and an unchanged source-bound ownership contract. Keep the configured prefix/settings; no metadata rewrite or alternative bump input. Historical v to release- control and ambiguous-baseline rejection.
GAL-CONTEXT / producing PR Event fallback omits Number; raw arrays/objects can be projected into valid/direct identity. Shared validation checks original context before projection and preserves the actual producing Number. Supplied normalized/event context; genuine absence remains direct. Preserve one original producing context; no consumer metadata edit. Permanent event/normalized malformed-context rejection and genuine direct-release controls.
GAL-ARTIFACT / full-run retry Supported omitted-GUID rebuilds change tested payload identity. Conflicting rebuilt bytes remain rejected; completion needs the original proven tested artifact. Original-artifact selection/provenance is a separate unresolved prerequisite. Use only an eligible verified original-job procedure; wait for approved full-run/cross-run selection, not GUID repair. Four real builds and frozen retained-artifact preflight investigation; not current-head hosted promotion.

Complete release coverage and scoped comparisons

Release-note coverage uses observed published archive source 105e4dcefe1946782066aa50a5c7d3658319895a to exact candidate a015792b20054275ed7defe5726e9bc003d51a09, with current readback proof and the unresolved historical receipt recorded above. Its complete 27-file range includes earlier guidance and unmerged preflight, not only recovery. Live Pages and consumer Gallery inventories are not substituted for this framework target.

The separately scoped main-to-head range is 64ffb1d87f86bd5d487891fdb140b78385a00531 to a015792b20054275ed7defe5726e9bc003d51a09: 22 files, 4,839 insertions and 270 deletions. It establishes implementation scope, contains unmerged #548, and is not the full release coverage baseline.

The independent delta from prerequisite eb3eb0cb8fb6f0b7822c79ad9b2781d17127dcd4 is 11 files, 964 insertions and 46 deletions, identical to owner recovery ba1359d4ccc0e0bd9a994ab2abb607021f1521e4. The source-bound implementation carries only bounded owner context/shared-reader/recovery corrections; no independent algorithm or bump authority is added. Patch describes this implementation delta only. A prerequisite landing without publication does not remove its Major effects from the next artifact. Caller/settings/Build/test interfaces remain unchanged across the full range; no template/fleet or #541 work is copied.

Delivery and validation evidence

This topic first fast-forwarded to frozen 982f3dd660e6870cad381ea48d7f9c749e7e9152, then incorporated the first owner correction as d4b206a. The next ordered owner sources are aa86256471cfcc38fa0360ff8a2f563eb751c0c8, dc78ee268e63ef8a014020bd2f99f0d2739609c3, adapter 32b93d1f523d53ef635359c14d8203de58127854, regression 6254d3442778d07a776a5c4be4adba4ca37ba571, and guard/guidance 474d0946a6bcf4112b097a84557c7c76465e84a6. Their ordinary attributed copies are e20d41a, 5fb356b, f68b14a, 61f81ff, and ff6bf3f; every source is recorded by cherry-pick -x.

The one additive reader conflict retains both GetTagList and GetVersionReference and matches the exact owner helper bytes. The earlier ff6bf3f tree equals owner bae4e7c. The next ordered originals are proof regressions 2afb9294a6de5452ba0d9aba00c722529b0eece5, event regressions 131c30b1ec476717b140a5703673ada72a854bfb, and source/tests/guidance e59ac33a8627e021ec89d380988d14cc5eae44fc, incorporated as ordinary attributed 6abfb43, 85003e1, and c2542d4.

The earlier c2542d4 tree equals owner ce51909e. Resolver originals 136af136bb42e108754fe5cee21d45118ad52c18 and 3bdda6582e0abb1767707136f2bb5e1cee3c3bdd were incorporated as 2c4ecf6/c665a9b, exactly matching the owner tree. Terminal/resource/coordinate originals 3faf9fb1315471a3b11f62c1856b914fd263dd19 and 8ed237742e1a98b869310a8e14c770ba55bde0db, followed by collection originals b367050dc8984b8acac56dd1d91488a528e8723a and ae7c3334aed87c30578a84efc89022cc87b6462d, became 53b32f3/085036b/c47584b/e2e282a. The documented shared-reader translation retains GetTagList; the whole tree equals owner ae7c3334.

The confirmed final follow-up contains only originals 254cebc22e3bd6add72c6d5ee3a8013f3c1b29bf, 0281a037576e08f3461c60b1a48724bca545993d, bf242f28878f3f7aac0293f482991f1f800dbb5e, and eb3eb0cb8fb6f0b7822c79ad9b2781d17127dcd4, in that order. Ordinary attributed copies are 33efec4/33c2050/a9f6194/a015792. Current a015792b20054275ed7defe5726e9bc003d51a09 exactly matches owner ba1359d4ccc0e0bd9a994ab2abb607021f1521e4; translated owner copies were not applied twice.

Original authorship/history are preserved; no owner branch or #548 is rewritten, retargeted, switched, amended, or force-pushed. There is no independent resolver/publisher algorithm, Build, GUID/consumer-metadata, caller-promotion, or bump-policy rewrite.

The authored delivery record reports all 136 composed action tests passing with actual Pester 6.1.0 shuffle seed 42 and parallel throttle 2, changed PowerShell analysis passing, and both recovery documentation pages linting cleanly. The composition demonstrates Gallery success, GitHub creation failure, raw source/package proof before a Build spy, same-version retry with exactly one Gallery write, unchanged raw nupkg bytes, and a matching GitHub ZIP digest. A second composition covers an existing release with a missing upload; changed rebuilt bytes cause zero additional Gallery or GitHub creation/upload writes.

Three late-reservation cases at 61f81ff each reproduced one simulated Gallery write before the guard. The next raw-proof/event test-only head 85003e1 reproduced 21 intended failures and 11 controls/passes across 32 bounded cases, including the inconsistent ZIP tuple. No RED head was pushed.

The raw-shape/paired-archive head c2542d4 passed 201 action tests with one genuine Windows Unix skip. All eight permanent raw-event and three paired-archive cases passed; two additional actual-controller checks rejected {"pull_request":[]} before publication reads/writes. Those controller/proof surfaces remain unchanged in the resolver correction.

Resolver test-only 2c4ecf6 reproduced four exact failures with twelve controls passing: an unpublished shared-only claim was bypassed, missing-tag proof was misclassified, a changed-prefix historical baseline was rejected, and an ambiguous baseline was accepted. After the exact owner source, current c665a9bb44711d36684098f3f3733748e11213f4 passes all 16 resolver cases and 206 full action tests, with one genuine Unix-only Windows skip and zero failures. Actual Pester 6.1.0 shuffle 42/parallel throttle 2 are checked on the executed configuration. No RED head was pushed.

All four directly related documentation pages and diff whitespace pass. Configured analysis passes all 15 changed PowerShell files in a no-profile process with declared Pester 6.1/PSAnalyzer 1.25 and standard modules. The ordinary local process had misresolved unchanged Pester Context blocks as an unrelated installed Get-Context; isolation corrected tool resolution without changing source, adding suppressions, or weakening repository rules.

The earlier hosted merge 267d362ac4b4704224ec38b524a73227ff9f410e was fetched and its tree verified identical to c665a9b/owner 3bdda658 and passed 207 Ubuntu cases. This is historical validation, not a substitute for the current head. At a015792, all 238 local tests pass with one genuine Windows-only skip for the Unix filename case, using actual Pester 6.1 shuffle 42/parallel throttle 2. The three valid digit-prefix regressions plus unrelated-version control and four invalid draft-status cases all pass after their recorded RED runs.

Current Ubuntu action tests pass all 239 cases with zero skips, including the eight new prefix/status cases. All reported current-head checks pass (71 passes/eight intended skips), including both fixture workflows and repository lint. Five newly changed PowerShell files pass the same local analyzer rules, and four documentation pages pass lint. Full local analysis still reports 14 Context/Get-Context diagnostics in an unchanged Pester DSL file; no valid test block, rule, or suppression is changed to hide that tool-resolution issue, and full local clean analysis is not claimed.

The earlier c665a9b fixture run needed one transport retry: macOS tests passed 13/13, but artifact creation timed out, leaving a missing report. The same-head failed-jobs-only retry uploaded artifact 13058539690; aggregation verified it present, executed, and passed. This is historical evidence, not a new-head artifact receipt. Current a015792 fixture and lint jobs pass independently, Module/Site publication is skipped, and its Release log explicitly reports no stable/prerelease creation. No Build, source, pin, or gate was weakened.

Review 5723853208 at earlier head d4b206a reported four native findings. The corrected, locally verified composition addresses three:

  • Tag/artifact binding: exact configured-prefix/version binding and shared module/version ownership have permanent zero-write/custom-prefix fixtures.
  • Producing PR event fallback: the supported event fallback retains the positive producing Number.
  • Original PR context validation: the shared validator checks original normalized/event arrays and objects before projection, while genuine absence remains direct.

The complete ff6bf3f review 5724385048 confirms those three resolved findings and reported two new high-severity inline gaps plus one previously missed summary-only regression:

  • Publisher/Release raw event fallback: the exact owner source correction now validates both original event objects/PR values before projection and uses a null check. The raw-event and array-valued-number fixtures pass at c2542d4, and this thread is replied/resolved. This closure is not full review convergence.
  • Incomplete shared-coordinate claim discovery: the bounded owner correction scans shared-only claims, checks original package evidence, and deduplicates proven immutable SHAs. The unpublished original claim stops before the next-version function; all 16 targeted/207 Ubuntu cases pass, and this thread is replied/resolved.
  • Historical baseline prefix, summary-only in 5724385048: actual historical tag/release proof now permits the anonymous completed v1.2.4 baseline with a new release- prefix and rejects ambiguity. Recovery/new claims retain current-prefix binding. All 16 cases pass; the summary is explicitly answered, not omitted for having no inline thread.

The raw-event, shared-only, and historical-prefix corrections are all exact bounded owner work, not an independent rewrite. The owner correction at e59ac33a also rejects raw provenance/field arrays and pairs ZIP bytes/payload before mutation. Fresh primary summary 5725043230 still requests human assessment of terminal/raw-metadata/Git-ref risks; the canonical owner is checking concrete remaining boundaries. Its final transfer/readiness remains held. Green runners and narrow closures are not proof that full provenance/recovery is complete.

The GUID finding remains open. Separately published investigation at frozen d4b206a/3405467 executed four actual clean anonymous builds: omitted GUID changed only final manifest identity and therefore tree/canonical ZIP hashes; explicit-GUID controls retained payload identity despite raw nupkg container differences. Retained original bytes passed frozen read-only preflight; fresh omitted-GUID bytes did not. The experiment was not hosted publication recovery or completed framework/consumer module tests, and does not validate a later composition. Build tree e8d5b81d740c8ae185de3e9aa5adb59026a94b99 is unchanged here.

Current-run/name downloads, highest-ID duplicate-name selection, and one-day retention are not immutable original-artifact/test provenance. Missing or expired evidence must fail. Original-job versus full/new-run/cross-run recovery therefore remains a separate decision and delivery; the explicit-GUID control does not authorize consumer metadata repair.

The original tag/context, raw-event, shared-only, and digit-containing prefix threads are replied/resolved; historical-prefix, strict draft:false, and scalar asset-proof summary findings are explicitly answered. Current-head review 5727566292 confirms the digit-prefix correction and still requests closer assessment, with the GUID finding open. The user explicitly chose to keep #549 blocked pending a separately approved original-artifact selection/provenance delivery. This does not authorize a Build, GUID/metadata, or promotion rewrite. Canonical release-ID/replacement, unpublished malformed-tag detail, human review, publication/source coverage, and native gates remain held. The sweep closes only #513.

Final authoring uses the user-directed, ready/unmerged MSXOrg/docs#209 PR Format at bc03a5992615f65d1d5346dc48e7506e80b8b6ca, including Resolve release coverage first and the complete description example. The earlier be8c340 and 27ffab8 captures are historical evidence, not final-source authority. This changes the authored description, not GitHub template-file policy.

Changed surface Standards checked Framework docs checked Result
Immutable claim enumeration and original-version selection PowerShell, Functions, Error Handling, Testing Plan/version/source context contract Fixed in this PR
Read-only collection and exact raw package proof PowerShell, Error Handling, Testing Shared publication preflight and raw nupkg evidence Fixed in this PR
Resolver controller context PowerShell, GitHub Actions Complete Settings and normalized producing context Aligned
Publisher/resolver/retry composition fixtures Pester, Testing Existing local action-suite validation Fixed in this PR
Recovery action and guide documentation Markdown, Natural Language Versioning, publication, original-job retry contracts Fixed in this PR

Readiness and ordering

#513 retains its native blocked-by dependency on open Bug #547; delivery #548 remains open/unmerged. No cycle is added. After an authorized prerequisite landing, reconcile the scoped recovery delta against advanced main and repeat exact-head checks/full review. Separately re-read actual target receipts: a merged but unpublished prerequisite remains part of full release coverage. The user-confirmed artifact/provenance blocker, canonical identity assessment, expired historical receipt, and native gates prevent readiness. GitHub's open/non-draft UI state is not that clearance. Merging remains disabled; no live publication, tags/releases, labels/permissions/rulesets, or production unmerged pin are authorized.

The inspected main rules require squash integration, code-owner/last-push review, and resolved review threads, but do not currently name a required release-decision status check. A passing Release job on an unmerged, unlabeled draft is not a verified compatibility decision or permission to release; the producer/mapping/check gap remains blocked rather than treated as a pass.

The safe delivery order is publication preflight, this recovery delta, then bounded #531 composition. Neither safety leaf depends on unmerged #531. #524's settings/Skip work and #541's artifact scope remain separate.

Related references
Release decisions
  • Release: Yes, proposed for the native GitHub Stable framework-artifact route: the complete observed published-archive-to-candidate range changes supported publication and standalone contracts and includes previously merged guidance. The original publication-time provenance gap keeps final coverage unresolved; this draft performs no release.
  • Version bump: Major for the verified current v8.0.7 archive-source-to-candidate comparison because of required standalone resolved-tag/token and non-default prefix adoption. This decision is provisional while publication-time provenance remains unresolved. Patch applies only to the 11-file recovery implementation comparison; a prerequisite merge without verified publication does not reset the consumer baseline or turn the full next artifact into Patch. Final confirmation remains blocked on publication/source proof, complete review, and native enforcement.
  • Mode: Stable for the intended main-targeting route after an authorized merge; no prerelease override or publication is requested.
  • Labels: None, this PR's actual unchanged state. Native .github/workflows/Release.yml uses released PSModule/Release-GHRepository v2.0.3 at 750abed0ecab02394554b610dc3aa191e75e3248, with bare label defaults and AutoPatching, not canonical release: mapping. Prerequisite Module publication verifies ownership before Gallery upload #548 has its separate current-PR Major plus release:major compatibility bridge; it is not copied here, a label migration, or decision-check enforcement. No pin/configuration/label/ruleset changes are made. This draft remains blocked on prerequisite landing, compatible native decision mapping/enforcement, and the required release-decision check rather than treating the legacy Patch default as a Major decision for the combined range.

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
CSS Pass ✅
CSS_PRETTIER Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
HTML Pass ✅
JAVASCRIPT_ES Pass ✅
JAVASCRIPT_PRETTIER Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Release validation allows publishing a tag that mismatches the artifact version, while nondeterministic manifest GUIDs and incorrect PR identity handling can block recovery.

4 open issues
What changed in this PR

This PR adds source-bound publication checks and recovery of the original owned Gallery version before Build. The full diff includes the prerequisite’s breaking standalone-publisher contract; normal reusable-workflow callers retain their existing interface.

Changes:

  • Verify immutable source, producing context, package contents, and release ZIP before publication.
  • Recover proven original versions and complete missing GitHub work without replacing published bytes.
  • Add recovery and failure-path tests, workflow wiring, and caller guidance.
File Description
docs/​content/​guides/​versioning-and-releases.md Documents ownership checks and safe recovery.
.github/​workflows/​Publish-Module.yml Passes resolved tag and immutable source to publication.
.github/​actions/​Resolve-PSModuleVersion/​tests/​Resolve-PSModuleVersion.Recovery.Tests.ps1 Tests ownership-based original-version selection.
.github/​actions/​Resolve-PSModuleVersion/​tests/​Resolve-PSModuleVersion.ReadErrors.Tests.ps1 Tests Gallery errors and malformed metadata.
.github/​actions/​Resolve-PSModuleVersion/​tests/​Resolve-PSModuleVersion.Helpers.Tests.ps1 Replaces numeric-retry expectations with proof requirements.
.github/​actions/​Resolve-PSModuleVersion/​src/​Resolve-PSModuleVersion.Helpers.psm1 Adds recovery selection and stricter Gallery reads.
.github/​actions/​Resolve-PSModuleVersion/​src/​main.ps1 Supplies publication context to resolution.
.github/​actions/​Resolve-PSModuleVersion/​README.md Documents resolver inputs and recovery failures.
.github/​actions/​Release-PSModule/​tests/​Release-PSModule.WhatIf.Tests.ps1 Tests guarded release creation and upload recovery.
.github/​actions/​Release-PSModule/​tests/​Release-PSModule.Ownership.Tests.ps1 Tests ownership, artifact hashing, and archive identity.
.github/​actions/​Release-PSModule/​src/​release.ps1 Rechecks ownership and retains identical release assets.
.github/​actions/​Release-PSModule/​src/​Release-PSModule.Helpers.psm1 Adds shared ownership and artifact-proof helpers.
.github/​actions/​Release-PSModule/​README.md Documents immutable-source and no-replacement contracts.
.github/​actions/​Publish-PSModule/​tests/​Publish-PSModule.TestFixture.psm1 Provides isolated publication APIs and package fixtures.
.github/​actions/​Publish-PSModule/​tests/​Publish-PSModule.Recovery.Tests.ps1 Exercises Gallery-to-GitHub retry compositions.
.github/​actions/​Publish-PSModule/​tests/​Publish-PSModule.Preflight.Tests.ps1 Tests conflict rejection before publication writes.
.github/​actions/​Publish-PSModule/​src/​publish.ps1 Enforces preflight and skips proven duplicate uploads.
.github/​actions/​Publish-PSModule/​src/​Publish-PSModule.Helpers.psm1 Implements publication readers and create-only claims.
.github/​actions/​Publish-PSModule/​README.md Documents standalone requirements and retry constraints.
.github/​actions/​Publish-PSModule/​action.yml Adds required release tag and optional source inputs.

Review effort: Balanced

Comment on lines +973 to +975
$recovered = Get-PSModuleGalleryRecoveryVersion @recoveryParameters
if ($null -ne $recovered) {
return $recovered

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed by the separate bounded investigation: four actual clean builds at the frozen d4b206a/3405467 baseline showed omitted GUID changing only the final manifest GUID, file-tree digest, and canonical ZIP digest; the explicit-GUID control preserved payload identity. Retained original bytes passed frozen read-only preflight and fresh omitted-GUID bytes were rejected. These were not hosted publication recovery or completed framework/consumer module tests. The Build tree is unchanged in this composition.

Leaving this open. An original failed-job retry can reuse surviving original artifacts/settings only when the original runtime already contains the safety behavior and original artifact/completed-test evidence remains verifiable. Current-run/name selection and one-day retention are not immutable original-artifact selection or producing-run/test provenance. Full/new-run/cross-run recovery still requires a separately approved delivery. No Build/GUID/consumer-metadata change, weakened byte check, or original-artifact promotion is implemented here.

Three isolated disappearance/replacement races each reach one Gallery spy write before the guard correction. Two partial-claim controls pass. No live publication is used.

(cherry picked from commit 6254d34)
Recheck the immediately preceding tag SHA after create-only reservation, including a tag first observed after preflight. Retain valid partial-claim completion without recreating a disappeared or replaced observed tag.

(cherry picked from commit 474d094)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical issues allow malformed pull-request context to reach publication writes and retries to bypass existing unpublished claims, alongside a baseline-resolution regression when the version prefix changes.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Resolve baseline releases using their historical tag prefix

.github/​actions/​Resolve-PSModuleVersion/​src/​Resolve-PSModuleVersion.Helpers.psm1:892

For a new source that changes VersionPrefix from v to release-, this lookup requests release-1.2.4 even when the completed baseline was published as v1.2.4. Resolution then reports a Gallery-only gap instead of selecting the normal new-source version release-1.2.5. Check baseline completeness using its actual historical release/tag evidence, while retaining exact configured-prefix binding for recovery and new claims.

3 resolved since last review

Review effort: Balanced

Malformed outer and field arrays are accepted as ownership, and a mismatched ZIP payload reaches Gallery in the isolated real-controller fixture. Preserve raw shape and bind both byte digests before mutation.

(cherry picked from commit 2afb929)
Validate raw producing context and proof shapes before projection. Verify ZIP bytes and payload as one snapshot against the tested tree before claims, Gallery writes, release creation and upload.

(cherry picked from commit e59ac33)
Four isolated cases show unpublished claims bypassed, missing-tag proof misclassified, changed-prefix completed baselines rejected, and ambiguous baseline refs selected. Twelve existing controls remain green.

(cherry picked from commit 136af13)
…lines

Deduplicate immutable alias refs and stop unpublished source claims before selecting another version. Use actual historical tag and release evidence for new-source completeness without changing configured-prefix binding or bump policy.

(cherry picked from commit 3bdda65)
@MariusStorhaug

Copy link
Copy Markdown
Member Author

The summary-only historical-prefix issue in review 5724385048 is addressed by the bounded owner correction at c665a9b. New-source baseline completeness reads the actual historical tag/release instead of constructing it from the current prefix; ambiguous completed historical baselines fail explicitly. Recovery and new claims still bind the configured current prefix, and the configured bump policy is unchanged.

The permanent anonymous v to release- regression and ambiguity rejection pass among all 16 targeted resolver cases; the current Ubuntu action suite passes all 207. This is not full-run original-artifact promotion or final review clearance. GUID/caller provenance, canonical terminal/raw-metadata/Git-ref assessment, native release/source-receipt gates, and the current CI artifact-transport retry remain held.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved validation defects exclude valid legacy tags with digit-containing prefixes and can permit publication or skipped ZIP uploads without confirmed published-release status or well-formed scalar asset proof.

2 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Require existing releases to explicitly set draft to false

.github/​actions/​Publish-PSModule/​src/​Publish-PSModule.Helpers.psm1:506

A release response with draft missing or malformed can pass this check, allowing Gallery publication or a resumed ZIP upload without establishing that the release is published. Require a boolean draft: false, as the historical-baseline path already does. Update successful existing-release fixtures, including Release-PSModule.WhatIf.Tests.ps1, to supply that field.

Medium severity Reject non-scalar release asset proof fields

.github/​actions/​Publish-PSModule/​src/​Publish-PSModule.Helpers.psm1:528

An asset whose raw digest is a singleton JSON array, such as ["sha256:…"], passes this check because the string cast collapses it into a valid checksum. Preflight can consequently authorize Gallery publication or skip the ZIP upload despite malformed published-byte proof. Reject non-scalar asset proof fields before comparison or coercion; the same scalar validation is needed for name and state.

2 resolved since last review

Review effort: Balanced

@MariusStorhaug
Marius Storhaug (MariusStorhaug) marked this pull request as ready for review October 31, 2026 22:38
…ity gaps

Publication spies accept malformed terminal markers and projected API arrays; stable PR provenance is absent, empty verified arrays fail, and valid module names can form invalid Git refs. All experiments are isolated.

(cherry picked from commit 3faf9fb)
Reuse the provenance footer for stable PR releases, preserve raw API object and collection shapes, and share typed immutable tag reads. Escape module-name dots without altering Gallery names or payload metadata.

(cherry picked from commit 8ed2377)
Keep verified empty collections valid and reject projected scalar metadata before source-bound recovery selection.

(cherry picked from commit ae7c333)
Copilot AI balanced review requested due to automatic review settings October 31, 2026 23:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed to evaluate validation gaps that could authorize publication with unverifiable release status or leave a publication claim unable to complete on retry.

2 open issues

Review effort: Balanced

@MariusStorhaug

Copy link
Copy Markdown
Member Author

Reject non-scalar release asset proof fields (review 5725288044)

The exact owner correction at e2e282a rejects raw name, state, and digest fields unless they are strings before checksum comparison. Its hosted suite passes all 231 cases, and three additional anonymous checks against the actual publisher confirm singleton arrays for each field fail before any Gallery/GitHub mutation; this resolves only that summary finding, not the remaining prefix, draft-status, or artifact-provenance holds.

…haracters

Use suffix matching only for candidate discovery and retain exact release, module-version asset and immutable source checks before baseline completeness.

(cherry picked from commit 0281a03)
Reject missing or malformed draft metadata and retain valid published controls. The branch-specific Release WhatIf fixture handback adds only two boolean fields and changes no assertions.

(cherry picked from commit eb3eb0c)
Copilot AI balanced review requested due to automatic review settings November 1, 2026 10:07
@MariusStorhaug

Copy link
Copy Markdown
Member Author

Require existing releases to explicitly set draft to false (review 5725288044)

The exact owner correction at a015792 now requires scalar boolean draft: false before publication or resumed upload. Missing, null, string, and array statuses each reproduced one simulated Gallery write before the fix and now fail with zero writes; existing successful fixtures add only the explicit boolean fields, with assertions and negative cases retained. The full local suite passes 238 tests with one genuine Unix-only Windows skip; current-head hosted checks still need to report, and original-artifact/canonical/native/source-receipt holds are unchanged.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed because release-tag validation, Gallery baseline detection, and ambiguous package metadata can block stable planning or undermine publication recovery.

1 open issue
1 resolved since last review

Review effort: Balanced

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resume source-bound Gallery-only publication on retry

2 participants