Add New-PfbDriftIssue.ps1: reconcile drift findings with GitHub issues (dry run by default) - #158
Merged
juemerson-at-purestorage merged 16 commits intoSep 25, 2026
Conversation
First piece of the drift -> issue reconciler (G2): endpoint normalisation,
endpoint family, ordinal sorting and sha256('<category>|<METHOD /path>|<field>')
fingerprints, pinned by golden values because they are stamped into issues.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
One finding per gap, one fingerprint each. Reads both the string and the object shape of missingQueryParameters and missingBodyProperties, refuses a field that is a stringified object, leaves out readOnlyFields and the systemicGaps aggregate, normalises the dead-key report's split method and path, and stops on a missing category rather than reading it as zero findings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
family:<segment> by default; systemic:<param> once a missing parameter spans three or more families (query and body together), which removes it from the family groups; envelope:, validateset: and deadkey: for the other kinds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> @
The block names an issue's group (or marks it paired) and lists its active and vanished fingerprints. It counts only on an issue labelled source:drift, which only collaborators can apply; anywhere else it is ignored and never throws. On a trusted issue parsing fails closed and names the issue, including a block hidden by an unclosed code fence; a block quoted in a balanced fence is ignored. A rewrite preserves every character outside the block, CRLF and non-ASCII text included, and must parse back to the block it wrote. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fence tracking toggled on any backtick or tilde fence line, so a backtick line inside a tilde fence closed it early and a later real block on a trusted issue read as fenced, returning no marker and inviting a duplicate filing. Tracking now follows CommonMark via Update-PfbDriftFenceState: a fence closes only on a run of the same character at least as long as its opener. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nstant Get-PfbDriftFenceState avoids the state-changing-verb analyzer rule without a suppression. $script:PfbDriftFence has no remaining readers; Task 6 will use the helper instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every body and comment opens with the automation disclaimer; bodies end with the machine block and stay under GitHub's size limit by truncating the table, never the block. Titles are limited to characters that survive the ghx .cmd shim. One area: label per issue, from the group's most severe finding. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An optional **Drift keys:** field (fp:, param:, family:, category:) lets a settled entry stop the reconciler filing a declined finding again. An unrecognised key stops the run instead of silently matching nothing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Tracked > reappeared > settled > declined > regression (reopen:<N>) > append > create, first match wins. Open issues come first so a "still reported after #N" issue is filed once; closed duplicates are ignored; a close with no reason counts as completed; paired legacy issues are never appended to; an issue without source:drift claims nothing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ructure guard One block rewrite and one comment per changed issue; a vanished fingerprint is announced once; an issue with nothing left is labelled status:resolved-upstream in place of its status label, and never closed. The status label is derived from the resulting block on every run, so an append lifts resolved-upstream and a label left wrong by a failed call is fixed next time. More than 25% of recorded fingerprints vanishing in one run aborts the plan. Creates are capped, most severe groups first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…dry run by default) Reads both reports and docs/settled, lists every issue, prints the plan, and writes only with -Apply. Bodies go through --body-file as BOM-less UTF-8, stdout is decoded as UTF-8, the CLI runs from the repo root (ghx resolves identity from there), and every label the plan adds is checked before the first write. Issues whose pfb-drift block was ignored for lack of source:drift are named in a warning. Tested against a fake CLI: a dry run makes no write call; -Apply does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
workflow_dispatch only, dry run unless the apply input is ticked, built-in token with issues: write and nothing else writable, never cancelled mid-run -- each property pinned by a test. Documents status:resolved-upstream in TRIAGE-ROLES.md, the reconciler in tools/README.md, and the reports' new consumer in Reports/README.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A report row whose tuple member was absent or renamed read as '', so distinct rows collapsed onto one garbage fingerprint and were merged without a word (final review I-1, measured: two dead keys with wireKey renamed became one finding 'deadKey|GET /alerts|'). Get-PfbDriftRowValue now reads every member the frozen tuple needs (endpoint, method, wireKey, location, field, from, to, cmdlet, parameter) and throws on an absent or empty one, naming the category, the member and the row. The dead-key report also gains a schema gate: it has never carried a schemaVersion, so one appearing now stops the run instead of being read under the old shape. No golden value moves: the committed reports give the same 1143 fingerprints before and after, byte for byte. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A fingerprint recorded only in a closed issue's vanished list must still be declined (NOT_PLANNED) or filed as a regression (COMPLETED). The code already did this, but the spec-named rule had no test (final review, Task 7). Dropping the vanished term from the closed-issue lookup turns exactly these two tests red on both editions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Invoke-TestRun runs New-PfbDriftIssue.ps1 in-process, so on every CI leg the script appended its tables, 'APPLY' ones included, to the Pester job's own GITHUB_STEP_SUMMARY (final review, Task 9). Each run now points the variable at a file in its fixture directory and restores the previous value, or its absence, in a finally block. Measured with GITHUB_STEP_SUMMARY set to a scratch file around the whole test file: 1976 bytes and 4 APPLY lines written before, 0 after, and the variable holds its original value afterwards, on both editions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Only collaborators can apply the label, but an issue's author can always edit its body and close it, so on an outsider-authored issue the label would vouch for a block the outsider still controls (final review I-2). Say to apply source:drift only to collaborator- or bot-authored issues, and to check the author first, by hand or in the post-merge stamper. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
tools/New-PfbDriftIssue.ps1, which turns the findings inReports/PfbApiDriftReport.jsonandReports/PfbDeadKeyReport.jsoninto GitHub issues and keeps them in step with the reports. It is a reconciler: issues are its only state (a machine block of HTML comments at the end of each drift issue), a re-run over unchanged inputs plans nothing, and it is a dry run unless given-Apply. It never closes an issue.sha256("<category>|<METHOD /path>|<field>")(16 hex, no version component). A report row missing any member of that tuple stops the run rather than producing a colliding fingerprint.family:,systemic:(a parameter missing in 3+ families),envelope:,validateset:,deadkey:, andreopen:<N>for findings still reported after #N closed.docs/settled/entry names in a new optional**Drift keys:**field.source:drift, which only collaborators can apply; a block on anyone else's issue is ignored and named in a warning, so it can neither suppress nor capture findings, nor stop a run. Because an issue's author can always edit and close it,source:driftbelongs only on collaborator-authored issues (documented indocs/TRIAGE-ROLES.md).status:resolved-upstreamin place of its status label, and loses it again when any finding is still reported (documented indocs/TRIAGE-ROLES.md).-MaxCreate, default 10), most severe first, labelledsource:drift,status:triage,needs:live-testand onearea:; every body and comment says automation wrote it..github/workflows/drift-issues.yml:workflow_dispatchonly,applydefaults to false, built-in token withissues: write, no secrets.Adoption -- pairing existing issues with their findings and provisioning the
status:resolved-upstreamlabel -- happens after merge and before the first-Apply.Testing
Tests/PfbDriftIssueTools.Tests.ps1(160) andTests/New-PfbDriftIssue.Tests.ps1(14), plus the approved-verb, import-guard and agent-brief guard files: pwsh 7 218 passed, 0 failed, 0 skipped; Windows PowerShell 5.1 218 passed, 0 failed, 0 skipped.-Applymakes them (the control).deadkey:groups), 138 queued, and exactly two gh calls (issue list,label list) on each edition. The 66 issue bodies containing non-ASCII text decoded cleanly.Live verification
The diff leaves the module source and the manifest entirely untouched, so nothing here can alter a request the module sends or a response it parses. -- the diff is
tools/,Tests/, a workflow and docs only; no line inPublic/,Private/, the manifest or the root module changed, so the usual live-FlashBlade verification does not apply.No version bump and no CHANGELOG change.
🤖 Generated with Claude Code