Browse Source

docs(memory-bank): record the integrated stack and curate the budgets

The maintainer merged the whole release-gate stack into master (fa0701b,
CI green): #116, #120 (it replaced #117, which GitHub closed unmerged when
the branch deletion after #116 removed its base), #118, and #119. rc7 is
not tagged yet.

Update the focus, evidence, next steps, progress, and deployment notes for
that state, and record the operating rule of a stack in Decision 15:
retarget before merging, delete head branches last.

The work of the night had pushed techContext (248 of 200 lines) and
systemPatterns (147 of 110) over their budgets, and activeContext and
progress close to theirs. Condense them and point to the records and to
Decision 24 for the detail; the full text is in git at 2b8643f. Port the
one durable pattern of the unmerged handoffs commit cb53fd7. The health
check passes: 0 errors, 2 near-limit warnings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
pull/121/head
Raimund Andree 2 days ago
parent
commit
d85a51d23e
  1. 277
      .memory-bank/activeContext.md
  2. 13
      .memory-bank/decisions/0015-merge-stacks-with-merge-commits.md
  3. 86
      .memory-bank/deployment-notes.md
  4. 158
      .memory-bank/progress.md
  5. 99
      .memory-bank/systemPatterns.md
  6. 195
      .memory-bank/techContext.md

277
.memory-bank/activeContext.md

@ -9,186 +9,117 @@ source: current task evidence
## Current focus ## Current focus
The maintainer asked on 2026-10-09 at 21:21 UTC to continue with the release-gate State at 2026-10-10 11:47 UTC: the maintainer integrated the release-gate stack
handoffs and to decide and report later. On 2026-10-10 at 09:10 UTC he merged into `master` (`fa0701b`, CI green at 11:40Z): #116 (rc7, `8a6be9f`), #120
#116 (rc7, merge commit `8a6be9f`; rc7 is neither tagged nor published). His (`bdb9981`; it replaced #117, which GitHub closed unmerged when the branch
`--delete-branch` also deleted the base branch of #117, so GitHub closed #117 deletion after #116 removed its base, see Decision 15), #118 (`03bef2c`,
unmerged; nothing is lost (`ai/quality-gate-coverage` is intact at `f11ff41`, handoff 1, the paths), and #119 (`fa0701b`, handoff 2, the operating-system
and the merge into `master` is conflict-free by simulation), and a new pull matrix). The remote head branches are deleted. rc7 is not tagged or published:
request replaces it (Next step 1). Handoff 1 (paths) is draft #118 (`83149ee`, rc6 is the latest published prerelease, 4.2.6 the stable Gallery version. rc7
CI green, base `ai/quality-gate-coverage`; rc6 is the latest published contains the Phase 2 behavior changes, the path tests and fixes, and the three
candidate, 4.2.6 the stable Gallery version). Handoff 2 (operating-system module fixes of the matrix (`962887a`, `fdd7a8b`). Stable 5.0.0 stays gated
matrix) is draft #119 (`49734ef`, CI green, base `ai/quality-gate-paths`): the (Decision 21).
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.
The earlier state of handoff 1, from the reviewed head `f11ff41` of #117: 28 The maintainer asked on 2026-10-09 at 21:21 UTC to continue with the
commits, which the maintainer pushed as draft #118. Every C# method that no test release-gate handoffs and to decide and report later. The agent's decisions are
visits is classified (223 explained, 8 open for the maintainer), and the D1 to D47 in `decisions-night-2026-10-09.md` of the session files. Decisions
other paths have behavior tests. Eleven defects were fixed, ten of them 22 (Phase 2), 23 (the #34 dossier), and 24 (the matrix) are proposed: the agent
with a regression guard that is red before the fix and green after it (owner confirmed Decision 22 under the delegation, and neither that nor any risk
restore, `InheritedFrom`, a later command that ends the pipeline or throws, acceptance is the maintainer's.
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.
## Evidence ## Evidence
- rc6 Release run `37839669028`, attempt 2, succeeded; GitHub prerelease - rc6 Release run `37839669028`, attempt 2, succeeded; GitHub prerelease with
with zip appeared 2026-10-09 07:01:34 UTC. First attempt proves HTTP 409 zip appeared 2026-10-09 07:01:34 UTC. The first attempt proves HTTP 409
after Gallery publication, not the previously assumed retry chronology. after Gallery publication, not the earlier assumed retry chronology.
- #116 was merged into `master` on 2026-10-10 at 09:10:12Z (merge commit - Integration on 2026-10-10 (UTC): #116 merged 09:10, #117 closed unmerged
`8a6be9f`, head `d25647d`); rc7 isn't tagged or published. #117 was closed 09:10:16 (events `base_ref_deleted`, `closed`), #120 merged 10:50, #118
unmerged at 09:10:16Z (events `base_ref_deleted`, `closed`). 11:12, #119 11:28, head branches deleted 11:34, CI on `master` at `fa0701b`
- Local changes: deletion/ownership guards (`a97e46f`); all scopes and green 11:40. A `git merge-tree` simulation of the chain was conflict-free and
inheritance (`e7ee203`); absolute basic-user results (`51dec86`); ended in the tree of the matrix branch.
exact-package publication recovery (`95b827e`); first-hidden-item fix - Handoff 1 (paths), measured at `5a5d58b` (frozen Release, four configurations,
(`d610372`); Force/descriptor guards (`3442194`); SMB regression above. CI wrappers, then AltCover): 1,310 cases per configuration, zero failures
- Hidden omission was reproduced in all four configurations before the (baseline `3442194`: 914 cases); coverage 3,192/3,634 sequence points
fix. No parameter/design change. Publication tests are wholly mocked; (87.84%) and 1,273/1,978 branches (64.36%), against 74.21% and 50.39%. All 231
exact ordinal SHA-512 identity is required, no real upload occurred. methods with 442 unvisited points are classified: 223 explained, 8 open for
- At `3442194` (start of Handoff 1): 914 cases per configuration, 2,641/3,559 the maintainer. Skip eligibility was checked by row: all 578 skipped rows
sequence points (74.21%), 974/1,933 branches (50.39%), 918 unvisited (137 distinct tests) are executed in two other configurations.
points. All skipped templates had executed counterparts. - Eleven defects were fixed, ten with a guard that is red before the fix and
- Handoff 1 result at `5a5d58b` (frozen Release, four configurations, CI green after it (a red/green matrix over ten states of the branch: 76 rows
wrappers, then AltCover): 1,310 cases per configuration, zero failures; red at the base `f11ff41`, none after the last fix; the leak of a native
passed/skipped: elevated Desktop 1,286/24, Core 1,255/55; basic Desktop buffer has no guard). Mutation rounds at `5a5d58b`: 25 of 26 detected, M25
1,076/234, Core 1,045/265. Coverage 3,192/3,634 sequence points (87.84%), (the check by type) an equivalent mutant. The matrix doesn't show that a test
1,273/1,978 branches (64.36%); 231 methods with 442 points stay unvisited, preceded its fix: each fix commit carries both. Report:
all classified: 223 explained, 8 open. Skip eligibility was checked by row `Tests/Coverage/Quality-Gate-Paths-2026-10-09.md`.
from a second full run per configuration: all 578 skipped rows (137 - Reviews: the custom `security-reviewer` can't start (its model is
distinct tests) are executed in two other configurations. unavailable; no override). The built-in `code-review` agent made nine static
- Mutation rounds on the frozen tree at `5a5d58b`: 26 mutations in four passes of the paths work (no Blocker or Major) and four rounds on the matrix
rounds; 25 are detected by their guard in every configuration where it (one Major, record accuracy, resolved by the replay; Minors corrected); the
runs, and M25 (the check by type, an equivalent mutant) survives as built-in `security-review` agent found no exploitable vulnerability and two
expected. At `d61dffa` three had escaped (the verbose and debug rows ran LOW items left for the maintainer (Next step 5).
under the CI runner's `Stop`, and an Init test could not fail for its - Live candidate of 2026-10-09 (09:20 to 09:51 UTC): 330 passed, 0 failed, 2
branch), which led to `f4a16e1`. A first round at `630926f` had let one expected skips; published rc6: 326 passed, 4 expected failures, 2 skips; the
mutation escape, which led to the `-Filter` bracket defect. 11 tested files match the ZIP. Independent probes verified the fixture
- Red/green matrix (measured after the last measurement, because the first removal on six machines (`Tests/Lab/Acceptance-2026-10-09-quality-gate.md`).
red runs were not kept): the final tests of the eight files that guard the - Six checkpoints report Standard even after a successful ProductionOnly probe;
fixes (650 cases per configuration) over the production code of ten states policy restored, no restore performed: don't claim verified Production
of the branch, built in Release and run with the focused runner (it sets rollback evidence.
`Stop` like the CI wrappers) in the four configurations. 76 rows (73 in the - Lab acceptance of the paths fixes, 2026-10-09 20:41 to 21:42 UTC: candidate
basic configurations) fail at the base `f11ff41`, each is green at the step `83149ee` against its base `f11ff41`, the same 244 tests per edition (78
of its fix, none breaks later, and `d44a200` has none (the control). Defect new): 486 passed, 0 failed, 2 expected skips against 338 passed, 148 failed
9 (the native buffer) has no guard. The matrix does not show that a test was (each green on the candidate); fixture removal verified. Record:
written before its fix: each fix commit carries both, and the red runs of `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`.
that time were not kept. - Operating-system matrix, 2026-10-10 (record
- Review: custom `security-reviewer` could not start (model unavailable); the `Tests/Lab/Acceptance-2026-10-10-os-matrix.md` with CSV tables): the suite of
built-in read-only `code-review` agent made nine static passes: no Blocker the final candidate `fdd7a8b` passes on OSFile19/22/25, OSWin11E, OSWin11, and
or Major; its Minor findings led to the `*.*`, help, test, later-command, the host (24 runs, no failure; the baseline `83149ee` fails 4 elevated and 20
error-stream, and privilege fixes. Report: basic-user tests on OSFile22 and OSFile25); the live controller passes in
`Tests/Coverage/Quality-Gate-Paths-2026-10-09.md` with an appendix of three cells (1,374 passed, 0 failed, 12 skipped) and in the first lab with
explanations and CSV rows; raw evidence is in the session folder case 9 (245 passed, 0 failed, 1 skipped per edition; fixture removed and
`4b12e2f4-d4c7-4a5d-883a-ddb7421c4848\files\qg-paths`. verified). The Admin-role effective-access failures in earlier cells were
- Live packaged candidate, 09:20 to 09:51 UTC: 330 passed, zero failed, stale account state, not the module: in a replay the baseline failed two of
two expected Server-module skips. Published rc6: 326 passed, four three cells and the candidate one, and one lifetime of about ten minutes fits
expected failures (Hidden and rc7 warning text in each edition), two 43 runs of 27 cells (the Windows mechanism is unknown). The controller names
skips. Tested folder and all 11 ZIP files are byte-identical. the case-3 account anew for each fixture (`1dec389`); four more cells with it
- Temporary host result verifier failed on Desktop JSON wrapping/full passed. A dry run of `Run-MatrixSequence.ps1 -Version 5.0.0-rc6` showed that
test names; corrected verification passed on unchanged raw results in the published-package path works. Labs at 07:50 UTC on 2026-10-10: no fixture
both editions. Cleanup wrapper's broad Error.Count was not acceptance or probe residue; `OSWin11E` shuts itself down an hour after its start.
proof. Independent probes verified all fixture objects/members/profiles - Raw evidence is outside git: the session folder
gone from six machines. Raw failing markers and corrected evidence kept. `4b12e2f4-d4c7-4a5d-883a-ddb7421c4848\files` (`qg-paths`, the matrix runs, the
- Review of the lab candidate: one read-only independent code review night log) and
approved, high confidence, no significant findings or confirmed exploit. `26f151b6-e46f-49bd-9398-b27e20603949\files\quality-gate-3442194-20261009`.
- 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.
## Next step ## Next step
1. The maintainer integrates the rest of the stack (Decision 15; commands in 1. The maintainer tags `fa0701b` as `5.0.0-rc7` and pushes the tag; the
the deployment notes). A **new** pull request from `ai/quality-gate-coverage` `release` job then publishes to the Gallery and GitHub after the approval of
to `master` replaces #117; then #118 and, if its module fixes go into rc7, the `powershell-gallery` environment (deployment notes). Every release step
#119 are retargeted with `gh pr edit <n> --base master`, marked ready, and is his.
merged. No `--delete-branch` while another open pull request uses the branch 2. Gate 3, after rc7 is on the Gallery (the agent runs it on request):
as its base; the head branches are deleted last. He decides which module `Test-PublishedRelease.ps1 -Version 5.0.0-rc7`, the live controller with
fixes of the matrix branch belong to rc7 (two commits: `962887a` holds two `-Version` in the first lab, and `Run-MatrixSequence.ps1 -Version 5.0.0-rc7`
fixes, `fdd7a8b` one) and reviews them (Decision 24). for every cell (deployment notes, "Accept a published package"). Open: keep
2. He decides the open items listed in the paths report: `FileSecurity` or replace the matrix VMs (about 60 GB) and the evaluation client (it shuts
conversions, `RemoveAll` account filters, lazy path overloads, abandoned 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 `PrivilegeEnabler`, dot patterns of `Get-ChildItem2 -Filter`, the 17
owner-restore handlers without the later-command check, unused classes owner-restore handlers without the later-command check, unused classes
(Decisions 21/22). (Decisions 21/22). He also confirms or changes the proposed Decisions 22 and
3. Gate 3: accept the published package in the first lab and in every cell of 24.
the matrix (`Run-MatrixSequence.ps1 -Version`) before the candidate counts as 4. #34 stays open (Decision 23; no reply since 2026-10-06): the maintainer
accepted; no local upload. The paths fixes were accepted locally (record chooses between waiting for a test of the published candidate on the
above). NetApp, EMC, and IBM ESS servers of the reporters (checklist:
4. Retain stacked-PR order (15): #116 (merged), the replacement of #117, #118, `Tests/Lab/Non-Windows-File-Server-Test.md`) and accepting the untested
then #119; a simulated merge in that order gives exactly the tree of the risk with a release-note caveat. No agent can accept it.
matrix branch (`62aa1ae`). Confirm or change Decision 22. 5. He decides the two LOW findings of the security review (record, Limits):
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):
the swallowed initialization errors of `GetEffectiveAccess` (a false "no the swallowed initialization errors of `GetEffectiveAccess` (a false "no
access" instead of an error on an OS that refuses at initialization, and access" instead of an error on an OS that refuses at initialization; fix:
neither warning nor error when the local fallback fails; fix: record the record the exceptions in `authzException`, with a regression test and a
initialization exceptions in `authzException`, with a regression test and a check of "the error stays" in the help and CHANGELOG), and the ACL of the
check of the sentence "the error stays" in the help and CHANGELOG), and the stage folders under `C:\` in the lab kit (they inherit Authenticated Users:
ACL of the stage folders under `C:\` in the lab kit (they inherit Modify; protecting them is a design change of the controller and needs a new
Authenticated Users: Modify; protecting them is a design change of the acceptance). The help could also say that a local standard user who asks
controller and needs a new acceptance). The help could also say that a local about a domain account still gets "Access is denied".
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.
7. Do not release stable 5.0.0 or equate a percentage with gate closure.

13
.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 pull request would conflict, and the commit IDs in the descriptions and
the changelog would no longer exist on `master`. A merge commit keeps 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. 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 <n> --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.

86
.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) ## Publish the next prerelease (rc7)
State on 2026-10-10 at 09:59 UTC: #116 (rc7, head `d25647d`) is merged into State on 2026-10-10 at 11:47 UTC: the whole stack is merged into `master`,
`master` (merge commit `8a6be9f`, 09:10:12Z). #117 (head `f11ff41`, base which stands at `fa0701b` and has the tree of `2b8643f`: #116 (rc7, `8a6be9f`,
`ai/release-5.0.0-rc7`) was **closed without a merge** at 09:10:16Z: the 09:10Z), #120 (`bdb9981`, 10:50Z), #118 (`03bef2c`, 11:12Z), and #119
`--delete-branch` of `gh pr merge 116` deleted its base branch, and GitHub (`fa0701b`, 11:28Z). #117 had been closed without a merge at 09:10:16Z, when
closed it (events `base_ref_deleted`, then `closed`) instead of retargeting it. the branch deletion after the merge of #116 removed its base branch (Decision
Nothing is lost: `ai/quality-gate-coverage` is intact at `f11ff41`, and 15, operating rule); #120, a new pull request from its head `f11ff41`,
`master` still lacks its change (25 files). #118 (draft, head `83149ee`, base replaced it. The remote head branches were deleted at 11:34Z. The CI run on
`ai/quality-gate-coverage`) and #119 (draft, head `49734ef`, base `master` at `fa0701b` passed at 11:40Z (Build and test, Wiki, Publish the
`ai/quality-gate-paths`) are open and green. A simulated merge chain wiki; Release skipped, as for any push without a tag). The manifest says
(`git merge-tree --write-tree`, no ref written) with merge commits `5.0.0` with `Prerelease = 'rc7'`, and `$publishedVersions` in
(Decision 15) is conflict-free at every step: the coverage branch into `master` `Tests/Repository.Tests.ps1` lists the versions up to rc6, as it must before
gives the tree of `f11ff41`, #118 then gives `b1dc006`, and #119 gives rc7 is published. The release notes of a prerelease are the `[Unreleased]`
`62aa1ae`, the tree of the matrix branch. The manifest says `5.0.0` with section of `CHANGELOG.md`.
`Prerelease = 'rc7'`, and `$publishedVersions` in `Tests/Repository.Tests.ps1`
lists the versions up to rc6, as it must before rc7 is published.
The branch `ai/quality-gate-lab-matrix` (draft #119) is stacked on #118. It rc7 contains everything that is merged: the behavior changes of Phase 2
holds three fixes of the module in two commits (`962887a` has two, `fdd7a8b` (#116), the quality-gate paths (#120, #118), and the three module fixes of
one). `fdd7a8b` reverts cleanly on its own; `962887a` doesn't the matrix (#119, in two commits: `962887a` holds two, `fdd7a8b` one; they
revert while `fdd7a8b` stays (the two conflict in `Security2/Win32/Lib.cs` and don't revert separately, because they conflict in `Security2/Win32/Lib.cs` and
`CHANGELOG.md`), and its two fixes go together. The branch also holds the kit of the `CHANGELOG.md`), with the kit, the controller changes, and the record of the
operating-system matrix, the changes of the live controller, and the record operating-system matrix (Decision 24).
(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.
Do not delete a head branch while another open pull request uses it as its 1. Tag the commit `fa0701b` on `master` with `5.0.0-rc7` and push the tag
base. On 2026-10-10 the deletion through `gh pr merge --delete-branch` closed (lightweight tags, as for rc1 to rc6). The `release` job checks the tag
#117 instead of retargeting it. The open reports `cli/cli#1168` and against the manifest and builds nothing new: it publishes the package that
`cli/cli#14223` show the same two events and say that GitHub retargets only the `build` job tested. Approve the deployment of the `powershell-gallery`
when the branch is deleted with the button on the pull request page. The environment if it asks.
latter also reports, and this was not tried here, that `gh pr edit --base` 2. Accept the published package (next section): `Test-PublishedRelease.ps1`,
refuses a closed pull request and that `gh pr reopen` refuses while the base the first lab, and every cell of the matrix.
branch is missing. A new pull request from the same head is the repair. 3. After the publication, add `5.0.0-rc7` to `$publishedVersions` with the
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
next change that goes to `master`. next change that goes to `master`.
## Accept a published package ## 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 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 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 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 waiting. A model with one lifetime (9.95 to 10.25 minutes) fits all 43
for each new fixture; a script of your own that recreates accounts needs unique Admin-role runs of 27 cells; the replay and the model are in the record of the
names too. 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, - 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 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. about two and a half minutes and may need the repair of the secure channel.

158
.memory-bank/progress.md

@ -9,17 +9,13 @@ source: repository and validation evidence
## Current status ## Current status
5.0.0-rc6 is published on the Gallery and GitHub; its failed Release job 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 recovered in attempt 2 on 2026-10-09). On 2026-10-10 the maintainer merged the
`master` on 2026-10-10 (`8a6be9f`); rc7 is neither tagged nor published. #117 whole stack into `master` (`fa0701b`, CI green): #116 (rc7), #120 (it replaced
was closed unmerged when its base branch was deleted, so a new pull request #117, which GitHub closed unmerged when the branch deletion after #116 removed
from `ai/quality-gate-coverage` replaces it. Further quality-gate work is its base), #118 (the quality-gate paths), and #119 (the operating-system
`ai/quality-gate-paths` (draft #118), which classifies every remaining matrix with three module fixes, Decision 24 proposed). rc7 is not tagged or
unvisited path (the open items are the maintainer's decisions), and published. Stable Gallery version: 4.2.6.
`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.
After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). After 5.0.0, archive in favor of WindowsAccessControl (Decision 18).
## Recent milestones ## 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. Published rc6 live tests differed only in rc7's warning expectation.
- 2026-10-09: release attempt 2 succeeded; rc6 GitHub prerelease and zip - 2026-10-09: release attempt 2 succeeded; rc6 GitHub prerelease and zip
appeared at 07:01:34 UTC. #116 passed CI on `d25647d`. appeared at 07:01:34 UTC. #116 passed CI on `d25647d`.
- 2026-10-09: autonomous follow-up on `ai/quality-gate-coverage`, through - 2026-10-09: autonomous follow-up on `ai/quality-gate-coverage` (#117, then
`3442194`, adds 202 cases above rc7: deletion/owner failures, all 13 #120), through `3442194`: 202 cases above rc7 (deletion/owner failures, all
scopes, inheritance transitions, enumeration, forced replacement, 13 scopes, inheritance transitions, enumeration, forced replacement,
descriptor failures, and offline CI recovery. Reproduced/fixed rooted descriptor failures, offline CI recovery); fixed rooted result paths and the
result-path handling and first-hidden-item omission. Publication recovery first-hidden-item omission; publication recovery verifies the exact SHA-512
verifies exact SHA-512 identity, not merely version existence. identity, not merely the version. Suite: 914 per configuration, zero
- 2026-10-09: final uninstrumented suite: 914 per configuration, zero failures; 2,641/3,559 sequence points (74.21%), 974/1,933 branches (50.39%).
failures; coverage: 2,641/3,559 sequence points (74.21%) and 974/1,933 Live comparison, 09:20 to 09:51 UTC: candidate 330 passed, 0 failed, 2
branches (50.39%), aggregate of four runs without AltCover `--save`. expected skips; published rc6 only its four expected failures (`7594e0c`).
All skipped templates have executed counterparts. Mutation guards were - 2026-10-09: handoff 1 (#118): suite 914 to 1,310 per configuration, zero
proved and production source restored; Release build/checks pass. failures; 3,192/3,634 sequence points (87.84%), 1,273/1,978 branches; all 231
- 2026-10-09: live comparison, 09:20 to 09:51 UTC: candidate 330 passed, unvisited methods classified (223 explained, 8 open). Eleven defects fixed,
zero failed, two expected skips; published rc6 four expected Hidden/ ten with a guard that is red before the fix and green after it (76 rows red
warning-text failures only. Independent cleanup probes verified fixture at the base), among them a later command's exception that cmdlets swallowed
absence; raw host-verifier failures retained with corrected verification. (a `throw` made `Remove-Item2` remove the next item) and a privilege left
Lab guards/acceptance committed in `7594e0c`. One independent code review enabled. Lab acceptance, `83149ee` against `f11ff41`: 486 passed, 0 failed, 2
approved with no significant finding (custom model unavailable; built-in expected skips against 338 passed, 148 failed. Report in `Tests/Coverage`;
fallback). All 11 tested files match the ZIP. OS/path gates stay open. record `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`.
- 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 to 10: handoffs 2 to 4 under the maintainer's delegation (decisions - 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 D1 to D47 in the night log of the session files). The matrix lab
`NtfsSecurityOsMatrixLab` (Server 2019, 2022, and 2025 file servers, Windows 11 `NtfsSecurityOsMatrixLab` (Server 2019, 2022, 2025, a Windows 11 Enterprise
Enterprise 22H2 client, Windows 11 26H1 suite only) found three defects of the 22H2 client, Windows 11 26H1 suite only) found three module defects, fixed in
module, fixed in `962887a` and `fdd7a8b`: audit inheritance by descriptor, `962887a` and `fdd7a8b`: audit inheritance by descriptor,
`Get-NTFSEffectiveAccess -ServerName ''`, and the same cmdlet for a user who `Get-NTFSEffectiveAccess -ServerName ''`, and the same cmdlet for a
isn't an administrator on a domain member. The final candidate passes the non-administrator on a domain member. The final candidate passes the module's
module's suite on every machine (24 runs, no failure) and the live controller suite on every machine (24 runs), the live controller in three cells (1,374
in three cells (1,374 passed, 0 failed, 12 skipped) and in the first lab with passed, 0 failed, 12 skipped), and the first lab with case 9 (245 passed, 0
case 9 (245 passed, 0 failed, 1 skipped per edition). The failures of the failed, 1 skipped per edition). The Server 2022 effective-access failures
effective-access tests in the Server 2022 cell were not a defect of the module: were stale account state, not the module (a replay; the Windows mechanism is
in a replay of the same cells the baseline failed two of three and the final unknown); the controller names the case-3 account anew (`1dec389`). Built-in
candidate one of three (not counting the warm-up cell), and one model (the reviews: Minors corrected, one Major resolved by the replay, no Blocker; the
remote authorization managers answer for an account name for about ten minutes built-in security review found no exploitable vulnerability and two LOW items
after the account was created again) fits all 43 Admin-role runs of 27 cells; left for the maintainer. Record:
the Windows mechanism is unknown. The controller `Tests/Lab/Acceptance-2026-10-10-os-matrix.md`.
names the account of case 3 anew for each fixture (`1dec389`). A read-only - 2026-10-10: the maintainer integrated the stack. His branch deletion after the
built-in review of the kit and the fixes approved with Minor findings, fixed in merge of #116 (`8a6be9f`, 09:10:12Z) removed the base branch of #117, and
`db04ef2`. A second review of the later commits found one Major (the record GitHub closed #117 unmerged three seconds later instead of retargeting it
called the cause settled without a baseline replay), addressed by the replay, (`cli/cli#14223` shows the same events); the earlier guidance that relied on a
`9344ff7`, and `ab0d8e1`; a follow-up review of those fixes found no Blocker or retarget was wrong. Nothing was lost: #120 (`bdb9981`, 10:50Z) replaced #117,
Major and five Minors, corrected in `e2384e5` and `70f494a`; a second then #118 (`03bef2c`, 11:12Z) and #119 (`fa0701b`, 11:28Z) merged after their
follow-up review (the first-lab run and the cleanup changes) found no Blocker or retargeting; CI on `master` passed at 11:40Z. Decision 15 has the rule.
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).
## Stable capabilities ## Stable capabilities
@ -131,11 +99,11 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18).
## Open work ## Open work
1. Decision 21 gate: review Decision 22, integrate reviewed quality-gate 1. Decision 21 gate: tag and publish rc7, then test the published package
follow-up, publish the next candidate, and test the published package. (first lab, every matrix cell) and review Decision 22. Do not release 5.0.0
Do not release 5.0.0 until the remaining-path and OS-matrix gates close. until the remaining-path and OS-matrix gates close. Release steps:
Release steps: `Docs/Contributing/05-Releasing.md`; remove prerelease `Docs/Contributing/05-Releasing.md`; remove the prerelease label, date
label, date `[5.0.0]`, update `$publishedVersions`, tag through CI. `[5.0.0]`, update `$publishedVersions`, tag through CI.
2. Issues: #110's seven items were addressed by rc6, but #115 deliberately 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 used no closing keyword. #34 stays open for non-Windows owner feedback
or maintainer acceptance. #16, #21, #45, #89 await reporters. #68 tracks 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 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, by the lab. A conditional ACE display remains a .NET representation limit,
not evidence of unconditional permissions. not evidence of unconditional permissions.
8. Publication recovery is implemented locally in `95b827e`, with 14 offline 8. Publication recovery (`95b827e`, merged in #120): 14 offline tests and exact
tests and exact artifact SHA-512 verification. Original upload errors artifact SHA-512 verification; the original upload errors remain errors for
remain errors for missing/different/unverifiable outcomes. Not deployed missing, different, or unverifiable outcomes. The agent published nothing,
until the maintainer merges/pushes; no publication was performed here. so the recovery has never run against the Gallery.
9. Operating-system matrix (Decision 24, proposed): the lab and the cells exist 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 and the candidate passes them; the published rc7 still needs its acceptance
published rc7 in every cell, keeping or replacing the VMs (about 60 GB) and in every cell. #34 has no new reply since 2026-10-06.
the evaluation client (it shuts down every hour), which module fixes go to 10. Lab rollback evidence: new checkpoints report Standard even after a
rc7, and a domain cell for Windows 11 26H1. #34 has no new reply since successful temporary ProductionOnly probe; original VM policy restored, no
2026-10-06. checkpoint restored. Don't represent them as verified Production snapshots.
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.

99
.memory-bank/systemPatterns.md

@ -1,6 +1,6 @@
--- ---
status: current status: current
last-verified: 2026-10-09 last-verified: 2026-10-10
owner: active-agent owner: active-agent
source: repository and regression evidence 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. - Pipeline getters never throw; per-item errors name input and allow continuation.
- Folder moves never use CopyAllowed; preserve cross-volume source folders. - Folder moves never use CopyAllowed; preserve cross-volume source folders.
- Apply implied Hidden/Force before deciding to emit, including the first item. - 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 - A catch-all for one item's failures passes on what a later command raises
raises through a Write call. A downstream throw is an ordinary exception, through a Write call (`IsFromLaterCommand`, `PipelineControl`; see
so a type check finds only the end of the pipeline, break, and continue. `BaseCmdlets.cs`); add a row to `Tests/PipelineControl.Tests.ps1` for a new
BaseCmdlet notes the exception that its WriteObject, WriteError, cmdlet. Record an enabled privilege before the next write.
WriteVerbose, and WriteDebug raised (WriteWarning is not noted: no catch-all - `Get-ChildItem2 -Filter` has two matchers (AlphaFS, then a wildcard on the
encloses it); `IsFromLaterCommand` recognizes it, and the type check name); `*.*` means `*`, other dot patterns are an open decision.
`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.
### Tests and documentation ### Tests and documentation
- Tests import Release in isolated processes, both editions and privilege - Tests import Release in isolated processes, both editions and privilege
modes. File/ACL/link fixtures use shared sandbox guards and cleanup. modes, with guarded sandboxes; a skip needs an eligible counterpart.
Privilege-dependent skips must have eligible counterparts in the matrix.
- Assert persisted state, errors/targets, continuation, and no failed - Assert persisted state, errors/targets, continuation, and no failed
PassThru output. Prove new characterization guards with bounded mutations; PassThru output. Prove new characterization guards with bounded mutations
restore source exactly and rebuild before green validation or packaging. (one round together only if no guard can fail because of another); restore
Apply the mutations of one round together only when no guard can fail source exactly and rebuild before green validation or packaging. A retry
because of another mutation; otherwise split the rounds. test asserts its precondition (the plain write is denied).
- A test that arranges a retry asserts its precondition (the plain write is - CI scripts and focused runs set `Stop`: a test that needs a non-terminating
denied), or it can pass without reaching the retry. error names `-ErrorAction Continue`. Don't name a test variable like an
- A test variable must not take the name of an automatic variable such as automatic variable (`$foreach`): Pester runs the block inside a foreach.
`$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`.
- Fixture DACLs use .NET SetAccessControl, not Set-Acl's unintended SACL writes. - Fixture DACLs use .NET SetAccessControl, not Set-Acl's unintended SACL writes.
- Scope/descendant expectations are independent of the production converter. - Scope/descendant expectations are independent of the production converter.
- Drive-root tests map a sandbox folder with `subst` through - Desktop platyPS: generate help, rebuild, round-trip unchanged, check links;
`New-TestDriveMapping` (elevated only; the basic token cannot). Tests that platyPS 0.14.2 turns paired asterisks into emphasis, even in backticks.
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.
- Live tests use only approved lab targets, SMB then independent server state; - Live tests use only approved lab targets, SMB then independent server state;
Get/SetFileSecurity preserves stored DACLs; rights oracles use S4U tokens. 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 - A suite that is green on the host and CI misses defects that need a domain
feature that the environment lacks. The matrix found three defects that every member or another token (the matrix found three): also run a domain member,
earlier run had missed because the host is outside a domain and the CI other builds, and a basic user. A failure that follows cell order, not
runner's token differs: run the suite on a domain member, on other builds, and version, points to stale account state (Decision 24): alternate the cells.
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.
### CI results and publication ### CI, publication, and integration
- Use Path.Combine then GetFullPath for a rooted-or-repository-relative - Discovery treats only PackageNotFound as absence. Rerun/uncertain-upload
result path; Join-Path appends even a rooted child and corrupts it. success needs Gallery SHA-512 equality with the exact build artifact
- Discovery handles only expected PackageNotFound as absence; repository, (ordinal Base64); anything else preserves the upload error. Secrets stay
authentication, and network errors remain failures. environment references; mock all publication commands, no test uploads.
- Rerun/uncertain-upload success requires Gallery SHA-512 equality with the - Gate prompts are self-contained: pins are historical, state is rechecked,
exact build artifact. Base64 is case-sensitive: use ordinal comparison. completion is evidence, risk acceptance is no test pass. In a stack of pull
Missing/different/unverifiable metadata preserves the upload error. requests, retarget each to `master` before merging the one below; delete a
- Secrets stay by environment reference, never in process arguments/logs. head branch only when no open pull request uses it as its base (Decision 15).
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.

195
.memory-bank/techContext.md

@ -1,6 +1,6 @@
--- ---
status: current status: current
last-verified: 2026-10-09 last-verified: 2026-10-10
owner: active-agent owner: active-agent
source: repository and executable evidence 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. 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. - GitHub CLI: `C:\Program Files\GitHub CLI\gh.exe`, signed in as raandree.
Read-only queries work; remote mutations belong to the maintainer. Read-only queries work; remote mutations belong to the maintainer.
- LabSources: `V:\LabSources`. All 13 deployed machines are Server 2025. - LabSources: `V:\LabSources`. The first lab's machines are Server 2025; the
Windows 11 consumer/enterprise-evaluation media and Server 2019/2022 matrix lab `NtfsSecurityOsMatrixLab` adds Server 2019/2022 and Windows 11.
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.
## Constraints ## Constraints
- Source manifest: ModuleVersion 5.0.0, prerelease rc7 on #116/follow-up. - Manifest: ModuleVersion 5.0.0, prerelease rc7 (on `master` since
Latest stable: 4.2.6; latest published prerelease: rc6 (2026-10-08). 2026-10-10, untagged). Latest stable 4.2.6; latest published prerelease
GitHub rc6 release recovered 2026-10-09. rc7 publication is pending. rc6 (2026-10-08). rc7 publication is pending.
- Changed-section writes preserve unchanged owner/group/DACL/SACL (19). - Changed-section writes preserve unchanged owner/group/DACL/SACL (19).
Roots use root-folder APIs, not AlphaFS device security (#41). Roots use root-folder APIs, not AlphaFS device security (#41).
- CHANGELOG contains user-visible changes only (7); tests and CI-only fixes - 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. Issue references use no closing keyword unless closure is intended.
- Lab passwords stay in memory and are lab-only; no secret in repository, - 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. 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 ## Build and focused checks
@ -94,14 +90,11 @@ source: repository and executable evidence
- Packaging needs Compress-PSResource (Core 7.4+). New-ModulePackage copies - Packaging needs Compress-PSResource (Core 7.4+). New-ModulePackage copies
only FileList, validates the manifest, creates nupkg plus NTFSSecurity.zip. only FileList, validates the manifest, creates nupkg plus NTFSSecurity.zip.
Check package/file hashes and test the extracted artifact, not build extras. Check package/file hashes and test the extracted artifact, not build extras.
- Release runs only for validated version tags in powershell-gallery. - Release runs only for validated version tags in powershell-gallery; the API
API key stays as PSGALLERY_API_KEY environment reference. Helper key is the environment secret PSGALLERY_API_KEY. The rules of
Publish-ModulePackage treats only PackageNotFound as expected absence; `Publish-ModulePackage` are in `systemPatterns.md`. Read status through
existing-version skip and uncertain-upload recovery require exact Gallery `gh pr checks` and `gh run view --log-failed`. A successful Gallery upload
SHA-512 equality. Base64 comparison is case-sensitive. Unverifiable, followed by HTTP 409 does not prove its retry chronology.
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.
## Coverage and test eligibility ## Coverage and test eligibility
@ -112,45 +105,35 @@ source: repository and executable evidence
four configurations sequentially with the real CI wrappers, then four configurations sequentially with the real CI wrappers, then
AltCover runner --collect recalculates the report. Compute option paths AltCover runner --collect recalculates the report. Compute option paths
before passing native arguments, not inline Join-Path expressions. before passing native arguments, not inline Join-Path expressions.
- Report sequence points, not unique source lines. Four-run baselines: - Report sequence points, not unique source lines. Four-run baselines: rc5
rc5 2,020/3,476 (58.1%), branches 711/1,873 (38.0%); 2,020/3,476 (58.1%); rc6 2,412/3,540 (68.14%); `3442194` 2,641/3,559
rc6 2,412/3,540 (68.14%), branches 850/1,918 (44.32%); (74.21%); `5a5d58b` 3,192/3,634 (87.84%), branches 1,273/1,978 (64.36%).
follow-up `3442194` 2,641/3,559 (74.21%), 974/1,933 (50.39%); The code changes the denominators: never present these as same-source
Handoff 1 `5a5d58b` 3,192/3,634 (87.84%), 1,273/1,978 (64.36%). Different increments. The branch summary counts 820 compiler-generated points; report
code changes denominators; never present these as same-source incremental the explicit branch points too (1,088/1,158, 93.96%). Suite at `5a5d58b`:
percentages. The branch summary counts 820 compiler-generated points (185 1,310 per configuration, zero failures (skipped: 24 and 55 elevated, 234
visited); report the explicit branch points as well (1,088/1,158, 93.96%). and 265 basic, Desktop and Core).
- 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.
- NUnit skipped ForEach names retain placeholders and parameter tuples, - NUnit skipped ForEach names retain placeholders and parameter tuples,
executed names expand them; raw-name intersection and positional alignment executed names expand them: raw-name intersection and positional alignment
are invalid. Skip eligibility is checked by row: run the suite once per are invalid. Check skip eligibility by row: run the suite once per
configuration with Pester PassThru (`Get-DiscoveryRows2.ps1 -Run` in the configuration with Pester PassThru and match skipped with executed rows by
session evidence) and match skipped with executed rows by file, line, file, line, path, name, and data (discovery alone misses tests that skip
path, name, and data. Discovery alone misses tests that skip themselves while running; write primitives, as `ConvertTo-Json` of rich rows hangs).
while they run, and `ConvertTo-Json` of rich data rows never finishes:
write primitives and type names.
- Remaining inventory: 442 points in 231 methods, classified by rule with - Remaining inventory: 442 points in 231 methods, classified by rule with
evidence (probe, IL scan, source reading); see `Tests/Coverage`. Preserve evidence (probe, IL scan, source reading); see `Tests/Coverage`. Preserve
raw XML, row CSVs, logs, commit identity, and build hashes. The frozen 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 Build rewrites its hash file, so save the hashes of the measured assemblies
assemblies (AltCover `__Saved` copies) before any mutation build. (AltCover `__Saved` copies) before any mutation build.
- Bounded mutations: one script per round on the frozen worktree, with - Bounded mutations: one script per round on the frozen worktree, with guards
guards that no other mutation of the round can trip (an escape can be an that no other mutation of the round can trip (an escape can be an overlap
overlap or an equivalent mutant: check before changing a test). Restore or an equivalent mutant: check before changing a test). Restore the source
the source exactly and rebuild. exactly and rebuild.
- Red/green matrix, to show afterwards that a guard fails without its fix: - Red/green matrix (a guard fails without its fix): build each state of the
build each state of the branch (base, then each fix commit) in its own branch in its own Release worktree, lay the final `Tests` over it, run the
Release worktree, lay the final `Tests` over it (`git checkout <final> -- guarding files with the focused runner in all four configurations, and count
Tests`), run the guarding files with the focused runner (it sets failed rows per name with multiplicity; the last state is the control. Keep
`$ErrorActionPreference` to `Stop` like the CI wrappers) in all four the logs, a manifest with hashes, and the hash of each build: the first red
configurations, and count failed rows per name with their multiplicity (a runs of Handoff 1 were deleted and could not be reproduced.
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.
## Lab acceptance ## Lab acceptance
@ -159,36 +142,31 @@ source: repository and executable evidence
Controller accepts alternate machines; changing topology/OS scope waits Controller accepts alternate machines; changing topology/OS scope waits
for a maintainer decision. Do not repurpose another project's shared VMs. for a maintainer decision. Do not repurpose another project's shared VMs.
- Before a run: authenticated WinRM, LDAP RootDSE, Kerberos tickets, member - Before a run: authenticated WinRM, LDAP RootDSE, Kerberos tickets, member
secure channels, clocks; checkpoint only approved targets. Inspect actual secure channels, clocks; checkpoint only approved targets. New checkpoints
checkpoint kind: new checkpoints reported Standard even after a successful report Standard even after a successful ProductionOnly request (policy
temporary ProductionOnly request. Policy restored; no rollback performed; restored, no rollback): Production is unverified, not a passed safety check.
Production classification remains unverified, not a passed safety check.
- Run Tests\Lab\Invoke-NTFSSecurityLabTest.ps1 in elevated Desktop with - Run Tests\Lab\Invoke-NTFSSecurityLabTest.ps1 in elevated Desktop with
-Version for hash-checked Gallery packages or -ModulePath for the extracted -Version for hash-checked Gallery packages or -ModulePath for the extracted
build artifact, both editions. Per version/edition: Delegate, ServerAdmin, build artifact, both editions. Per version/edition: Delegate, ServerAdmin,
Admin on client, then Server independently checks persisted state. Admin on client, then Server independently checks persisted state.
- Controller writes Summary.json even when tests fail: validate every role, - Controller writes Summary.json even when tests fail: validate every role,
exit code, failure name, and total; DONE alone is not acceptance evidence. exit code, failure name, and total; DONE alone is not acceptance evidence.
Desktop ConvertFrom-Json can wrap arrays; explicitly enumerate the result Desktop ConvertFrom-Json can wrap arrays: enumerate the result and compare
and compare full Describe-prefixed names. Never gate cleanup on the global full Describe-prefixed names. Never gate cleanup on the global Error.Count
Error.Count, which includes handled errors; independently verify footprint. (it includes handled errors); verify the footprint independently.
- Remote Authz answers administrators and Access Control Assistance - Remote Authz answers administrators and Access Control Assistance
Operators (S-1-5-32-579); other accounts get access denied. Check firewall Operators (S-1-5-32-579); other accounts get access denied (check the
when remote resource-manager RPC fails. Expected rights use S4U tokens. firewall when its RPC fails). Expected rights use S4U tokens. A domain
A computer in a domain offers the remote interface to every caller, so the member offers the remote interface to every caller, so the default
denial also hit the default `-ServerName localhost` for a user who isn't an `-ServerName localhost` was denied for a non-administrator; hosts outside a
administrator; a computer outside a domain doesn't offer it, which is why the domain don't, so the host and CI missed it. Since `fdd7a8b` the local
tests passed on the development host and on CI. Since `fdd7a8b`, the local manager answers for a name of this computer; another computer stays denied.
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).
- A live test is evidence of a fix only when it fails on the build without - 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 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 the base, a new process per edition, and join the results by edition, role,
sets by edition, role, and full test name; the tests that pass on both are and full test name; tests that pass on both are controls (record of
controls (`Tests\Lab\Acceptance-2026-10-09-quality-gate-paths.md`). A 2026-10-09). PowerShell variables ignore case: `$edition` overwrote
validator must not name a loop variable like a typed parameter: PowerShell `$Edition`.
variables ignore case, so `$edition` overwrote `$Edition` and every edition
in the CSV became `System.String[]`.
- RemoveFixture after the run; verify OUs/accounts, share, folders, local - RemoveFixture after the run; verify OUs/accounts, share, folders, local
memberships, and test profiles removed. Credentials must never be printed. 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 - Lab `NtfsSecurityOsMatrixLab`: OSDC1 (Server 2025), OSFile19/22/25 (Server
2019/2022/2025), OSWin11E (Windows 11 Enterprise Evaluation 22H2, the domain 2019/2022/2025), OSWin11E (Windows 11 Enterprise Evaluation 22H2, the domain
client), OSWin11 (Windows 11 Pro 26H1, suite only). Kit: `Tests\Lab\Acceptance`; client), OSWin11 (Windows 11 Pro 26H1, suite only). Kit
record: `Tests\Lab\Acceptance-2026-10-10-os-matrix.md`. `Tests\Lab\Acceptance`; record
- Run the module's own suite on every machine class before the controller `Tests\Lab\Acceptance-2026-10-10-os-matrix.md` (procedure, limits);
(`Run-MatrixLocalSuite.ps1`, elevated and basic, both editions, as scheduled the lessons of building it are in `deployment-notes.md`.
tasks with a batch logon at the highest run level): a child of a remoting - Run the module's own suite on every machine first (`Run-MatrixLocalSuite.ps1`
session has every privilege enabled and fails eight tests that expect them as scheduled tasks with a batch logon at the highest run level; a remoting
disabled. Skipped lists are compared as multisets against the host. child has every privilege enabled). One `Import-Lab` at a time. Compare skips
- AutomatedLab: one `Import-Lab` at a time, and none while a controller as multisets against the host. Hash each candidate and its package: builds
sequence runs (it re-imports the lab); `Wait-LabVM` waits for a heartbeat that aren't byte-reproducible.
a client may not report, so retry `New-LabPSSession`. The host's `bcdboot` - The 26H1 client can't keep its secure channel to a Server 2025 DC (suite
leaves the ESP of a Server 2019 or Windows 11 22H2 base image empty. only); the 22H2 evaluation client shuts down every hour: keep a run under an
- Windows PowerShell 5.1: `$PSScriptRoot` is empty in a parameter default under hour and test a domain session, not `nltest /sc_verify`.
`-File`; `2>&1` on a native command under `Stop` makes its stderr line - A fixture that re-creates an account name gets stale answers for about ten
terminating; `Get-LocalGroupMember` fails on an orphaned SID; `net localgroup minutes, for the baseline and the candidate alike (mechanism unknown; no
<name> <SID> /delete` refuses the SID of a name that its cache still remedy but waiting). The controller names the case-3 account anew for each
resolves (use `Remove-LocalGroupMember -SID`). fixture; the replay and the model are in the record. `Test-MatrixCleanup.ps1`
- Windows 11 26H1 (28000.1836) loses the secure channel to a Server 2025 domain verifies and repairs the probe's profiles and group entries.
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.

Loading…
Cancel
Save