Skip to content

fix(libkernel): classify Windows directory links by app0 scope - #8726

Merged
oneandonlydean merged 3 commits into
boykopovar:mainfrom
ArjenS-LA:fix/windows-directory-link-types
Oct 26, 2026
Merged

oneandonlydean merged 3 commits into
boykopovar:mainfrom
ArjenS-LA:fix/windows-directory-link-types

Conversation

@ArjenS-LA

@ArjenS-LA ArjenS-LA commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What

Windows directory enumeration classifies links by canonical app0 scope: live links inside that root report their target type, while dangling links and links outside it remain DT_LNK. Failed initial stat returns DT_UNKNOWN, and the directory snapshot is published only after collection succeeds. This follows the reviewed resolved-path scope.

The test correction in c5229e510a4b463fd4f6d39f017793d753f7c86b uses Windows backslashes for relative symbolic-link targets and RemoveDirectoryW/DeleteFileW for cleanup of dangling and looping reparse points. Production code is unchanged from 4fb4187bd327a33cb139959d596c46782c3ac08d.

Tested

Windows x64, supported MinGW-w64 GCC 15.2.0: both the previous and corrected fixtures freshly compile and pass the junction cases against the same preserved libraries from 4fb4187. Both leave no test directories behind. Native symbolic-link cases skip because the user token lacks symbolic-link privilege, so the reviewer’s failure is not independently reproduced locally. JJenkx reported five failing runs followed by five passing runs with these exact test edits and symlink cases enabled. His offered rerun on this corrected head remains pending.

The branch and current-main conventions checkers pass, as does whitespace validation. No full build, full CTest, homebrew or GPU run was repeated for this test-only correction. Full Linux/Windows CI still needs a collaborator-triggered run for the new head; the previous successful Build workflow skipped its platform test jobs.

Earlier implementation validation at 4fb4187 remains applicable to the unchanged production code: full build and explicit libraries build passed; CTest reported 1,882 passes, 6 skips and 3 unresolved GPU sample-order failures. Released Prospero Explorer v1.0 (PPSA99109) execution, with disclosed host-added junction and removable-file fixtures, showed app0 junction type 4 and DT_UNKNOWN for the disappearing entry. Original package bytes were unchanged; decrypted inputs were converted separately. This established directory-response behavior under those accommodations, not gameplay or physical-console behavior.

Current overlap check: main c8d34aa8f4d8058d57169cc1e423ba6db00faaf0, corrected head c5229e510a4b463fd4f6d39f017793d753f7c86b, 1,288 open PRs with complete paginated changed-file lists. This PR merges cleanly with main. Tree-only comparisons of 129 shared-file peers yielded 89 clean pairs, 3 conflicts and 37 inconclusive pairs because the peer already conflicts with main. No other open PR changes the Windows link fixture. Source review was selective; combined runtime compatibility is unverified.

Peer Checked head Existing conflict
#8520 0a64d23bdf502e32b1857009a5227634d4a53f16 core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp
#9732 acac3b1c00a97443536b6697bb2f7ad46a0c57b5 docs/dev/debt/libkernel.md
#10121 e9b842569aaf59e5b1282b2637b10e94d589109b docs/dev/debt/libkernel.md

#8520 integration must preserve archive/disk enumeration, inode/cursor handling, canonical-app0 target typing, failed-stat DT_UNKNOWN and complete snapshot publication. Its ordering discussion remains pending. #9732’s author agreed to #8726 first, then rebase while retaining both debt entries. #10121 ordering remains pending; both adjacent debt entries must survive. The test correction does not alter these existing overlaps. The complementary Linux PR #9303 has merged.

Checklist

  • Based on current main; no other open PR implements the same functions — tested merge against the exact main above; overlapping implementation and integration limits are disclosed.
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; unsupported classifications remain explicit
  • No notes, investigation Markdown files or images added to the repository
  • New third-party code is a submodule built from source — none added
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a — directory enumeration change
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the current diff and test report. Deriving the getdents entry type from the same no-follow FillLinkStat classification used by lstat correctly distinguishes ordinary files/directories from normal, dangling, and self-loop junctions. Load builds a temporary snapshot and only publishes it after every entry is classified, so an unsupported reparse type does not leave a partially loaded directory. The author reports the Windows junction regression failing on baseline and passing on the PR, plus the full CTest delta with only identical pre-existing failures. Hosted conventions/eligibility/intake/labels pass; platform build jobs are skipped. I did not run a local Windows build. AI-assisted review.

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 8520 core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp L6-15, L34, L52, L55-59, L61-65
PR 9732 docs/dev/debt/libkernel.md L159-160
PR 9947 core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp L57-64
PR 10121 docs/dev/debt/libkernel.md L159
PR 11311 core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp L12, L34-35, L52, L57-59, L62-64

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 4563 core/libs/prx/libkernel/CMakeLists.txt
PR 4630 docs/dev/debt/libkernel.md
PR 5021 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6740 docs/dev/debt/libkernel.md
PR 6830 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6936 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7201 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7804 docs/dev/debt/libkernel.md
PR 8010 docs/dev/debt/libkernel.md
PR 8605 docs/dev/debt/libkernel.md
PR 9156 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9284 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9293 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9297 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9302 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9383 core/libs/prx/libkernel/CMakeLists.txt
PR 9389 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9509 docs/dev/debt/libkernel.md
PR 9557 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9566 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9575 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9669 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9693 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10319 docs/dev/debt/libkernel.md
PR 10442 docs/dev/debt/libkernel.md
PR 10621 docs/dev/debt/libkernel.md
PR 10666 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10755 core/libs/prx/libkernel/CMakeLists.txt
PR 10898 docs/dev/debt/libkernel.md
PR 11002 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11047 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@ArjenS-LA Thanks. Deriving the type from FillLinkStat is the right source, and publishing the snapshot only after classification is careful.

One request about the new failure path. EntryType throws when FillLinkStat fails. That can happen for an entry that's deleted between the directory listing and the stat (another thread or process cleaning up a temp or save directory), or one the host refuses to stat. main gave such an entry a type and carried on, so the whole getdents call would now end the process instead. FreeBSD has DT_UNKNOWN (0) for an entry whose type isn't known. Could a failed stat give DT_UNKNOWN (or skip an entry that no longer exists) instead of throwing? Keep NotImplemented for a type that really is unsupported.

After that, the bar is a full CI run with guest_directory_link_types and the existing directory-entry tests passing on Linux and Windows.

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

I reproduced the stat race in Prospero Explorer 1.0 (PPSA99109) and prepared the narrow fix: failed FillLinkStat returns DT_UNKNOWN (0), while unsupported types and reparse points still take the existing NotImplemented path.

Using the same shipped Explorer package and workload, a debugger breakpoint removes one added host fixture immediately before stat. Published head b898b072bb9429390537d78cfd074a6d95349b1a aborts with directory entry type: No such file or directory; the rebuilt kernel returns that entry with type 0. No guest memory/register writes or injected guest calls were used. Original package bytes stay unchanged; the prior unwrapped copies/relinker and baseline library snapshot are reused, with only the rebuilt kernel substituted for the fixed run. This proves the observed directory-enumeration path under that disclosed race fixture, not general startup/gameplay or console behavior.

Windows x64, MinGW-w64 GCC 15.2.0: the same six directory regression executables pass with both baseline and fixed libraries. Junction cases executed; optional symbolic-link subcases skipped because the host lacks that privilege. The explicit libs build passes. The full build retains the previously recorded unrelated ImageArrayWindowPastLayerLimit.cpp error (65536-byte requested alignment exceeds the 8192-byte object limit). Native CTest: 1548 passed, 1 failed, 18 skipped; 221 script-driven or unavailable tests were excluded. Failed native tests: agc_driver_lookup_log_fits_build. The AGC failure passes on isolated reruns of both baseline and fixed builds; the original parallel-suite failure remains recorded, with its cause unresolved. guest_audio3d_port exceeded 30 seconds locally (49.31 s); no test timeout or unrelated source was changed. GPU used by broad native tests: NVIDIA GeForce RTX 4070 SUPER, Windows driver 32.0.16.1088. This is not a clean complete-suite result or a fresh full baseline comparison.

The patch is still local and uncommitted (base above; tree 54371a619e665444cc3e0a0684feee40a2b57fdc). Four repository commits from today are visible, but the coordinator records do not certify the combined count including disposable test commits across sessions, so the daily commit rule prevents creating another commit. Full Linux/Windows CI also remains outstanding: this account has no upstream workflow-dispatch/write permission, so a collaborator will need to run it after an update is publishable. I have not pushed this fix. The patch and exact commands, hashes and logs are preserved in .codex/pr-maintainer/logs/pass-20261020T2338Z; the worktree is .codex/pr-maintainer/worktrees/pr-8726-20261020.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@ArjenS-LA thanks for this. For links the guest makes itself, DT_LNK is what FreeBSD reports, so that part is right. The problem is /app0. A real app0 never contains links, so any link in it comes from how the host built the app0 directory, and a title enumerating it expects the target's type.

We have a concrete case of this on Linux, where main's getdents already passes the host type through. PPSA04263 crashes at about 0 s when its top-level app0 directories are symlinks into the dump, and it runs when they are real directories. The title lists /app0 and only walks into entries typed DT_DIR. With the links typed 10, it never opens any of them, and it crashes on startup. Symlinked files are fine, because they're opened by name and open follows the link.

Today Windows reports a junction to a directory as 4, so a junction-built app0 works there. After this change it would report 10, so the same title would see the same listing on Windows (we haven't run it there). Your Explorer row shows the switch on /app0 itself (junction-fixture: type=4 → type=10).

Could you keep the target's type inside the app0 tree? For an entry under /app0 whose FillLinkStat mode is a link, resolve it (the following stat) and return 4 or 8 for the target. Keep 10 when the link dangles, and keep 10 everywhere outside app0 (/data, /download0), where the guest can create links. The fixture then needs its junction outside app0 to check 10, plus one junction inside app0 that must come back as 4.

We're making the matching change to the Linux path, so both platforms will treat app0 the same way.

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@oneandonlydean I reproduced the Windows part with a focused native junction fixture on Windows x64 / MinGW-w64 GCC 15.2.0. Against the published b898b072bb9429390537d78cfd074a6d95349b1a kernel snapshot, enumeration through /data passes with type 10, while enumeration through /app0 fails with junction: getdents type 10, expected 4. The existing local DT_UNKNOWN stat-race patch gives the same results, so it does not address this additional regression. These are synthetic native tests, not PPSA04263 or fresh Explorer execution; optional symbolic-link cases skipped for lack of Windows privilege, while junction cases executed.

There is a path-tracking detail to coordinate: Load obtains the resolved host path with GetFinalPathNameByHandleW, and OpenInDirectory_nid_no_patch likewise opens relative to that resolved path. A host-path prefix check alone can lose the /app0 origin after entering a junction whose target is outside the mapped root. Can you link the matching Linux change so I can align the Windows directory-origin tracking with it? The /app0 request remains unresolved and no updated kernel commit has been pushed.

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@oneandonlydean I found the matching Linux change in #9303 at 58ad4eda77577412aab42a180a82fc164d1cfab1. Its resolved-descriptor-path check explicitly leaves nested links typed DT_LNK after entering an app0 link whose target is outside the canonical app0 root.

Should the Windows correction mirror that documented limitation, or must it preserve the guest /app0 origin across those directory opens? This determines whether a resolved-path check is sufficient or directory-origin tracking must change.

Both PRs also add different implementations of core/libs/tests/GuestDirectoryLinkTypes.cpp. I propose keeping the Windows fixture in a separate Windows-specific source file when integrating the correction. The published head remains b898b072bb9429390537d78cfd074a6d95349b1a; this update is source/merge inspection only, with no new runtime result or pushed fix.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@ArjenS-LA Mirror the #9303 limitation; don't add directory-origin tracking in this PR.

#9303 decides "inside /app0" from the resolved descriptor path (weakly_canonical of /app0 plus the directory's resolved path), as your GetFinalPathNameByHandleW check would. With it, links that sit directly in /app0 or in a directory below it, links to links, relative links and an /app0 that is itself a link all report as directories. Entries inside a directory that an app0 link led outside the root stay DT_LNK. That nested case is documented in the debt doc and no title we have run needs it, while tracking the guest origin across every directory open adds state to each descriptor for a case nobody has hit. If a title does need it, that is a separate change for both platforms.

So on Windows the /app0 junction enumeration should report type 4, like the Linux fixture, and a junction that leads outside the root and holds further links should stay type 10, with the limitation worded the same in docs/dev/debt/libkernel.md. I haven't run the Windows side myself, so your fixture is the evidence there.

Keep the Windows fixture in its own source file. #9303's GuestDirectoryLinkTypes.cpp is the Linux test (skipped elsewhere), so two different files under one name would only collide.

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@oneandonlydean The local correction now mirrors #9303's resolved-path limitation. It follows live links when the enumerated directory resolves inside canonical /app0, retains DT_LNK for dangling links and nested links reached outside that root, and keeps the earlier DT_UNKNOWN stat-failure correction. The Windows fixture is now GuestWindowsDirectoryLinkTypes.cpp, with its own test name.

Windows x64 / MinGW-w64 GCC 15.2.0 results:

  • The identical expanded native fixture fails against published head b898b072bb9429390537d78cfd074a6d95349b1a (app0 junction type 10 instead of 4) and passes against the draft. It covers outside-app0 links, chained junctions, dangling/loop junctions, nested external targets, a sibling-path boundary, and app0 itself being a junction. Optional symbolic-link subcases skip because this host lacks the privilege.
  • All six existing directory regression executables pass with both library versions.
  • Fresh execution of the same Prospero Explorer 1.0 / PPSA99109 package changes its added app0 junction response from type 10 to 4. The controlled disappearance fixture aborts on the published kernel and returns type 0 on the draft. Original package hashes remain unchanged. This observes directory responses, not gameplay or console behavior.

This is still an uncommitted draft, tree 9899b6e7b8014a74a472725b97978bcfc26f4267, based on the published head; nothing has been pushed. Validation rebuilt the changed kernel object and relinked it with preserved same-base build objects, including the required Windows unwind processing. It is not a clean full build/CTest result. Full validation and collaborator-run Linux/Windows CI remain outstanding, and combined daily commit accounting is still uncertified.

The draft merges textually with main 4a17c71757644170c6a0acfcc67fb17f81cff93f and #9303 58ad4eda77577412aab42a180a82fc164d1cfab1; those integrations have not been runtime tested. The wider audit retains a documentation conflict with #9239 and 22 inconclusive kernel comparisons because peers conflict with main. Patch, commands, binary/input hashes and logs: .codex/pr-maintainer/logs/pass-20261022T0534Z. AI-assisted.

@ArjenS-LA ArjenS-LA changed the title fix(libkernel): report Windows directory links in getdents fix(libkernel): classify Windows directory links by app0 scope Oct 22, 2026
@ArjenS-LA
ArjenS-LA force-pushed the fix/windows-directory-link-types branch from b898b07 to 4fb4187 Compare October 22, 2026 07:36
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 22, 2026
@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@simonbronk I checked the #9732 overlap with Git's merge engine against main 8b3a6ba88d8fc74e768f1a7e8e9e36fb69842768, normalizing both PRs onto that same base. #8726 at 4fb4187bd327a33cb139959d596c46782c3ac08d and #9732 at eb900c3d7a08388d9df34b9b1b4bd3799f8eade4 each merge with main, but their combined tree conflicts in docs/dev/debt/libkernel.md.

This is an adjacent documentation edit: the Windows directory-type entry is inserted immediately before your revised vector-I/O entry. Both entries should survive; the implementation files are separate.

I propose #8726 first, then rebasing #9732 while preserving both entries. Does that order work for you? Maintainers retain the final choice; no dependency has been declared before agreement. This check used source inspection and tree-only merges, with no new commits, builds or runtime tests.

@MarcZX10

Copy link
Copy Markdown
Contributor

Open #9732 changes the vector-I/O debt entry in docs/dev/debt/libkernel.md; pairwise merge of the current heads conflicts in that file, though the implementation topics are independent. Please coordinate merge order with #9732 and preserve both documentation entries when rebasing. No duplicate implementation was found in the code paths.

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Independent Windows run, as data only. Machine: Windows 11 Enterprise 10.0.22621, WinLibs GCC 15.2.0 UCRT r7, Release. Head 4fb4187 was merged onto main b7d1d47. CreateSymbolicLinkW with SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE succeeds on this machine, so the symbolic-link subcases run. Your description says the executed cases were junction cases, so they may not have run there.

guest_windows_directory_link_types fails in 5 of 5 runs, for two separate reasons:

  1. Test cleanup (line 117, and the same pattern at line 191): std::filesystem::remove(root / name) returns false for dangling-junction. The junction entry before it is removed, and dangling-junction, loop-junction and the symbolic links are left behind. Every getdents and lstat check before that line passed. This libstdc++ doesn't classify reparse points with a missing or looping target, the same issue as in test(libc): run guest_fopen_errors on Windows #9583. With line 117 changed to RemoveDirectoryW(path) != 0 || DeleteFileW(path) != 0, the whole outside-app0 part passes. Each failed run leaves an anyps5-app0-links-<n> directory under build/core/libs/prx/libkernel.

  2. The app0 symbolic-link subcase (line 184): with cleanup patched, the run gets further and prints:

    app0 packed/chain/real types: 4/4/4 (expected 4/4/4)
    app0 file-link/relative types: 10/10 (expected 8/4)
    

    So inside canonical /app0 the junctions are classified as the PR describes, but the native symbolic links app0/file-link (to ../external/regular) and app0/relative (to ../external, directory) still come back as DT_LNK. Both are relative targets that leave app0, unlike the junctions, whose targets are absolute. That may be the difference, but I haven't traced it in DirectoryDescriptor.cpp.

AI-assisted (Claude Code).

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Correction to point 2 of my comment above: the app0 10/10 result comes from the test's own links, not from this PR's classification.

The test creates app0/file-link and app0/relative with forward-slash relative targets (L"../external/regular", L"../external"). Windows doesn't resolve a symbolic-link target written with /, so both links are effectively dangling, and DT_LNK is the right answer for them. A standalone program on the same machine and toolchain shows it:

  • with the targets as written, CreateFileW (no FILE_FLAG_OPEN_REPARSE_POINT) and _wstat64 fail with ENOENT on both links, whatever the current directory;
  • with L"..\external\regular" and L"..\external", both resolve: a regular file (100666) and a directory (40777).

So the fix belongs in the test: write those two targets with backslashes. Point 1, the std::filesystem::remove cleanup, still stands. I'll rerun the full test with both changes once my build tree is free and post the result.

AI-assisted (Claude Code).

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Follow-up: same machine and merge (head 4fb4187 on main b7d1d47), with only these test changes. Both cleanup loops delete links without following them, and the two app0 symbolic-link targets use backslashes:

-    for (const auto& name : links) Require(std::filesystem::remove(root / name));
+    for (const auto& name : links) Require(RemoveDirectoryW((root / name).c_str()) != 0 || DeleteFileW((root / name).c_str()) != 0);
-    const bool symbolic = CreateSymbolicLinkW((root / "app0/file-link").c_str(), L"../external/regular",
+    const bool symbolic = CreateSymbolicLinkW((root / "app0/file-link").c_str(), L"..\\external\\regular",
-        Require(CreateSymbolicLinkW((root / "app0/relative").c_str(), L"../external",
+        Require(CreateSymbolicLinkW((root / "app0/relative").c_str(), L"..\\external",
-    for (auto it = links.rbegin(); it != links.rend(); ++it) Require(std::filesystem::remove(root / *it));
+    for (auto it = links.rbegin(); it != links.rend(); ++it) Require(RemoveDirectoryW((root / *it).c_str()) != 0 || DeleteFileW((root / *it).c_str()) != 0);

With those changes, guest_windows_directory_link_types passes in 5 of 5 runs, the symbolic-link subcases included, and no anyps5-app0-links-* directory is left behind. The PR's DirectoryDescriptor.cpp change is unchanged in these runs.

AI-assisted (Claude Code).

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@JJenkx The correction belongs in GuestWindowsDirectoryLinkTypes.cpp. I prepared the four test-only edits from your follow-up against 4fb4187bd327a33cb139959d596c46782c3ac08d: both cleanup loops use RemoveDirectoryW/DeleteFileW, and the two app0 relative targets use escaped Windows backslashes. DirectoryDescriptor.cpp is unchanged.

Local check: Windows x64, WinLibs GCC 15.2.0 UCRT r7. I freshly compiled both the published fixture and the corrected fixture and ran them against the same preserved libraries from that head. Both pass the junction cases and leave no test directories behind. Both skip native symbolic-link subcases because this session lacks the privilege, so I cannot independently reproduce your symbolic-link before/after result or the cleanup failure on your machine. Your five failing/five passing runs remain separately attributed evidence. No full build, CTest suite, homebrew or hardware run was repeated for these test edits.

The correction is preserved locally in .codex/pr-maintainer/worktrees/pr-8726-test-review-20261022; patch, exact commands, results and artifact hashes are in .codex/pr-maintainer/logs/pass-20261022T1734Z. It is not committed or pushed: this maintenance pass cannot certify the combined daily commit count required by the contributor's five-commit rule. The feedback remains pending publication and privileged Windows validation. AI-assisted.

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

@ArjenS-LA thanks. This machine can create symbolic links without elevation, so the symbolic-link subcases run here. When you push the corrected test, I'll rerun guest_windows_directory_link_types on that exact head and post the result.

@simonbronk

Copy link
Copy Markdown
Contributor

@ArjenS-LA that order works for me: #8726 first, then I rebase #9732 and keep both debt entries. #9732 doesn't need #8726's code, so I'm leaving Depends on as none.

AI-assisted: yes

@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@qpavyros I confirmed the #8520 overlap with Git's merge engine against main 895f47f4eeaf56048b9a7080b7c01a9a47cf0ecf: #8726 at 4fb4187bd327a33cb139959d596c46782c3ac08d and #8520 at dfbac8ea58c6783f01286be3aca3ef8f13b44349 each merge with main, but their normalized trees conflict in core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp.

The shared Load changes need integration: retain #8520's archive/disk enumeration, inode and cursor handling together with #8726's Windows canonical-app0 target typing, DT_UNKNOWN on failed entry stat, and publication of the snapshot only after classification succeeds. Taking either implementation wholesale would lose behavior from the other.

Would #8726 first, once its pending test correction and full CI are ready, then rebasing #8520 with both behaviors preserved work for you? Maintainers retain the final order; no code dependency is declared before agreement. This is source inspection and tree-only merge evidence, with no combined build or runtime result. AI-assisted.

@oneandonlydean oneandonlydean self-assigned this Oct 23, 2026
@ArjenS-LA

Copy link
Copy Markdown
Contributor Author

@xXPBSXx I checked the new #10121 overlap against main 777bdbb4f80bcc03e870dfda0d292c0c6410fd6a. #8726 at 4fb4187bd327a33cb139959d596c46782c3ac08d and #10121 at e9b842569aaf59e5b1282b2637b10e94d589109b each merge with main, but Git's tree-only comparison of both normalized trees conflicts in docs/dev/debt/libkernel.md.

This is an adjacent documentation edit: #10121 extends the ftruncate entry, and #8726 inserts the Windows directory-entry-types entry immediately after it. Both entries should survive; #10121 does not change the directory implementation.

Would #8726 first, once its pending test correction and full CI are ready, then rebasing #10121 while preserving both entries work for you? If the documentation change is ready sooner, please say so and we can coordinate the reverse order. This is a proposal, not an agreed dependency; maintainers retain the final order.

This check used source inspection and tree-only Git merges. No code, commits, builds or runtime tests changed in this pass. AI-assisted.

@Gruzzberry

Copy link
Copy Markdown
Contributor

Gruzzberry here: I am opening a small PR that changes the file number (d_fileno) getdirentries reports in DirectoryDescriptor.cpp, next to lines your PR edits. Proposal: yours goes first and mine rebases. Tell me if you would rather go the other way.

@oneandonlydean
oneandonlydean merged commit 27c2794 into boykopovar:main Oct 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants