Skip to content

[P0] Replace the Windows worktree artifact-routing wall-clock timeout with deterministic phase evidence #695

Description

@mohanagy

Parent: #654
Target branch: next
Depends on: #689 and #690 completed
Blocks: #654 completion, merge of #681 and #680, and start of #657
Milestone: v0.33.0-beta.1 — Trust Foundation

Outcome

Make the linked-worktree artifact-routing test prove correctness deterministically on Windows and the other supported platforms, without relying on one fixed 20-second wall-clock budget around Git repository setup, worktree creation, graph generation, assertions, and cleanup.

The issue is limited to the test/integration contract and any minimal testability seam required to observe its phases. It must not change Madar's graph semantics or artifact-routing behavior unless a separate product defect is conclusively reproduced.

Confirmed evidence

Protected matrix attempt 3 for frozen commit:

b1300f8fcc2758404abc5e6064433c4d8b2ab40b

failed in:

  • workflow run: 31711572439
  • run attempt: 3
  • lane: windows-latest, Node 22
  • job: 94523609780
  • runner image: Windows Server 2025
  • Node: 22.23.2
  • npm: 10.9.8

Exact failure:

tests/unit/workspace.test.ts > worktree artifact routing > keeps a linked worktree graph outside the source checkout and isolated from the primary checkout
Error: Test timed out in 20000ms
Location: tests/unit/workspace.test.ts:46:3
Observed file duration: approximately 21.3 s

The guarded raw log contained:

Failed to start forks worker: 0
Timeout waiting for worker to respond: 0

The failure-only raw-log artifact is:

name: vitest-guard-logs-31711572439-3-windows-latest-node22
artifact id: 9190243054
SHA-256: 90520d018b7a76cb3e172f8b78b070d94e5fa7bd0a0c131d33a0d567def9fa08

Five other OS/Node lanes in the same matrix passed. This is therefore distinct from the absorbed forks-worker symptom fixed by #690.

Current test contract

The affected test currently places one 20-second outer timeout around all of these operations:

  1. Create temporary primary and linked-worktree directories.
  2. git init.
  3. Configure Git username/email.
  4. Create and stage a README.
  5. Commit the repository.
  6. git worktree add -b feature <linked>.
  7. Run generateGraph(linked, { noHtml: true }).
  8. Assert the output directory and graph are outside the linked source checkout.
  9. Assert the primary checkout remains isolated.
  10. Run git worktree remove --force <linked>.
  11. Delete temporary files.

One aggregate wall-clock timeout cannot identify which phase is slow and can fail on a correct but slower Windows filesystem or Git worktree operation.

Required investigation

1. Reproduce or directly prove the fragile contract

Instrument the test by phase before changing its semantics.

Capture durations and outcomes for:

  • repository initialization;
  • Git configuration;
  • add and commit;
  • linked-worktree creation;
  • graph generation;
  • graph/artifact assertions;
  • linked-worktree removal;
  • temporary-directory cleanup.

Run the instrumented test repeatedly on:

  • Windows Node 20;
  • Windows Node 22;
  • Ubuntu Node 22;
  • macOS Node 22.

Determine which phase crossed or approached the aggregate 20-second bound.

Do not infer the phase only from the final timeout.

2. Separate correctness from latency

The correctness contract is:

  • the linked worktree resolves to the correct primary Git common directory;
  • Madar places graph artifacts outside the linked source checkout;
  • the graph path is deterministic and usable;
  • the primary checkout's artifacts remain isolated;
  • cleanup leaves no linked worktree registration or temporary artifact behind.

These conditions should be observed directly.

A true latency test belongs in a separately declared performance fixture with an evidence-supported budget. This issue must not silently turn integration correctness into a performance assertion.

3. Replace the single aggregate timeout

Prefer:

  • explicit phase completion;
  • direct assertions after each synchronous Git command;
  • deterministic graph/artifact path checks;
  • a test helper that reports the exact phase on failure;
  • phase-specific deadlock limits only where an operation can genuinely hang.

The final test may retain a generous outer deadlock timeout, but it must not use that timeout as the primary correctness criterion.

Do not solve the issue by changing only:

20_000 → a larger number

4. Preserve real integration coverage

Continue to exercise real:

  • Git repository initialization;
  • Git linked worktree creation;
  • Madar graph generation;
  • path resolution;
  • worktree removal.

Do not replace the complete test with mocks.

Mocks or injected delay controls may supplement the real integration test to prove phase diagnostics and cleanup behavior.

5. Cleanup correctness

Cleanup must run when failure occurs during:

  • worktree creation;
  • graph generation;
  • assertions;
  • worktree removal.

After the test, verify:

git worktree list --porcelain

contains no stale registration for the linked path.

Verify both temporary directories are removed when expected.

Do not hide cleanup failures behind the original timeout error.

Explicit non-goals

Required characterization and tests

At minimum add or retain proof for:

  1. Primary repository setup completes and Git commands report actionable failures.
  2. Linked worktree creation succeeds with spaces in the temporary path.
  3. Windows path separators do not affect graph artifact routing.
  4. Graph artifacts live outside the linked source checkout.
  5. Primary and linked checkout artifacts remain isolated.
  6. Graph generation failure identifies the graph-generation phase.
  7. Worktree-add failure identifies the worktree-add phase.
  8. Cleanup runs after assertion failure.
  9. Cleanup runs after graph-generation failure.
  10. git worktree list --porcelain has no stale linked registration afterward.
  11. A deliberately slowed phase does not create a false correctness failure merely because the aggregate runtime exceeds 20 seconds.
  12. A genuinely hung or failed phase fails with the phase name and retained diagnostics.
  13. No global timeout, retry, skip, quarantine, or worker-count workaround is introduced.

Validation

At minimum run:

npm ci
npm run typecheck
npm run build
npx vitest run tests/unit/workspace.test.ts --maxWorkers=1
npx vitest run tests/unit/workspace.test.ts --maxWorkers=4
npm run test:run
npm run test:coverage
npm run verify:pack-parity
npm pack --dry-run
npm run registry:validate
npm run release:verify

Run the focused workspace test repeatedly on Windows Node 20 and Node 22.

Then run at least three exact-commit complete six-lane protected matrices:

Ubuntu × Node 20
Ubuntu × Node 22
macOS × Node 20
macOS × Node 22
Windows × Node 20
Windows × Node 22

For every lane and attempt report:

  • job conclusion;
  • workspace test result and duration;
  • guarded complete-suite status;
  • worker-start signature count;
  • handshake-timeout signature count;
  • raw-log readability/control result;
  • cleanup result.

Do not rerun until green and report only the successful attempt.

Acceptance criteria

  • The failing Windows phase is identified through direct evidence, or the aggregate-timeout fragility is proven with controlled phase delay.
  • The test no longer relies on one fixed 20-second wall-clock budget as its correctness contract.
  • No timeout-only workaround is used.
  • Real linked-worktree and graph-generation integration remains covered.
  • Failure diagnostics name the exact phase.
  • Cleanup is guaranteed and verified after every tested failure phase.
  • No stale linked worktree remains registered.
  • Windows path behavior is explicitly tested.
  • Focused tests pass repeatedly on Windows Node 20 and Node 22.
  • Three complete exact-commit protected matrices pass.
  • Every accepted lane has zero canonical worker-start signatures.
  • Raw-log controls prove scanning was active.
  • No unexplained timeout or nontermination remains.
  • No unrelated roadmap scope enters the diff.

Relationship to #693 and #654

The fresh macOS 26 ARM64 VM qualification in #693 may finish and establish its own environment boundary independently.

However, #654 remains incomplete while this Windows timeout is unexplained. Three clean protected matrices are unavailable until this issue is resolved and rerun on one exact commit.

Do not discard or rerun the failed matrix as though it were clean evidence.

Rollback

Revert the phase-aware test/helper changes together. Do not restore the fixed 20-second aggregate timeout as the permanent gate. If the proposed design is invalid, return to investigation with the retained Windows log and phase measurements.

Agent handoff

Start from current origin/next in an isolated worktree after the live #693 diagnostics run has finished or while it continues remotely. Begin with phase instrumentation and the exact Windows failure receipt. Keep the PR focused on workspace.test.ts, directly shared workspace/Git test helpers, and minimal testability seams. Return the phase timing table, identified failure phase, files changed, cleanup proof, focused Windows results, exact protected matrices, raw-log counts, and remaining uncertainty. Stop after opening a focused PR for review.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions