Skip to content

ci: scratch push to validate the #707 Windows fixes - #710

Merged
blafourcade merged 10 commits into
claude/aidd-telemetry-layer-e403uffrom
ci/windows-last
Aug 23, 2026
Merged

blafourcade merged 10 commits into
claude/aidd-telemetry-layer-e403uffrom
ci/windows-last

Conversation

@blafourcade

Copy link
Copy Markdown
Contributor

Scratch PR to run the windows-probe job against the fixes for #707. Base is the layer branch (not main) so it merges cleanly and pull_request triggers fire. Will be closed and the branch deleted once the run is read.

Test and others added 4 commits August 23, 2026 05:41
The journal's per-write ACL reset walked (`icacls /T`) into files it
does not own - a checked-out `.gitkeep` among them - and left it with
no usable ACE, so an ordinary `git add -A` right after got
"Permission denied" opening it. Drops `/T`: a file this code writes
already gets its own direct icacls pass, and `(OI)(CI)` alone makes
the directory's own grant apply to anything created afterward, so
nothing needed the recursion. A marker file also stops the directory
reset from repeating on every session-start once it has already run.

Closes the rest of the set the Windows measurement found: the
doc/code-parity test for the figures location now checks the sink's
real per-platform answer instead of a POSIX literal, folding the
Windows pin into the same three subtests rather than a fourth; eleven
CLI integration tests get the direction-correct fix each one actually
needed - a native `join` used for a virtual, always-"/" relative path
in one production translator (a real small defect, fixed), the same
native-vs-virtual-path mismatch inverted across four test files, and
three hardcoded POSIX literals; the golden baseline's own normalizer
gains a drive-letter/backslash fold so it redacts a Windows path the
same way it already redacts a POSIX one (a real gap, not a content
difference - the settings.json hash mismatch traced to the same
un-redacted path, not different bytes); the other golden file's two
timeouts get a per-test bump, not the e2e project's global one.

The windows-probe job also gets a step that echoes `icacls` for the
runs directory and the written journal file, then runs `git add -A`
against the real checkout - proof for both properties on the runner
itself, not just inferred from a passing test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
The marker file from the first pass permanently disabled re-tightening
the runs directory once written - exactly the "checked-out aidd_docs/
runs/ needs this chmod" case the reset exists for in the first place.
Dropping /T alone already closes the git collision (it never touches
a file already sitting in the directory), so the reset goes back to
running on every write, unconditionally, matching what it did before
this task beyond no longer recursing.

Also names, rather than only routes around, the real defect the
copilot/claude Mode A test fixes surfaced: resolveSourceForSettings
re-resolves an already-absolute local source path against projectRoot
unconditionally. Harmless for a real builtDir (always drive-qualified
on a real Windows machine), but a genuinely drive-less absolute local
path - e.g. a marketplaces.json committed on POSIX and read on
Windows - would silently gain the current process's drive instead of
failing loud. Not fixed here; named in both tests instead of left
implied by a test-side literal-to-computed edit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
@blafourcade
blafourcade requested a review from a team as a code owner August 23, 2026 04:00
Test and others added 6 commits August 23, 2026 06:06
…#707 review)

normalize()'s blanket backslash fold ran over the manifest after
JSON.stringify - a settings.json path's separator is doubled by JSON's
own escaping there, but so is nothing else, and the same fold would
have flattened `\"` and `\n` right along with it, corrupting content
JSON.parse would then throw on rather than merely miscompare.

Walks the parsed manifest and normalizes each string value directly
instead (no JSON escaping to fight at that point), and gives the one
place that still reads raw JSON bytes off disk - recomputing a real
file's hash - its own narrow un-escape: a doubled backslash back to
one, scoped to .json files only, and only correct because every
settings.json this matrix writes carries path/repo/plugin-name values
and nothing else that JSON would need to escape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
…e test (#707)

The remaining failure in this file was the same resolve() mismatch as
the copilot/claude Mode A tests: FrameworkBuildUseCase.execute() calls
resolve(options.outDir) before ever touching the filesystem through
it, but this test's own colliding-file path was built from the
un-resolved builtMarketplaceDir() output. Harmless for a real
projectRoot; this test's drive-less "/proj" is what exposed it.

One real, unfixed defect surfaced investigating the file's last
failure and is now named at the assertion it breaks, not fixed:
EnsureBuiltMarketplaceUseCase.nested() compares sourceDir/builtDir
with a hardcoded "/" rather than path.sep, so on Windows it never
recognises genuine nesting - the "dogfood" build (a marketplace whose
source is the project being built) skips the temp-dir detour meant to
keep it out of guardPaths()'s way. Compounded by resolve() only ever
being applied to sourceDir (ensure-built-marketplace-use-case.ts:70),
never to builtDir, so a separator fix alone would not close it - both
sides need to compare normalized, equally-resolved paths. Out of this
task's surgical scope; reported rather than patched blind.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
builtMarketplaceDir() joins with the native separator, so a drive-less
projectRoot yields a drive-less builtDir on Windows. That raw value was
captured unresolved into FlatBuildStrategy's write target (absOut) at
construction, while FrameworkBuildUseCase.execute() separately resolved
its own outDir copy for the preBuild existence check only - letting
writes and checks silently diverge on Windows. Resolve builtDir at the
same point sourceDir already is.
…ls (#707)

nested() compared sourceDir/builtDir with a hardcoded "/", never
path.sep, so it silently missed real nesting on Windows - mirror
guardPaths()'s own "/"-normalized comparison. Also update the four
test-side builtDir literals left unresolved after the prior commit
started resolving builtDir in production: they now seed/expect the
same drive-qualified path the use-case actually reads and returns.
…#707)

Same gap as the prior two commits: execute() now always resolves
builtDir before capturedOutDirs sees it, but this test's cacheRoot
comparison literal stayed unresolved.
…707)

This repo has no .gitattributes, so a Windows checkout's core.autocrlf
rewrites every text file's line endings to CRLF - hashDirectory() was
hashing those raw bytes, diffing the frozen claude cell against the
LF-committed stored baseline on line endings alone, not real content.
Corrects the prior diagnosis: AC #1 was not only a timeout (fixed by
the earlier 120s bump) but a second, separate content-hash mismatch
the timeout fix then exposed.
@blafourcade
blafourcade merged commit 716661c into claude/aidd-telemetry-layer-e403uf Aug 23, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant