diff --git a/.memory-bank/activeContext.md b/.memory-bank/activeContext.md index c35e545..6d9356e 100644 --- a/.memory-bank/activeContext.md +++ b/.memory-bank/activeContext.md @@ -9,186 +9,117 @@ source: current task evidence ## Current focus -The maintainer asked on 2026-10-09 at 21:21 UTC to continue with the release-gate -handoffs and to decide and report later. On 2026-10-10 at 09:10 UTC he merged -#116 (rc7, merge commit `8a6be9f`; rc7 is neither tagged nor published). His -`--delete-branch` also deleted the base branch of #117, so GitHub closed #117 -unmerged; nothing is lost (`ai/quality-gate-coverage` is intact at `f11ff41`, -and the merge into `master` is conflict-free by simulation), and a new pull -request replaces it (Next step 1). Handoff 1 (paths) is draft #118 (`83149ee`, -CI green, base `ai/quality-gate-coverage`; rc6 is the latest published -candidate, 4.2.6 the stable Gallery version). Handoff 2 (operating-system -matrix) is draft #119 (`49734ef`, CI green, base `ai/quality-gate-paths`): the -lab `NtfsSecurityOsMatrixLab`, three fixes of the module in two commits -that the matrix found (`962887a`, `fdd7a8b`), the kit, the controller changes, and the -record `Tests/Lab/Acceptance-2026-10-10-os-matrix.md` (Decision 24, proposed). -The final local candidate `fdd7a8b` passes the module's suite on five operating -systems and the host (24 runs, no failure) and the live controller in three -cells of the matrix (1,374 passed, 0 failed, 12 skipped) and in the first lab, -where case 9 runs (245 passed, 0 failed, 1 skipped per edition). Handoff 3: Decision 22 was confirmed -under the delegation and stays proposed; nothing is published. Handoff 4: -Decision 23 (the #34 dossier); the risk acceptance is the maintainer's. The -agent's decisions of the night are D1 to D46 in -`decisions-night-2026-10-09.md` of the session files. Stable 5.0.0 stays gated. +State at 2026-10-10 11:47 UTC: the maintainer integrated the release-gate stack +into `master` (`fa0701b`, CI green at 11:40Z): #116 (rc7, `8a6be9f`), #120 +(`bdb9981`; it replaced #117, which GitHub closed unmerged when the branch +deletion after #116 removed its base, see Decision 15), #118 (`03bef2c`, +handoff 1, the paths), and #119 (`fa0701b`, handoff 2, the operating-system +matrix). The remote head branches are deleted. rc7 is not tagged or published: +rc6 is the latest published prerelease, 4.2.6 the stable Gallery version. rc7 +contains the Phase 2 behavior changes, the path tests and fixes, and the three +module fixes of the matrix (`962887a`, `fdd7a8b`). Stable 5.0.0 stays gated +(Decision 21). -The earlier state of handoff 1, from the reviewed head `f11ff41` of #117: 28 -commits, which the maintainer pushed as draft #118. Every C# method that no test -visits is classified (223 explained, 8 open for the maintainer), and the -other paths have behavior tests. Eleven defects were fixed, ten of them -with a regression guard that is red before the fix and green after it (owner -restore, `InheritedFrom`, a later command that ends the pipeline or throws, -also at the error, verbose, and debug streams, `-Filter` brackets, null, and -`*.*`, public object APIs, a privilege left enabled); the leak of a native -buffer has no observable guard. The lab acceptance of those fixes was repeated -on 2026-10-09 (below); the published package still needs its own acceptance -in gate 3. Decisions 21/22 and stable 5.0.0 -remain gated; Decision 22 is proposed: the agent confirmed all ten choices -on 2026-10-09 under the maintainer's delegation, and his own confirmation is -open. +The maintainer asked on 2026-10-09 at 21:21 UTC to continue with the +release-gate handoffs and to decide and report later. The agent's decisions are +D1 to D47 in `decisions-night-2026-10-09.md` of the session files. Decisions +22 (Phase 2), 23 (the #34 dossier), and 24 (the matrix) are proposed: the agent +confirmed Decision 22 under the delegation, and neither that nor any risk +acceptance is the maintainer's. ## Evidence -- rc6 Release run `37839669028`, attempt 2, succeeded; GitHub prerelease - with zip appeared 2026-10-09 07:01:34 UTC. First attempt proves HTTP 409 - after Gallery publication, not the previously assumed retry chronology. -- #116 was merged into `master` on 2026-10-10 at 09:10:12Z (merge commit - `8a6be9f`, head `d25647d`); rc7 isn't tagged or published. #117 was closed - unmerged at 09:10:16Z (events `base_ref_deleted`, `closed`). -- Local changes: deletion/ownership guards (`a97e46f`); all scopes and - inheritance (`e7ee203`); absolute basic-user results (`51dec86`); - exact-package publication recovery (`95b827e`); first-hidden-item fix - (`d610372`); Force/descriptor guards (`3442194`); SMB regression above. -- Hidden omission was reproduced in all four configurations before the - fix. No parameter/design change. Publication tests are wholly mocked; - exact ordinal SHA-512 identity is required, no real upload occurred. -- At `3442194` (start of Handoff 1): 914 cases per configuration, 2,641/3,559 - sequence points (74.21%), 974/1,933 branches (50.39%), 918 unvisited - points. All skipped templates had executed counterparts. -- Handoff 1 result at `5a5d58b` (frozen Release, four configurations, CI - wrappers, then AltCover): 1,310 cases per configuration, zero failures; - passed/skipped: elevated Desktop 1,286/24, Core 1,255/55; basic Desktop - 1,076/234, Core 1,045/265. Coverage 3,192/3,634 sequence points (87.84%), - 1,273/1,978 branches (64.36%); 231 methods with 442 points stay unvisited, - all classified: 223 explained, 8 open. Skip eligibility was checked by row - from a second full run per configuration: all 578 skipped rows (137 - distinct tests) are executed in two other configurations. -- Mutation rounds on the frozen tree at `5a5d58b`: 26 mutations in four - rounds; 25 are detected by their guard in every configuration where it - runs, and M25 (the check by type, an equivalent mutant) survives as - expected. At `d61dffa` three had escaped (the verbose and debug rows ran - under the CI runner's `Stop`, and an Init test could not fail for its - branch), which led to `f4a16e1`. A first round at `630926f` had let one - mutation escape, which led to the `-Filter` bracket defect. -- Red/green matrix (measured after the last measurement, because the first - red runs were not kept): the final tests of the eight files that guard the - fixes (650 cases per configuration) over the production code of ten states - of the branch, built in Release and run with the focused runner (it sets - `Stop` like the CI wrappers) in the four configurations. 76 rows (73 in the - basic configurations) fail at the base `f11ff41`, each is green at the step - of its fix, none breaks later, and `d44a200` has none (the control). Defect - 9 (the native buffer) has no guard. The matrix does not show that a test was - written before its fix: each fix commit carries both, and the red runs of - that time were not kept. -- Review: custom `security-reviewer` could not start (model unavailable); the - built-in read-only `code-review` agent made nine static passes: no Blocker - or Major; its Minor findings led to the `*.*`, help, test, later-command, - error-stream, and privilege fixes. Report: - `Tests/Coverage/Quality-Gate-Paths-2026-10-09.md` with an appendix of - explanations and CSV rows; raw evidence is in the session folder - `4b12e2f4-d4c7-4a5d-883a-ddb7421c4848\files\qg-paths`. -- Live packaged candidate, 09:20 to 09:51 UTC: 330 passed, zero failed, - two expected Server-module skips. Published rc6: 326 passed, four - expected failures (Hidden and rc7 warning text in each edition), two - skips. Tested folder and all 11 ZIP files are byte-identical. -- Temporary host result verifier failed on Desktop JSON wrapping/full - test names; corrected verification passed on unchanged raw results in - both editions. Cleanup wrapper's broad Error.Count was not acceptance - proof. Independent probes verified all fixture objects/members/profiles - gone from six machines. Raw failing markers and corrected evidence kept. -- Review of the lab candidate: one read-only independent code review - approved, high confidence, no significant findings or confirmed exploit. -- Six checkpoints exist but report Standard, even after a successful - temporary ProductionOnly probe; policy restored, no restore performed. - Do not claim verified Production rollback evidence. -- Lab acceptance of the paths fixes, 20:41 to 21:42 UTC on 2026-10-09: the - candidate `83149ee` and its base `f11ff41` ran the same 244 tests per - edition (78 new, case 10) from their extracted packages. Candidate 486 - passed, 0 failed, 2 expected skips; baseline 338 passed, 148 failed, each - green on the candidate; both editions gave the same counts. Fixture removal - verified by a separate read-only check in four domains and on both file - machines; six checkpoints (Standard type, no restore). Record, results CSV, - and limits: `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`. This - covers the gate-3 handoff table of the path report, except the published - package and the other operating systems. -- Wider matrix not deployed: 13 Server 2025 VMs; Windows 11/2019/2022 - media present, OS detection cache empty. #34 has no reply since Oct 6. -- Full evidence: session artifact `quality-gate-3442194-20261009`; - repository report `Tests/Lab/Acceptance-2026-10-09-quality-gate.md`. -- Operating-system matrix, 2026-10-10 (record `Tests/Lab/Acceptance-2026-10-10-os-matrix.md` - with CSV tables): the suite of the final candidate `fdd7a8b` on OSFile19, - OSFile22, OSFile25, OSWin11E, OSWin11, and the host, four configurations each, - zero failures, skipped tests identical to the host's; the baseline `83149ee` - (run on OSFile22 and OSFile25) fails 4 elevated and 20 basic-user tests. Live: run - `rc7l`, three cells, 1,374 passed, 0 failed, 12 skipped. First lab (run `fl1`, - case 9 included, both editions): 245 passed, 0 failed, 1 skipped per edition, - fixture removed and verified clean. The Admin-role - effective-access failures of the earlier cells were not the module: in a replay - (`ab0` to `ab6`) the baseline failed two of three cells and the final candidate - one of three (not counting the warm-up `ab0`), and one model (the remote - authorization managers answer for an account name for about ten minutes after - the account was created again) fits all 43 Admin-role runs of 27 cells; the - Windows mechanism is unknown. The controller now names the account of case 3 - anew for each fixture (`1dec389`); four more cells with it (`ab7` to `ab10`) - passed, two of them where the model predicts a failure for a reused name. - Reviewed by the built-in code-review agent (custom `security-reviewer` - unavailable): approve with Minor, fixed; a second review found one Major - (record accuracy), addressed by the replay; a follow-up review found no - Blocker or Major and five Minors, corrected; a second follow-up review found no - Blocker or Major and four Minors, corrected. The built-in `security-review` - agent (the custom reviewer is still unavailable) found no exploitable - vulnerability in the module changes and two LOW items that are not changed - (Next step 6). A dry run of `Run-MatrixSequence.ps1 -Version 5.0.0-rc6` on - OSFile19 showed that the published-package path works. State of the labs at - 07:50 UTC on 2026-10-10: no fixture and no probe residue in either lab - (`Verify` of the matrix lab 07:45, of the first lab 07:29); the six VMs of the - matrix run, and `OSWin11E` (restarted 07:36) shuts itself down about an hour - after its start. +- rc6 Release run `37839669028`, attempt 2, succeeded; GitHub prerelease with + zip appeared 2026-10-09 07:01:34 UTC. The first attempt proves HTTP 409 + after Gallery publication, not the earlier assumed retry chronology. +- Integration on 2026-10-10 (UTC): #116 merged 09:10, #117 closed unmerged + 09:10:16 (events `base_ref_deleted`, `closed`), #120 merged 10:50, #118 + 11:12, #119 11:28, head branches deleted 11:34, CI on `master` at `fa0701b` + green 11:40. A `git merge-tree` simulation of the chain was conflict-free and + ended in the tree of the matrix branch. +- Handoff 1 (paths), measured at `5a5d58b` (frozen Release, four configurations, + CI wrappers, then AltCover): 1,310 cases per configuration, zero failures + (baseline `3442194`: 914 cases); coverage 3,192/3,634 sequence points + (87.84%) and 1,273/1,978 branches (64.36%), against 74.21% and 50.39%. All 231 + methods with 442 unvisited points are classified: 223 explained, 8 open for + the maintainer. Skip eligibility was checked by row: all 578 skipped rows + (137 distinct tests) are executed in two other configurations. +- Eleven defects were fixed, ten with a guard that is red before the fix and + green after it (a red/green matrix over ten states of the branch: 76 rows + red at the base `f11ff41`, none after the last fix; the leak of a native + buffer has no guard). Mutation rounds at `5a5d58b`: 25 of 26 detected, M25 + (the check by type) an equivalent mutant. The matrix doesn't show that a test + preceded its fix: each fix commit carries both. Report: + `Tests/Coverage/Quality-Gate-Paths-2026-10-09.md`. +- Reviews: the custom `security-reviewer` can't start (its model is + unavailable; no override). The built-in `code-review` agent made nine static + passes of the paths work (no Blocker or Major) and four rounds on the matrix + (one Major, record accuracy, resolved by the replay; Minors corrected); the + built-in `security-review` agent found no exploitable vulnerability and two + LOW items left for the maintainer (Next step 5). +- Live candidate of 2026-10-09 (09:20 to 09:51 UTC): 330 passed, 0 failed, 2 + expected skips; published rc6: 326 passed, 4 expected failures, 2 skips; the + 11 tested files match the ZIP. Independent probes verified the fixture + removal on six machines (`Tests/Lab/Acceptance-2026-10-09-quality-gate.md`). +- Six checkpoints report Standard even after a successful ProductionOnly probe; + policy restored, no restore performed: don't claim verified Production + rollback evidence. +- Lab acceptance of the paths fixes, 2026-10-09 20:41 to 21:42 UTC: candidate + `83149ee` against its base `f11ff41`, the same 244 tests per edition (78 + new): 486 passed, 0 failed, 2 expected skips against 338 passed, 148 failed + (each green on the candidate); fixture removal verified. Record: + `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`. +- Operating-system matrix, 2026-10-10 (record + `Tests/Lab/Acceptance-2026-10-10-os-matrix.md` with CSV tables): the suite of + the final candidate `fdd7a8b` passes on OSFile19/22/25, OSWin11E, OSWin11, and + the host (24 runs, no failure; the baseline `83149ee` fails 4 elevated and 20 + basic-user tests on OSFile22 and OSFile25); the live controller passes in + three cells (1,374 passed, 0 failed, 12 skipped) and in the first lab with + case 9 (245 passed, 0 failed, 1 skipped per edition; fixture removed and + verified). The Admin-role effective-access failures in earlier cells were + stale account state, not the module: in a replay the baseline failed two of + three cells and the candidate one, and one lifetime of about ten minutes fits + 43 runs of 27 cells (the Windows mechanism is unknown). The controller names + the case-3 account anew for each fixture (`1dec389`); four more cells with it + passed. A dry run of `Run-MatrixSequence.ps1 -Version 5.0.0-rc6` showed that + the published-package path works. Labs at 07:50 UTC on 2026-10-10: no fixture + or probe residue; `OSWin11E` shuts itself down an hour after its start. +- Raw evidence is outside git: the session folder + `4b12e2f4-d4c7-4a5d-883a-ddb7421c4848\files` (`qg-paths`, the matrix runs, the + night log) and + `26f151b6-e46f-49bd-9398-b27e20603949\files\quality-gate-3442194-20261009`. ## Next step -1. The maintainer integrates the rest of the stack (Decision 15; commands in - the deployment notes). A **new** pull request from `ai/quality-gate-coverage` - to `master` replaces #117; then #118 and, if its module fixes go into rc7, - #119 are retargeted with `gh pr edit --base master`, marked ready, and - merged. No `--delete-branch` while another open pull request uses the branch - as its base; the head branches are deleted last. He decides which module - fixes of the matrix branch belong to rc7 (two commits: `962887a` holds two - fixes, `fdd7a8b` one) and reviews them (Decision 24). -2. He decides the open items listed in the paths report: `FileSecurity` - conversions, `RemoveAll` account filters, lazy path overloads, abandoned +1. The maintainer tags `fa0701b` as `5.0.0-rc7` and pushes the tag; the + `release` job then publishes to the Gallery and GitHub after the approval of + the `powershell-gallery` environment (deployment notes). Every release step + is his. +2. Gate 3, after rc7 is on the Gallery (the agent runs it on request): + `Test-PublishedRelease.ps1 -Version 5.0.0-rc7`, the live controller with + `-Version` in the first lab, and `Run-MatrixSequence.ps1 -Version 5.0.0-rc7` + for every cell (deployment notes, "Accept a published package"). Open: keep + or replace the matrix VMs (about 60 GB) and the evaluation client (it shuts + down every hour), and a domain cell for Windows 11 26H1, whose client loses + the secure channel to the Server 2025 domain controller. +3. He decides the open items of the paths report: `FileSecurity` conversions, + `RemoveAll` account filters, lazy path overloads, abandoned `PrivilegeEnabler`, dot patterns of `Get-ChildItem2 -Filter`, the 17 owner-restore handlers without the later-command check, unused classes - (Decisions 21/22). -3. Gate 3: accept the published package in the first lab and in every cell of - the matrix (`Run-MatrixSequence.ps1 -Version`) before the candidate counts as - accepted; no local upload. The paths fixes were accepted locally (record - above). -4. Retain stacked-PR order (15): #116 (merged), the replacement of #117, #118, - then #119; a simulated merge in that order gives exactly the tree of the - matrix branch (`62aa1ae`). Confirm or change Decision 22. -5. #34 stays open (Decision 23): the maintainer chooses between waiting for a - test of the published candidate on the NetApp, EMC, and IBM ESS servers of - the reporters (checklist: `Tests/Lab/Non-Windows-File-Server-Test.md`) and - accepting the untested risk with a release-note caveat. No agent can - accept it. -6. He decides the two LOW findings of the security review (record, Limits): + (Decisions 21/22). He also confirms or changes the proposed Decisions 22 and + 24. +4. #34 stays open (Decision 23; no reply since 2026-10-06): the maintainer + chooses between waiting for a test of the published candidate on the + NetApp, EMC, and IBM ESS servers of the reporters (checklist: + `Tests/Lab/Non-Windows-File-Server-Test.md`) and accepting the untested + risk with a release-note caveat. No agent can accept it. +5. He decides the two LOW findings of the security review (record, Limits): the swallowed initialization errors of `GetEffectiveAccess` (a false "no - access" instead of an error on an OS that refuses at initialization, and - neither warning nor error when the local fallback fails; fix: record the - initialization exceptions in `authzException`, with a regression test and a - check of the sentence "the error stays" in the help and CHANGELOG), and the - ACL of the stage folders under `C:\` in the lab kit (they inherit - Authenticated Users: Modify; protecting them is a design change of the - controller and needs a new acceptance). The help could also say that a local - standard user who asks about a domain account still gets "Access is denied". -7. Do not release stable 5.0.0 or equate a percentage with gate closure. + access" instead of an error on an OS that refuses at initialization; fix: + record the exceptions in `authzException`, with a regression test and a + check of "the error stays" in the help and CHANGELOG), and the ACL of the + stage folders under `C:\` in the lab kit (they inherit Authenticated Users: + Modify; protecting them is a design change of the controller and needs a new + acceptance). The help could also say that a local standard user who asks + about a domain account still gets "Access is denied". +6. Do not release stable 5.0.0 or equate a percentage with gate closure. diff --git a/.memory-bank/decisions/0015-merge-stacks-with-merge-commits.md b/.memory-bank/decisions/0015-merge-stacks-with-merge-commits.md index 45c6db6..4858f0d 100644 --- a/.memory-bank/decisions/0015-merge-stacks-with-merge-commits.md +++ b/.memory-bank/decisions/0015-merge-stacks-with-merge-commits.md @@ -16,4 +16,15 @@ source: maintainer decision of 2026-10-05 pull request would conflict, and the commit IDs in the descriptions and the changelog would no longer exist on `master`. A merge commit keeps them, and each merge leaves `master` at the tree its pull request tested. -- Applied: 5.0.0-rc2, the PRs #99 to #106 on 2026-10-05. +- Applied: 5.0.0-rc2, the PRs #99 to #106 on 2026-10-05; 5.0.0-rc7, the PRs + #116, #120, #118, and #119 on 2026-10-10. +- Operating rule (2026-10-10): retarget each pull request of the stack to + `master` (`gh pr edit --base master`) before the one below it is merged, + and delete a head branch only when no open pull request uses it as its base. + Deleting a base branch through the GitHub CLI closed #117 without a merge: + GitHub did not retarget it. The open reports cli/cli#1168 and cli/cli#14223 + show the same events (the first says that the button on the pull request + page retargets, the second quotes a maintainer who sees a platform issue) and + report that a closed pull request can't be retargeted or reopened while its + base is missing (not tried here). #120, a new pull request from the same + head, replaced #117. Nothing was lost; no content conflicted. diff --git a/.memory-bank/deployment-notes.md b/.memory-bank/deployment-notes.md index 681e479..6c2d106 100644 --- a/.memory-bank/deployment-notes.md +++ b/.memory-bank/deployment-notes.md @@ -9,55 +9,35 @@ source: release gates of 5.0.0 (lab acceptance, OS matrix, publication plan), re ## Publish the next prerelease (rc7) -State on 2026-10-10 at 09:59 UTC: #116 (rc7, head `d25647d`) is merged into -`master` (merge commit `8a6be9f`, 09:10:12Z). #117 (head `f11ff41`, base -`ai/release-5.0.0-rc7`) was **closed without a merge** at 09:10:16Z: the -`--delete-branch` of `gh pr merge 116` deleted its base branch, and GitHub -closed it (events `base_ref_deleted`, then `closed`) instead of retargeting it. -Nothing is lost: `ai/quality-gate-coverage` is intact at `f11ff41`, and -`master` still lacks its change (25 files). #118 (draft, head `83149ee`, base -`ai/quality-gate-coverage`) and #119 (draft, head `49734ef`, base -`ai/quality-gate-paths`) are open and green. A simulated merge chain -(`git merge-tree --write-tree`, no ref written) with merge commits -(Decision 15) is conflict-free at every step: the coverage branch into `master` -gives the tree of `f11ff41`, #118 then gives `b1dc006`, and #119 gives -`62aa1ae`, the tree of the matrix branch. The manifest says `5.0.0` with -`Prerelease = 'rc7'`, and `$publishedVersions` in `Tests/Repository.Tests.ps1` -lists the versions up to rc6, as it must before rc7 is published. +State on 2026-10-10 at 11:47 UTC: the whole stack is merged into `master`, +which stands at `fa0701b` and has the tree of `2b8643f`: #116 (rc7, `8a6be9f`, +09:10Z), #120 (`bdb9981`, 10:50Z), #118 (`03bef2c`, 11:12Z), and #119 +(`fa0701b`, 11:28Z). #117 had been closed without a merge at 09:10:16Z, when +the branch deletion after the merge of #116 removed its base branch (Decision +15, operating rule); #120, a new pull request from its head `f11ff41`, +replaced it. The remote head branches were deleted at 11:34Z. The CI run on +`master` at `fa0701b` passed at 11:40Z (Build and test, Wiki, Publish the +wiki; Release skipped, as for any push without a tag). The manifest says +`5.0.0` with `Prerelease = 'rc7'`, and `$publishedVersions` in +`Tests/Repository.Tests.ps1` lists the versions up to rc6, as it must before +rc7 is published. The release notes of a prerelease are the `[Unreleased]` +section of `CHANGELOG.md`. -The branch `ai/quality-gate-lab-matrix` (draft #119) is stacked on #118. It -holds three fixes of the module in two commits (`962887a` has two, `fdd7a8b` -one). `fdd7a8b` reverts cleanly on its own; `962887a` doesn't -revert while `fdd7a8b` stays (the two conflict in `Security2/Win32/Lib.cs` and -`CHANGELOG.md`), and its two fixes go together. The branch also holds the kit of the -operating-system matrix, the changes of the live controller, and the record -(Decision 24). rc7 contains the module fixes only if the branch is merged after -#118 and before the tag; otherwise they go to the next prerelease. The -maintainer decides. +rc7 contains everything that is merged: the behavior changes of Phase 2 +(#116), the quality-gate paths (#120, #118), and the three module fixes of +the matrix (#119, in two commits: `962887a` holds two, `fdd7a8b` one; they +don't revert separately, because they conflict in `Security2/Win32/Lib.cs` and +`CHANGELOG.md`), with the kit, the controller changes, and the record of the +operating-system matrix (Decision 24). -Do not delete a head branch while another open pull request uses it as its -base. On 2026-10-10 the deletion through `gh pr merge --delete-branch` closed -#117 instead of retargeting it. The open reports `cli/cli#1168` and -`cli/cli#14223` show the same two events and say that GitHub retargets only -when the branch is deleted with the button on the pull request page. The -latter also reports, and this was not tried here, that `gh pr edit --base` -refuses a closed pull request and that `gh pr reopen` refuses while the base -branch is missing. A new pull request from the same head is the repair. - -1. Open a new pull request from `ai/quality-gate-coverage` to `master` (it - replaces #117, same head and title), wait for its CI, and merge it with - **Create a merge commit**. Do not delete the branch yet. -2. Retarget #118 (`gh pr edit 118 --base master`), mark it ready, and merge it - the same way. Then do the same for #119 if its module fixes go into rc7. - A retarget doesn't start CI again (`pull_request` in `ci.yml` has the - default event types), and the merge result is the tree that CI tested. -3. Delete the head branches only after the last pull request that uses one as - its base is merged or retargeted. -4. Tag the merge commit on `master` with `5.0.0-rc7` and push the tag. The - `release` job checks the tag against the manifest and builds nothing new: - it publishes the package that the `build` job tested. Approve the - deployment of the `powershell-gallery` environment if it asks. -5. After the publication, add `5.0.0-rc7` to `$publishedVersions` with the +1. Tag the commit `fa0701b` on `master` with `5.0.0-rc7` and push the tag + (lightweight tags, as for rc1 to rc6). The `release` job checks the tag + against the manifest and builds nothing new: it publishes the package that + the `build` job tested. Approve the deployment of the `powershell-gallery` + environment if it asks. +2. Accept the published package (next section): `Test-PublishedRelease.ps1`, + the first lab, and every cell of the matrix. +3. After the publication, add `5.0.0-rc7` to `$publishedVersions` with the next change that goes to `master`. ## Accept a published package @@ -163,9 +143,15 @@ Local `-ModulePath` runs are validation; the gate needs the published bytes. logons returned the old account on the domain controller and member servers for 7 to 15 minutes. The five remedies tried (a ticket purge, `nltest /sc_reset`, a DNS flush, a restart of the Kerberos service, and waiting) helped only by - waiting (see `techContext.md`). The controller names the account of case 3 anew - for each new fixture; a script of your own that recreates accounts needs unique - names too. + waiting. A model with one lifetime (9.95 to 10.25 minutes) fits all 43 + Admin-role runs of 27 cells; the replay and the model are in the record of the + matrix and in Decision 24. The controller names the account of case 3 anew + for each new fixture; a script of your own that recreates accounts needs + unique names too. +- `Wait-LabVM` waits for a heartbeat that a client may not report: retry + `New-LabPSSession` instead of waiting longer. After an unplanned shutdown, + test a domain session, not `nltest /sc_verify` (it stays stale), and repair + with `Test-ComputerSecureChannel -Repair`. - Restart the evaluation client (`OSWin11E`) right before a sequence or a suite, not before several: it shuts down an hour after each start. The restart takes about two and a half minutes and may need the repair of the secure channel. diff --git a/.memory-bank/progress.md b/.memory-bank/progress.md index ae7ccbf..0f2f529 100644 --- a/.memory-bank/progress.md +++ b/.memory-bank/progress.md @@ -9,17 +9,13 @@ source: repository and validation evidence ## Current status -5.0.0-rc6 is published on the Gallery and GitHub; its failed Release job -recovered in attempt 2 on 2026-10-09. #116 (rc7, `d25647d`) was merged into -`master` on 2026-10-10 (`8a6be9f`); rc7 is neither tagged nor published. #117 -was closed unmerged when its base branch was deleted, so a new pull request -from `ai/quality-gate-coverage` replaces it. Further quality-gate work is -`ai/quality-gate-paths` (draft #118), which classifies every remaining -unvisited path (the open items are the maintainer's decisions), and -`ai/quality-gate-lab-matrix` (draft #119, stacked on #118): the -operating-system matrix, three fixes of the module found by it, and the -controller changes (Decision 24, proposed). -Stable Gallery version: 4.2.6. +5.0.0-rc6 is published on the Gallery and GitHub (its failed Release job +recovered in attempt 2 on 2026-10-09). On 2026-10-10 the maintainer merged the +whole stack into `master` (`fa0701b`, CI green): #116 (rc7), #120 (it replaced +#117, which GitHub closed unmerged when the branch deletion after #116 removed +its base), #118 (the quality-gate paths), and #119 (the operating-system +matrix with three module fixes, Decision 24 proposed). rc7 is not tagged or +published. Stable Gallery version: 4.2.6. After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). ## Recent milestones @@ -50,75 +46,47 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). Published rc6 live tests differed only in rc7's warning expectation. - 2026-10-09: release attempt 2 succeeded; rc6 GitHub prerelease and zip appeared at 07:01:34 UTC. #116 passed CI on `d25647d`. -- 2026-10-09: autonomous follow-up on `ai/quality-gate-coverage`, through - `3442194`, adds 202 cases above rc7: deletion/owner failures, all 13 - scopes, inheritance transitions, enumeration, forced replacement, - descriptor failures, and offline CI recovery. Reproduced/fixed rooted - result-path handling and first-hidden-item omission. Publication recovery - verifies exact SHA-512 identity, not merely version existence. -- 2026-10-09: final uninstrumented suite: 914 per configuration, zero - failures; coverage: 2,641/3,559 sequence points (74.21%) and 974/1,933 - branches (50.39%), aggregate of four runs without AltCover `--save`. - All skipped templates have executed counterparts. Mutation guards were - proved and production source restored; Release build/checks pass. -- 2026-10-09: live comparison, 09:20 to 09:51 UTC: candidate 330 passed, - zero failed, two expected skips; published rc6 four expected Hidden/ - warning-text failures only. Independent cleanup probes verified fixture - absence; raw host-verifier failures retained with corrected verification. - Lab guards/acceptance committed in `7594e0c`. One independent code review - approved with no significant finding (custom model unavailable; built-in - fallback). All 11 tested files match the ZIP. OS/path gates stay open. -- 2026-10-09: Handoff 1 on `ai/quality-gate-paths` (28 local commits, no - push): suite 914 to 1,310 per configuration, zero failures; coverage - 3,192/3,634 sequence points (87.84%), 1,273/1,978 branches; all 231 - unvisited methods classified (223 explained, 8 open). Eleven defects - fixed, ten with a guard that is red before the fix and green after it (a - red/green matrix over ten states of the branch: 76 rows red at the base, - none after the last fix), among them a later command's exception that - cmdlets swallowed (a `throw` made `Remove-Item2` remove the next item; also - through the error stream) and a privilege left enabled. Nine static - passes of the built-in code-review agent: no Blocker or Major. Report in - `Tests/Coverage`. -- 2026-10-09: lab acceptance of those fixes, `83149ee` against its base - `f11ff41` with the same 244 tests per edition (78 new, case 10): candidate - 486 passed, 0 failed, 2 expected skips; baseline 338 passed, 148 failed, all - 148 green on the candidate; fixture removed and verified clean on six - machines. Record: `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`. +- 2026-10-09: autonomous follow-up on `ai/quality-gate-coverage` (#117, then + #120), through `3442194`: 202 cases above rc7 (deletion/owner failures, all + 13 scopes, inheritance transitions, enumeration, forced replacement, + descriptor failures, offline CI recovery); fixed rooted result paths and the + first-hidden-item omission; publication recovery verifies the exact SHA-512 + identity, not merely the version. Suite: 914 per configuration, zero + failures; 2,641/3,559 sequence points (74.21%), 974/1,933 branches (50.39%). + Live comparison, 09:20 to 09:51 UTC: candidate 330 passed, 0 failed, 2 + expected skips; published rc6 only its four expected failures (`7594e0c`). +- 2026-10-09: handoff 1 (#118): suite 914 to 1,310 per configuration, zero + failures; 3,192/3,634 sequence points (87.84%), 1,273/1,978 branches; all 231 + unvisited methods classified (223 explained, 8 open). Eleven defects fixed, + ten with a guard that is red before the fix and green after it (76 rows red + at the base), among them a later command's exception that cmdlets swallowed + (a `throw` made `Remove-Item2` remove the next item) and a privilege left + enabled. Lab acceptance, `83149ee` against `f11ff41`: 486 passed, 0 failed, 2 + expected skips against 338 passed, 148 failed. Report in `Tests/Coverage`; + record `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`. - 2026-10-09 to 10: handoffs 2 to 4 under the maintainer's delegation (decisions - D1 to D46 in the night log of the session files). The matrix lab - `NtfsSecurityOsMatrixLab` (Server 2019, 2022, and 2025 file servers, Windows 11 - Enterprise 22H2 client, Windows 11 26H1 suite only) found three defects of the - module, fixed in `962887a` and `fdd7a8b`: audit inheritance by descriptor, - `Get-NTFSEffectiveAccess -ServerName ''`, and the same cmdlet for a user who - isn't an administrator on a domain member. The final candidate passes the - module's suite on every machine (24 runs, no failure) and the live controller - in three cells (1,374 passed, 0 failed, 12 skipped) and in the first lab with - case 9 (245 passed, 0 failed, 1 skipped per edition). The failures of the - effective-access tests in the Server 2022 cell were not a defect of the module: - in a replay of the same cells the baseline failed two of three and the final - candidate one of three (not counting the warm-up cell), and one model (the - remote authorization managers answer for an account name for about ten minutes - after the account was created again) fits all 43 Admin-role runs of 27 cells; - the Windows mechanism is unknown. The controller - names the account of case 3 anew for each fixture (`1dec389`). A read-only - built-in review of the kit and the fixes approved with Minor findings, fixed in - `db04ef2`. A second review of the later commits found one Major (the record - called the cause settled without a baseline replay), addressed by the replay, - `9344ff7`, and `ab0d8e1`; a follow-up review of those fixes found no Blocker or - Major and five Minors, corrected in `e2384e5` and `70f494a`; a second - follow-up review (the first-lab run and the cleanup changes) found no Blocker or - Major and four Minors, corrected in `b78784d` and `dbb4bd6`; the built-in - `security-review` agent found no exploitable vulnerability and two LOW items - that are not changed (record, Limits). Record: - `Tests/Lab/Acceptance-2026-10-10-os-matrix.md`; the agent pushed nothing. -- 2026-10-10: the maintainer merged #116 (`8a6be9f`, 09:10:12Z) with `gh pr - merge --delete-branch` and pushed the matrix branch as draft #119 (`49734ef`). - The deletion removed the base branch of #117, and GitHub closed #117 - unmerged three seconds later instead of retargeting it (events - `base_ref_deleted`, `closed`; the same pair is in `cli/cli#14223`). The - earlier guidance, which relied on a retarget, was wrong. Nothing is lost; a - new pull request from `ai/quality-gate-coverage` replaces #117 (deployment - notes). + D1 to D47 in the night log of the session files). The matrix lab + `NtfsSecurityOsMatrixLab` (Server 2019, 2022, 2025, a Windows 11 Enterprise + 22H2 client, Windows 11 26H1 suite only) found three module defects, fixed in + `962887a` and `fdd7a8b`: audit inheritance by descriptor, + `Get-NTFSEffectiveAccess -ServerName ''`, and the same cmdlet for a + non-administrator on a domain member. The final candidate passes the module's + suite on every machine (24 runs), the live controller in three cells (1,374 + passed, 0 failed, 12 skipped), and the first lab with case 9 (245 passed, 0 + failed, 1 skipped per edition). The Server 2022 effective-access failures + were stale account state, not the module (a replay; the Windows mechanism is + unknown); the controller names the case-3 account anew (`1dec389`). Built-in + reviews: Minors corrected, one Major resolved by the replay, no Blocker; the + built-in security review found no exploitable vulnerability and two LOW items + left for the maintainer. Record: + `Tests/Lab/Acceptance-2026-10-10-os-matrix.md`. +- 2026-10-10: the maintainer integrated the stack. His branch deletion after the + merge of #116 (`8a6be9f`, 09:10:12Z) removed the base branch of #117, and + GitHub closed #117 unmerged three seconds later instead of retargeting it + (`cli/cli#14223` shows the same events); the earlier guidance that relied on a + retarget was wrong. Nothing was lost: #120 (`bdb9981`, 10:50Z) replaced #117, + then #118 (`03bef2c`, 11:12Z) and #119 (`fa0701b`, 11:28Z) merged after their + retargeting; CI on `master` passed at 11:40Z. Decision 15 has the rule. ## Stable capabilities @@ -131,11 +99,11 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). ## Open work -1. Decision 21 gate: review Decision 22, integrate reviewed quality-gate - follow-up, publish the next candidate, and test the published package. - Do not release 5.0.0 until the remaining-path and OS-matrix gates close. - Release steps: `Docs/Contributing/05-Releasing.md`; remove prerelease - label, date `[5.0.0]`, update `$publishedVersions`, tag through CI. +1. Decision 21 gate: tag and publish rc7, then test the published package + (first lab, every matrix cell) and review Decision 22. Do not release 5.0.0 + until the remaining-path and OS-matrix gates close. Release steps: + `Docs/Contributing/05-Releasing.md`; remove the prerelease label, date + `[5.0.0]`, update `$publishedVersions`, tag through CI. 2. Issues: #110's seven items were addressed by rc6, but #115 deliberately used no closing keyword. #34 stays open for non-Windows owner feedback or maintainer acceptance. #16, #21, #45, #89 await reporters. #68 tracks @@ -164,17 +132,13 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). write's ownership retry cannot run on a local volume and is covered only by the lab. A conditional ACE display remains a .NET representation limit, not evidence of unconditional permissions. -8. Publication recovery is implemented locally in `95b827e`, with 14 offline - tests and exact artifact SHA-512 verification. Original upload errors - remain errors for missing/different/unverifiable outcomes. Not deployed - until the maintainer merges/pushes; no publication was performed here. +8. Publication recovery (`95b827e`, merged in #120): 14 offline tests and exact + artifact SHA-512 verification; the original upload errors remain errors for + missing, different, or unverifiable outcomes. The agent published nothing, + so the recovery has never run against the Gallery. 9. Operating-system matrix (Decision 24, proposed): the lab and the cells exist - and the final local candidate passes them. Open: the acceptance of the - published rc7 in every cell, keeping or replacing the VMs (about 60 GB) and - the evaluation client (it shuts down every hour), which module fixes go to - rc7, and a domain cell for Windows 11 26H1. #34 has no new reply since - 2026-10-06. -10. Lab rollback evidence: new checkpoints exist but report Standard even - after a successful temporary ProductionOnly probe. Classification is - unresolved; original VM policy restored, no checkpoint restored. Do - not represent these as verified Production snapshots. + and the candidate passes them; the published rc7 still needs its acceptance + in every cell. #34 has no new reply since 2026-10-06. +10. Lab rollback evidence: new checkpoints report Standard even after a + successful temporary ProductionOnly probe; original VM policy restored, no + checkpoint restored. Don't represent them as verified Production snapshots. diff --git a/.memory-bank/systemPatterns.md b/.memory-bank/systemPatterns.md index 8372541..7beb0f0 100644 --- a/.memory-bank/systemPatterns.md +++ b/.memory-bank/systemPatterns.md @@ -1,6 +1,6 @@ --- status: current -last-verified: 2026-10-09 +last-verified: 2026-10-10 owner: active-agent source: repository and regression evidence --- @@ -66,82 +66,43 @@ Read only task-relevant records; the index controls routing. - Pipeline getters never throw; per-item errors name input and allow continuation. - Folder moves never use CopyAllowed; preserve cross-volume source folders. - Apply implied Hidden/Force before deciding to emit, including the first item. -- A catch-all for the failures of one item must pass on what a later command - raises through a Write call. A downstream throw is an ordinary exception, - so a type check finds only the end of the pipeline, break, and continue. - BaseCmdlet notes the exception that its WriteObject, WriteError, - WriteVerbose, and WriteDebug raised (WriteWarning is not noted: no catch-all - encloses it); `IsFromLaterCommand` recognizes it, and the type check - `PipelineControl.IsEnd` backs it up for other calls into PowerShell. A write - inside a helper, such as the owner restore of `InvokeAsOwner`, is an - accepted gap: its handler reports the item's own error, which raises too. - Prefer writing outside the try. `Tests/PipelineControl.Tests.ps1` has rows - for every cmdlet: add a row for a new one, and keep the typed-throw rows - (they fail if PowerShell stops wrapping a thrown exception). -- Record an enabled privilege before the next write, which a later command - can answer with an exception: Dispose disables only what is recorded. -- `Get-ChildItem2 -Filter` has two matchers: the AlphaFS enumeration, whose - dot rules also differ from those of `Get-ChildItem` (probe: `Report.*` and - `Rep*.` in both editions), and a PowerShell wildcard on the name, where only - `*` and `?` are special. `*.*` is treated as `*`; the other dot patterns are - pinned by `ItemCmdlets.Tests` and are an open maintainer decision. +- A catch-all for one item's failures passes on what a later command raises + through a Write call (`IsFromLaterCommand`, `PipelineControl`; see + `BaseCmdlets.cs`); add a row to `Tests/PipelineControl.Tests.ps1` for a new + cmdlet. Record an enabled privilege before the next write. +- `Get-ChildItem2 -Filter` has two matchers (AlphaFS, then a wildcard on the + name); `*.*` means `*`, other dot patterns are an open decision. ### Tests and documentation - Tests import Release in isolated processes, both editions and privilege - modes. File/ACL/link fixtures use shared sandbox guards and cleanup. - Privilege-dependent skips must have eligible counterparts in the matrix. + modes, with guarded sandboxes; a skip needs an eligible counterpart. - Assert persisted state, errors/targets, continuation, and no failed - PassThru output. Prove new characterization guards with bounded mutations; - restore source exactly and rebuild before green validation or packaging. - Apply the mutations of one round together only when no guard can fail - because of another mutation; otherwise split the rounds. -- A test that arranges a retry asserts its precondition (the plain write is - denied), or it can pass without reaching the retry. -- A test variable must not take the name of an automatic variable such as - `$foreach`: Pester runs the block inside a foreach, and the value is lost. -- The CI scripts set `$ErrorActionPreference = 'Stop'`; focused runs do the - same, and a test that needs a non-terminating error (for example to take it - through `2>&1`) names `-ErrorAction Continue`. + PassThru output. Prove new characterization guards with bounded mutations + (one round together only if no guard can fail because of another); restore + source exactly and rebuild before green validation or packaging. A retry + test asserts its precondition (the plain write is denied). +- CI scripts and focused runs set `Stop`: a test that needs a non-terminating + error names `-ErrorAction Continue`. Don't name a test variable like an + automatic variable (`$foreach`): Pester runs the block inside a foreach. - Fixture DACLs use .NET SetAccessControl, not Set-Acl's unintended SACL writes. - Scope/descendant expectations are independent of the production converter. -- Drive-root tests map a sandbox folder with `subst` through - `New-TestDriveMapping` (elevated only; the basic token cannot). Tests that - need a letter without a volume take the lowest free one. -- Desktop platyPS: generate help, rebuild, round-trip unchanged, check links. - platyPS 0.14.2 turns a pair of asterisks in a paragraph into emphasis, also - inside backticks, and the help drops them: write the words, put patterns in - example code blocks, and check the generated XML. +- Desktop platyPS: generate help, rebuild, round-trip unchanged, check links; + platyPS 0.14.2 turns paired asterisks into emphasis, even in backticks. - Live tests use only approved lab targets, SMB then independent server state; Get/SetFileSecurity preserves stored DACLs; rights oracles use S4U tokens. -- A suite that is green on the development host and on CI says little about a - feature that the environment lacks. The matrix found three defects that every - earlier run had missed because the host is outside a domain and the CI - runner's token differs: run the suite on a domain member, on other builds, and - as a basic user before a release, and classify a failure by a probe under the - real tokens (elevated, filtered, local standard, domain standard) before - calling it a defect or a design. -- A fixture that deletes an account and creates it again with the same name can - get a wrong answer for about ten minutes: the remote authorization managers - answered `0x100000` for the current SID while the local manager and a Kerberos - logon were right in the same second, and, when the accounts are created again - within seconds, the Kerberos S4U logons returned the old account (7 to 15 - minutes). A failure that follows the order of the cells and not the version of - the module points to such state: run the baseline and the candidate in cells - that follow each other and alternate them (the replay of the record) before - blaming the code. The controller names the account of case 3 anew for each new - fixture. +- A suite that is green on the host and CI misses defects that need a domain + member or another token (the matrix found three): also run a domain member, + other builds, and a basic user. A failure that follows cell order, not + version, points to stale account state (Decision 24): alternate the cells. -### CI results and publication +### CI, publication, and integration -- Use Path.Combine then GetFullPath for a rooted-or-repository-relative - result path; Join-Path appends even a rooted child and corrupts it. -- Discovery handles only expected PackageNotFound as absence; repository, - authentication, and network errors remain failures. -- Rerun/uncertain-upload success requires Gallery SHA-512 equality with the - exact build artifact. Base64 is case-sensitive: use ordinal comparison. - Missing/different/unverifiable metadata preserves the upload error. -- Secrets stay by environment reference, never in process arguments/logs. - Test all external publication commands with mocks; no test may upload. -- AltCover aggregates all four sequential runs without --save. Report - sequence points, not unique source lines; keep unmatched paths visible. +- Discovery treats only PackageNotFound as absence. Rerun/uncertain-upload + success needs Gallery SHA-512 equality with the exact build artifact + (ordinal Base64); anything else preserves the upload error. Secrets stay + environment references; mock all publication commands, no test uploads. +- Gate prompts are self-contained: pins are historical, state is rechecked, + completion is evidence, risk acceptance is no test pass. In a stack of pull + requests, retarget each to `master` before merging the one below; delete a + head branch only when no open pull request uses it as its base (Decision 15). diff --git a/.memory-bank/techContext.md b/.memory-bank/techContext.md index 881aa48..4430756 100644 --- a/.memory-bank/techContext.md +++ b/.memory-bank/techContext.md @@ -1,6 +1,6 @@ --- status: current -last-verified: 2026-10-09 +last-verified: 2026-10-10 owner: active-agent source: repository and executable evidence --- @@ -37,16 +37,14 @@ source: repository and executable evidence runs in a new process. Current prereleases share assembly version 5.0.0.0. - GitHub CLI: `C:\Program Files\GitHub CLI\gh.exe`, signed in as raandree. Read-only queries work; remote mutations belong to the maintainer. -- LabSources: `V:\LabSources`. All 13 deployed machines are Server 2025. - Windows 11 consumer/enterprise-evaluation media and Server 2019/2022 - ISO files exist. OS cache is empty; exact detected editions are not yet - verified. Do not equate present media with a deployed/tested OS matrix. +- LabSources: `V:\LabSources`. The first lab's machines are Server 2025; the + matrix lab `NtfsSecurityOsMatrixLab` adds Server 2019/2022 and Windows 11. ## Constraints -- Source manifest: ModuleVersion 5.0.0, prerelease rc7 on #116/follow-up. - Latest stable: 4.2.6; latest published prerelease: rc6 (2026-10-08). - GitHub rc6 release recovered 2026-10-09. rc7 publication is pending. +- Manifest: ModuleVersion 5.0.0, prerelease rc7 (on `master` since + 2026-10-10, untagged). Latest stable 4.2.6; latest published prerelease + rc6 (2026-10-08). rc7 publication is pending. - Changed-section writes preserve unchanged owner/group/DACL/SACL (19). Roots use root-folder APIs, not AlphaFS device security (#41). - CHANGELOG contains user-visible changes only (7); tests and CI-only fixes @@ -57,8 +55,6 @@ source: repository and executable evidence Issue references use no closing keyword unless closure is intended. - Lab passwords stay in memory and are lab-only; no secret in repository, logs, or process arguments. Live ACL mutations occur only in the lab. -- Existing expired installation passwords of a.forest1/b.forest1 were - configured not to expire on 2026-10-07, matching the root domain. ## Build and focused checks @@ -94,14 +90,11 @@ source: repository and executable evidence - Packaging needs Compress-PSResource (Core 7.4+). New-ModulePackage copies only FileList, validates the manifest, creates nupkg plus NTFSSecurity.zip. Check package/file hashes and test the extracted artifact, not build extras. -- Release runs only for validated version tags in powershell-gallery. - API key stays as PSGALLERY_API_KEY environment reference. Helper - Publish-ModulePackage treats only PackageNotFound as expected absence; - existing-version skip and uncertain-upload recovery require exact Gallery - SHA-512 equality. Base64 comparison is case-sensitive. Unverifiable, - missing, and different outcomes preserve errors. No test uploads. -- Read status through gh pr checks / gh run view --log-failed. A successful - Gallery upload followed by HTTP 409 does not prove its retry chronology. +- Release runs only for validated version tags in powershell-gallery; the API + key is the environment secret PSGALLERY_API_KEY. The rules of + `Publish-ModulePackage` are in `systemPatterns.md`. Read status through + `gh pr checks` and `gh run view --log-failed`. A successful Gallery upload + followed by HTTP 409 does not prove its retry chronology. ## Coverage and test eligibility @@ -112,45 +105,35 @@ source: repository and executable evidence four configurations sequentially with the real CI wrappers, then AltCover runner --collect recalculates the report. Compute option paths before passing native arguments, not inline Join-Path expressions. -- Report sequence points, not unique source lines. Four-run baselines: - rc5 2,020/3,476 (58.1%), branches 711/1,873 (38.0%); - rc6 2,412/3,540 (68.14%), branches 850/1,918 (44.32%); - follow-up `3442194` 2,641/3,559 (74.21%), 974/1,933 (50.39%); - Handoff 1 `5a5d58b` 3,192/3,634 (87.84%), 1,273/1,978 (64.36%). Different - code changes denominators; never present these as same-source incremental - percentages. The branch summary counts 820 compiler-generated points (185 - visited); report the explicit branch points as well (1,088/1,158, 93.96%). -- Suite at `5a5d58b`: 1,310 per configuration, zero failures. Passed/skipped: - elevated Desktop 1,286/24, Core 1,255/55; basic Desktop 1,076/234, - Core 1,045/265. +- Report sequence points, not unique source lines. Four-run baselines: rc5 + 2,020/3,476 (58.1%); rc6 2,412/3,540 (68.14%); `3442194` 2,641/3,559 + (74.21%); `5a5d58b` 3,192/3,634 (87.84%), branches 1,273/1,978 (64.36%). + The code changes the denominators: never present these as same-source + increments. The branch summary counts 820 compiler-generated points; report + the explicit branch points too (1,088/1,158, 93.96%). Suite at `5a5d58b`: + 1,310 per configuration, zero failures (skipped: 24 and 55 elevated, 234 + and 265 basic, Desktop and Core). - NUnit skipped ForEach names retain placeholders and parameter tuples, - executed names expand them; raw-name intersection and positional alignment - are invalid. Skip eligibility is checked by row: run the suite once per - configuration with Pester PassThru (`Get-DiscoveryRows2.ps1 -Run` in the - session evidence) and match skipped with executed rows by file, line, - path, name, and data. Discovery alone misses tests that skip themselves - while they run, and `ConvertTo-Json` of rich data rows never finishes: - write primitives and type names. + executed names expand them: raw-name intersection and positional alignment + are invalid. Check skip eligibility by row: run the suite once per + configuration with Pester PassThru and match skipped with executed rows by + file, line, path, name, and data (discovery alone misses tests that skip + while running; write primitives, as `ConvertTo-Json` of rich rows hangs). - Remaining inventory: 442 points in 231 methods, classified by rule with evidence (probe, IL scan, source reading); see `Tests/Coverage`. Preserve - raw XML, row CSVs, logs, commit identity, and build hashes. The frozen - Build rewrites the hash file each time: save the hashes of the measured - assemblies (AltCover `__Saved` copies) before any mutation build. -- Bounded mutations: one script per round on the frozen worktree, with - guards that no other mutation of the round can trip (an escape can be an - overlap or an equivalent mutant: check before changing a test). Restore - the source exactly and rebuild. -- Red/green matrix, to show afterwards that a guard fails without its fix: - build each state of the branch (base, then each fix commit) in its own - Release worktree, lay the final `Tests` over it (`git checkout -- - Tests`), run the guarding files with the focused runner (it sets - `$ErrorActionPreference` to `Stop` like the CI wrappers) in all four - configurations, and count failed rows per name with their multiplicity (a - block whose `BeforeAll` fails lists its data rows under one unexpanded - template name). The last state is the control and must have no failure. - Keep the logs and a manifest with their hashes, and hash each build: the - first red runs of Handoff 1 were deleted and could not be reproduced, and - the frozen runner rewrites its hash file at each build. + raw XML, row CSVs, logs, commit identity, and build hashes: the frozen + Build rewrites its hash file, so save the hashes of the measured assemblies + (AltCover `__Saved` copies) before any mutation build. +- Bounded mutations: one script per round on the frozen worktree, with guards + that no other mutation of the round can trip (an escape can be an overlap + or an equivalent mutant: check before changing a test). Restore the source + exactly and rebuild. +- Red/green matrix (a guard fails without its fix): build each state of the + branch in its own Release worktree, lay the final `Tests` over it, run the + guarding files with the focused runner in all four configurations, and count + failed rows per name with multiplicity; the last state is the control. Keep + the logs, a manifest with hashes, and the hash of each build: the first red + runs of Handoff 1 were deleted and could not be reproduced. ## Lab acceptance @@ -159,36 +142,31 @@ source: repository and executable evidence Controller accepts alternate machines; changing topology/OS scope waits for a maintainer decision. Do not repurpose another project's shared VMs. - Before a run: authenticated WinRM, LDAP RootDSE, Kerberos tickets, member - secure channels, clocks; checkpoint only approved targets. Inspect actual - checkpoint kind: new checkpoints reported Standard even after a successful - temporary ProductionOnly request. Policy restored; no rollback performed; - Production classification remains unverified, not a passed safety check. + secure channels, clocks; checkpoint only approved targets. New checkpoints + report Standard even after a successful ProductionOnly request (policy + restored, no rollback): Production is unverified, not a passed safety check. - Run Tests\Lab\Invoke-NTFSSecurityLabTest.ps1 in elevated Desktop with -Version for hash-checked Gallery packages or -ModulePath for the extracted build artifact, both editions. Per version/edition: Delegate, ServerAdmin, Admin on client, then Server independently checks persisted state. - Controller writes Summary.json even when tests fail: validate every role, exit code, failure name, and total; DONE alone is not acceptance evidence. - Desktop ConvertFrom-Json can wrap arrays; explicitly enumerate the result - and compare full Describe-prefixed names. Never gate cleanup on the global - Error.Count, which includes handled errors; independently verify footprint. + Desktop ConvertFrom-Json can wrap arrays: enumerate the result and compare + full Describe-prefixed names. Never gate cleanup on the global Error.Count + (it includes handled errors); verify the footprint independently. - Remote Authz answers administrators and Access Control Assistance - Operators (S-1-5-32-579); other accounts get access denied. Check firewall - when remote resource-manager RPC fails. Expected rights use S4U tokens. - A computer in a domain offers the remote interface to every caller, so the - denial also hit the default `-ServerName localhost` for a user who isn't an - administrator; a computer outside a domain doesn't offer it, which is why the - tests passed on the development host and on CI. Since `fdd7a8b`, the local - manager answers for a name of this computer when the remote one refuses; the - denial stays for another computer (live test of the Delegate role). + Operators (S-1-5-32-579); other accounts get access denied (check the + firewall when its RPC fails). Expected rights use S4U tokens. A domain + member offers the remote interface to every caller, so the default + `-ServerName localhost` was denied for a non-administrator; hosts outside a + domain don't, so the host and CI missed it. Since `fdd7a8b` the local + manager answers for a name of this computer; another computer stays denied. - A live test is evidence of a fix only when it fails on the build without the fix: run the same tests, controller, and lab against the candidate and - the base of the branch, a new process per edition, and join both result - sets by edition, role, and full test name; the tests that pass on both are - controls (`Tests\Lab\Acceptance-2026-10-09-quality-gate-paths.md`). A - validator must not name a loop variable like a typed parameter: PowerShell - variables ignore case, so `$edition` overwrote `$Edition` and every edition - in the CSV became `System.String[]`. + the base, a new process per edition, and join the results by edition, role, + and full test name; tests that pass on both are controls (record of + 2026-10-09). PowerShell variables ignore case: `$edition` overwrote + `$Edition`. - RemoveFixture after the run; verify OUs/accounts, share, folders, local memberships, and test profiles removed. Credentials must never be printed. @@ -196,53 +174,20 @@ source: repository and executable evidence - Lab `NtfsSecurityOsMatrixLab`: OSDC1 (Server 2025), OSFile19/22/25 (Server 2019/2022/2025), OSWin11E (Windows 11 Enterprise Evaluation 22H2, the domain - client), OSWin11 (Windows 11 Pro 26H1, suite only). Kit: `Tests\Lab\Acceptance`; - record: `Tests\Lab\Acceptance-2026-10-10-os-matrix.md`. -- Run the module's own suite on every machine class before the controller - (`Run-MatrixLocalSuite.ps1`, elevated and basic, both editions, as scheduled - tasks with a batch logon at the highest run level): a child of a remoting - session has every privilege enabled and fails eight tests that expect them - disabled. Skipped lists are compared as multisets against the host. -- AutomatedLab: one `Import-Lab` at a time, and none while a controller - sequence runs (it re-imports the lab); `Wait-LabVM` waits for a heartbeat that - a client may not report, so retry `New-LabPSSession`. The host's `bcdboot` - leaves the ESP of a Server 2019 or Windows 11 22H2 base image empty. -- Windows PowerShell 5.1: `$PSScriptRoot` is empty in a parameter default under - `-File`; `2>&1` on a native command under `Stop` makes its stderr line - terminating; `Get-LocalGroupMember` fails on an orphaned SID; `net localgroup - /delete` refuses the SID of a name that its cache still - resolves (use `Remove-LocalGroupMember -SID`). -- Windows 11 26H1 (28000.1836) loses the secure channel to a Server 2025 domain - controller (`NetrLogonGetCapabilities` level 2, 0xC0000022): suite only. - The 22H2 evaluation client shuts down every hour (license grace expired) and - can lose its machine password after an unplanned shutdown: keep a run under - an hour from its start, test a domain session (not `nltest /sc_verify`, which - stays stale), repair with `Test-ComputerSecureChannel -Repair`. -- Builds are not byte-reproducible (two unchanged assemblies differ per build): - hash each candidate and its package separately. -- The fixture's account for case 3 gets a new name for each new fixture - (`NtfsLiveSubject` and four digits). In the matrix lab, after an account was - deleted and created again with the same name, the remote authorization - managers (the client's for the default `-ServerName`, the file server's for its - name) answered for about ten minutes as if it had no groups (`0x100000`), for - the baseline and for the final candidate alike, while the Kerberos S4U logon of - the oracle, the - name resolution, and the local manager were right in the same second. A replay - with the baseline and the final candidate alternating failed the baseline in two - of three cells and the final candidate in one of three (not counting the warm-up - cell). The mechanism in Windows is unknown; a model with one lifetime (9.95 to - 10.25 minutes for both tests, to within 0.05 minute) fits all 43 Admin-role runs - of 27 cells. When the accounts are created again within seconds, the S4U - logon itself returns the old account for 7 to 15 minutes. A `klist purge`, - `nltest /sc_reset`, a DNS flush, and a restart of the Kerberos service didn't - help. `Probe-AccountRecreation.ps1`, `Export-CellTimeline.ps1`, and - `Test-StaleAuthzModel.ps1` show it. -- `net.exe localgroup` lists a local user by its bare name and the entry of a - deleted domain account as its SID (or as its cached name for a while); - deleting a local user removes its entries from the local groups, so only the - entries of domain accounts stay orphaned. `Test-MatrixCleanup.ps1` finds the - entries of the account probe in Performance Log Users by a name with - `NtfsProbe` or by any unresolved `S-1-5-21-…` SID (every such member counts as - the probe's), and its profiles by their folder `C:\Users\NtfsProbe*`. The - cached-name form met real residue in a test; the bare-SID form and a profile - that stays loaded didn't. + client), OSWin11 (Windows 11 Pro 26H1, suite only). Kit + `Tests\Lab\Acceptance`; record + `Tests\Lab\Acceptance-2026-10-10-os-matrix.md` (procedure, limits); + the lessons of building it are in `deployment-notes.md`. +- Run the module's own suite on every machine first (`Run-MatrixLocalSuite.ps1` + as scheduled tasks with a batch logon at the highest run level; a remoting + child has every privilege enabled). One `Import-Lab` at a time. Compare skips + as multisets against the host. Hash each candidate and its package: builds + aren't byte-reproducible. +- The 26H1 client can't keep its secure channel to a Server 2025 DC (suite + only); the 22H2 evaluation client shuts down every hour: keep a run under an + hour and test a domain session, not `nltest /sc_verify`. +- A fixture that re-creates an account name gets stale answers for about ten + minutes, for the baseline and the candidate alike (mechanism unknown; no + remedy but waiting). The controller names the case-3 account anew for each + fixture; the replay and the model are in the record. `Test-MatrixCleanup.ps1` + verifies and repairs the probe's profiles and group entries.