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 1 day 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
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 <n> --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.

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
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 <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)
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.

158
.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.

99
.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).

195
.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 <final> --
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
<name> <SID> /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.

Loading…
Cancel
Save