Skip to content

test/docs: add canonical repo fixture builder and review hygiene#317

Open
flyingrobots wants to merge 2 commits intomainfrom
feat/repo-fixture-cycle
Open

test/docs: add canonical repo fixture builder and review hygiene#317
flyingrobots wants to merge 2 commits intomainfrom
feat/repo-fixture-cycle

Conversation

@flyingrobots
Copy link
Owner

PR Title

test/docs: add canonical repo fixture builder and review hygiene

Summary

  • add a shared fluent repo fixture builder for repository-shaped tests
  • add canonical base repos and reusable scenario overlays for test composition
  • migrate test/context.test.js onto the shared fixture substrate and add direct helper coverage
  • codify review-hygiene expectations after #314 and refresh roadmap/docs to reflect the completed git-warp prerequisite cycle
  • split broader suite migration into follow-up issue #316 to keep this PR cohesive

Problem Statement

  • Git Mind still had repeated mkdtemp + git init + git config boilerplate across repo-shaped tests, which makes Hill 1 test work slower, noisier, and less reusable.
  • The workflow also lacked an explicit review-hygiene step for stale threads / false positives, which #314 exposed as real merge friction.

ADR Compliance (Required)

Relevant ADR(s)

  • ADR-0002 (Worktree Independence and Materialization Architecture)
  • ADR-0003 (Graph-Native Content, Deterministic Materialization, and Workspace Bridge)
  • None

Compliance Declaration

  • This PR is fully compliant with all checked ADRs.
  • This PR intentionally deviates from one or more checked ADRs (complete Exception Request below).

Exception Request (Required if deviating)

  • ADR clause(s) deviated from: N/A
  • Why deviation is necessary now: N/A
  • Risk introduced by deviation: N/A
  • Mitigation and rollback plan: N/A
  • Follow-up ADR/issue to reconcile architecture debt: N/A

Architecture Laws Checklist (Hard Gates)

Canonical Truth & Context

  • Graph remains canonical truth (no dual truth with generated files).
  • No hidden worktree coupling introduced in core/domain/materialization paths.
  • Context-sensitive behavior is explicit (--at, --observer, --trust) or deterministically defaulted.
  • Resolved context is surfaced in output metadata where applicable.

Determinism & Provenance

  • Pure query/materialization paths remain deterministic for identical inputs.
  • Mutations/materializations include provenance receipts/envelopes where required.
  • Cache keys (if used) are derived only from semantic inputs + pinned versions.

Artifact Hygiene

  • No forbidden generated artifact paths are tracked.
  • Any generated artifacts intentionally tracked are in allowlisted publish paths only.
  • Pre-commit/CI policy checks updated or confirmed valid.

Contracts & Compatibility

  • Machine-facing outputs are schema-versioned.
  • Breaking contract changes include version bump + migration notes.
  • Backward compatibility impact is documented below.

Extension/Effects Safety (if applicable)

  • Extension behavior does not bypass capability restrictions.
  • Effectful operations use explicit plan/apply semantics and emit receipts.
  • Timeouts/resource bounds are defined for new script/effect paths.

Scope Control

  • PR is single-purpose/cohesive (no unrelated refactors).
  • Any non-essential refactor is split into separate PR(s) or explicitly justified.

Backward Compatibility

  • CLI/API contract changes: none
  • Data model/storage changes: none
  • Migration required?: no
  • User-facing behavior changes: contributor/test workflow now documents explicit review-hygiene cleanup; repo-shaped tests can use the new shared fixture substrate

Test Plan (Required)

Unit

  • Added/updated tests for changed logic
  • Commands:
npm test -- test/repo-fixture.test.js test/context.test.js

Integration

  • Added/updated integration tests
  • Commands:
npm test

Determinism

  • Determinism assertions included for relevant paths
  • Method: deterministic fixture repo setup uses fixed branch naming and controlled commit timestamps
  • Commands:
npm test -- test/repo-fixture.test.js test/context.test.js

Contract/Schema

  • Schema validation updated/passing
  • Commands:
npm run lint

Policy Gates

  • Mechanical architecture gates pass
  • Commands:
npm run lint

Security / Trust Impact

  • Threat surface changed?: no material change
  • Trust policy impact: none
  • Provenance/audit impact: none
  • New failure modes introduced: none beyond normal test-fixture setup failures

Performance Impact

  • Hot path affected?: no runtime hot path change
  • Expected impact (latency/memory/io): test setup becomes more reusable; no production impact
  • Benchmarks or profiling evidence: not applicable

Observability / Debuggability

  • Errors are actionable and include context.
  • Logs/diagnostics added or updated where needed.
  • git mind status / diagnostics updated if writeback/eventing behavior changed.

Operational Notes

  • Feature flag (if any): none
  • Rollback strategy: revert the two branch commits if fixture substrate or workflow docs prove problematic
  • Operational caveats: broader migration of older suites is intentionally deferred to #316

Linked Issues / Milestones


Reviewer Quick Verdict Block (for maintainers)

MUST (Hard Gates)

  • PASS

SHOULD (Quality)

  • PASS

Verdict

  • APPROVE

@flyingrobots
Copy link
Owner Author

@coderabbitai follow-up plan: broader suite migration onto the canonical repo fixture builder is intentionally tracked in #316. This PR closes #311 and #315 by establishing the shared fixture substrate and codifying review hygiene; it does not try to migrate every existing repo-shaped suite in one shot.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 27, 2026

Summary by CodeRabbit

  • Documentation

    • Updated delivery cycle workflow with explicit steps for reviewing feedback and resolving stale threads before merging.
    • Marked git-warp upgrade audit as completed.
  • Tests

    • Introduced repository fixture system for test setup and management.
    • Refactored existing tests to use shared fixture helpers.

Walkthrough

This PR codifies PR review hygiene workflows across documentation and introduces a comprehensive repository fixture builder for tests. Review hygiene steps (resolving stale threads, documenting false positives) are now explicit pre-merge requirements. The git-warp upgrade (issue #312) is marked complete. Test infrastructure provides fluent fixture composition with base repos and overlays, replacing boilerplate setup code.

Changes

Cohort / File(s) Summary
Review Workflow Documentation
AGENTS.md, CLAUDE.md, CONTRIBUTING.md, README.md, ROADMAP.md, docs/README.md, docs/adr/ADR-0006.md, docs/design/git-warp-upgrade-audit.md
Updated delivery cycle to explicitly insert review feedback processing and stale-thread/false-positive resolution steps before merge. Marked git-warp audit (issue #312) as completed, removed from active roadmap items. Reordered workflow checklist accordingly.
Repository Fixture Infrastructure
test/helpers/repo-fixture.js, test/helpers/repo-bases.js, test/helpers/repo-overlays.js
Added comprehensive test substrate: RepoFixture class (Git operations, file I/O, commit/branch/merge management), RepoFixtureBuilder fluent API (base repos, overlays, incremental setup), factory functions. Introduced minimalDocsAndCodeBase() and adrLinkedServiceBase() base configurations. Added four reusable overlays (withIssueRefOverlay, withRecentHistoryOverlay, withFeatureBranchOverlay, withNoisyHistoryOverlay).
Test Refactoring & Validation
test/context.test.js, test/repo-fixture.test.js
Replaced manual mkdtemp/git init/execSync boilerplate in context.test.js with repoFixture('context').build() helper and fixture methods. Added comprehensive test suite validating fixture builder, base repo composition, and overlay application with git log and file content assertions.

Sequence Diagram

sequenceDiagram
    actor Test as Test Suite
    participant Builder as RepoFixtureBuilder
    participant Fixture as RepoFixture
    participant Base as Base Factory
    participant Steps as Accumulated Steps
    participant Overlay as Overlay Factory

    Test->>Builder: repoFixture('name')
    Builder->>Builder: new RepoFixtureBuilder(name)
    Test->>Builder: .base(minimalDocsAndCodeBase)
    Builder->>Builder: store base factory
    Test->>Builder: .withFile(path, content)
    Builder->>Steps: accumulate file write
    Test->>Builder: .commit(message)
    Builder->>Steps: accumulate commit
    Test->>Builder: .overlay(withFeatureBranchOverlay)
    Builder->>Builder: store overlay factory
    Test->>Builder: .build()
    
    Builder->>Fixture: create temp repo
    Builder->>Fixture: init()
    Fixture->>Fixture: git init + config
    
    Builder->>Base: apply base factory
    Base->>Fixture: writeFiles() + commit()
    
    Builder->>Steps: apply accumulated steps
    Steps->>Fixture: write, commit, remove
    
    Builder->>Overlay: apply overlay factory
    Overlay->>Fixture: branch, write, commit, merge
    
    Builder-->>Test: return ready Fixture
    Test->>Fixture: git commands, assertions
    Test->>Fixture: cleanup()
    Fixture->>Fixture: rm -rf temp
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Rationale: Heterogeneous changes spanning documentation (8 files, consistent patterns) and substantial test infrastructure (3 new helper modules totaling 379 LOC with public classes/methods, moderate logic density). RepoFixture and RepoFixtureBuilder require careful review of Git operations, async patterns, and API ergonomics. Documentation changes are straightforward but numerous. Refactored test uses new patterns correctly. Overall scope and logic spread justify moderate effort; homogeneous doc updates partially offset infrastructure complexity.

Possibly Related PRs

Poem

🏗️ Fixtures built with fluent grace,
Repos spawn in temp-file space.
Bases, overlays compose,
Clean reviews before we close.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'test/docs: add canonical repo fixture builder and review hygiene' clearly summarizes the main changes: addition of a repo fixture builder and review hygiene codification.
Description check ✅ Passed The PR description is comprehensive and follows the template with all required sections: summary, problem statement, ADR compliance, architecture laws checklist, scope control, backward compatibility, test plan, security/trust impact, performance, observability, operational notes, and linked issues.
Linked Issues check ✅ Passed The PR fully addresses #311 (canonical repo fixture builder with base repos and overlays) and #315 (review hygiene codification) by implementing the shared fluent fixture substrate, reusable base repos/overlays, and documenting review-hygiene expectations across multiple documentation files.
Out of Scope Changes check ✅ Passed All changes are cohesive and in-scope: fixture infrastructure, documentation updates reflecting completed #312/git-warp upgrade, and one test migration (context.test.js). Broader suite migration is explicitly deferred to #316.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/repo-fixture-cycle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 27, 2026

Tip

For best results, initiate chat on the files or code changes.

@flyingrobots: Understood — the phased approach is clean and defensible. Establishing the substrate (#311) and locking down review hygiene (#315) before migrating existing suites is the right order of operations; doing it all at once would conflate infra work with churn across unrelated test files and make any regression harder to bisect. #316 as the explicit follow-up gives that migration a proper home without bloating this PR.

I'll record the migration strategy so future reviews don't incorrectly flag un-migrated suites as gaps in this PR.


✏️ Learnings added
Learnt from: flyingrobots
URL: https://github.com/flyingrobots/git-mind/pull/317

Timestamp: 2026-03-27T08:11:42.519Z
Learning: In the flyingrobots/git-mind repo, broader migration of existing repo-shaped test suites onto the canonical repo fixture builder (RepoFixtureBuilder) is intentionally deferred and tracked in issue `#316`. PR `#317` only establishes the shared fixture substrate (closes `#311`) and codifies review hygiene (closes `#315`). Future review comments should not flag un-migrated legacy suites as a defect in this PR or any PR that does not explicitly target the migration work.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: flyingrobots/git-mind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T01:14:33.896Z
Learning: Prefer canonical repo fixtures over ad hoc temp-repo setup when testing repository-shaped behavior

Learnt from: CR
Repo: flyingrobots/git-mind PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-27T01:14:19.543Z
Learning: YOU MUST prefer canonical repo fixtures over ad hoc temp-repo setup when testing repository-shaped behavior

Learnt from: CR
Repo: flyingrobots/git-mind PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-27T01:14:19.543Z
Learning: Prefer shared repo fixtures (base repos + overlays) where repository history or artifact shape matters

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 567c5250cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* @param {string} message
*/
async merge(ref, message) {
runGit(this.root, ['merge', '--no-ff', '-m', message, ref]);

Choose a reason for hiding this comment

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

P2 Badge Use deterministic dates for merge commits

RepoFixture.commit() intentionally fixes GIT_AUTHOR_DATE/GIT_COMMITTER_DATE, but RepoFixture.merge() runs git merge without those env vars (and does not advance the fixture clock), so any fixture using withFeatureBranchOverlay() gets wall-clock-dependent merge SHAs/timestamps. That makes fixture history non-reproducible across runs and can skew commit-order assumptions once a later deterministic commit has an older timestamp than the merge.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CONTRIBUTING.md`:
- Around line 48-50: Add a checklist item to the PR template to mechanically
enforce the new hygiene rule: update .github/pull_request_template.md to include
an explicit checkbox such as "Resolve stale review threads and document any
false positives" (or similar wording) in the pre-merge checklist so that the
CONTRIBUTING.md requirement (lines 48–50) is validated during reviews; ensure
the new item appears near existing checklist entries so reviewers must address
stale threads and false-positive documentation before merging.

In `@test/context.test.js`:
- Around line 24-26: The afterEach teardown should guard against repo being
undefined if beforeEach failed: in the afterEach async callback (the one calling
repo.cleanup()), check that the repo variable exists before invoking cleanup
(e.g., if repo) or use optional chaining to call cleanup only when repo is set;
ensure the same symbol names (repo and the afterEach callback) are used so
teardown won't throw a follow-on error hiding the original beforeEach failure.

In `@test/helpers/repo-fixture.js`:
- Around line 51-53: The resolve(relativePath) helper (and callers write() and
remove()) currently uses join(this.root, relativePath) which permits ../
traversal; change them to compute an absolute resolved path (using path.resolve
or path.resolve(this.root, relativePath)) and then validate that the resolved
path stays inside the fixture root (e.g., using path.relative(this.root,
resolvedPath) and rejecting if it starts with '..' or otherwise falls outside,
accounting for equality with this.root); if validation fails, throw an error and
do not perform the write/remove. Update resolve(), write(), and remove() to use
this validation check before touching the filesystem.
- Around line 159-161: The merge() helper is creating merge commits with
wall-clock metadata, breaking deterministic history; modify merge(ref, message)
to runGit with the same deterministic commit timestamp used by commit() (set
GIT_COMMITTER_DATE and GIT_AUTHOR_DATE to the deterministic value the fixture
uses) when invoking runGit(this.root, ['merge', '--no-ff', '-m', message, ref])
so the resulting merge commit metadata matches commit() and currentSha() remains
deterministic.
- Around line 239-257: The build() method currently leaks the temporary
directory created by mkdtemp when this.#base, any this.#steps, or this.#overlays
throws; wrap the sequence that initializes RepoFixture and then runs
this.#base/this.#steps/this.#overlays in a try/catch/finally (or try with
finally) so that if an error occurs you remove the created temporary root (the
value returned by mkdtemp) before rethrowing; reference sanitizeName, mkdtemp,
RepoFixture, and the this.#base / this.#steps / this.#overlays calls to locate
where to add the cleanup (use fs.rm or fs.promises.rm with recursive/force or an
equivalent cleanup helper) and ensure you only attempt cleanup if root was
created.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 35bc7b93-9f20-48a1-bedc-6c3362c4dbfb

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed15dc and 567c525.

📒 Files selected for processing (13)
  • AGENTS.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • README.md
  • ROADMAP.md
  • docs/README.md
  • docs/adr/ADR-0006.md
  • docs/design/git-warp-upgrade-audit.md
  • test/context.test.js
  • test/helpers/repo-bases.js
  • test/helpers/repo-fixture.js
  • test/helpers/repo-overlays.js
  • test/repo-fixture.test.js

Comment on lines +48 to +50
7. open the PR and process review feedback
8. resolve stale review threads and document false positives before merge
9. land it, then capture review-cycle learnings back into the backlog
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

New hygiene rule is documented but not mechanically enforced.

Lines 48–50 add the requirement, but the current .github/pull_request_template.md checklist still has no explicit item for stale-thread cleanup / false-positive documentation. This leaves compliance as “best effort” instead of a review gate.

🔧 Proposed enforcement update (PR template)
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@
 ## Scope Control

 - [ ] PR is single-purpose/cohesive (no unrelated refactors).
 - [ ] Any non-essential refactor is split into separate PR(s) or explicitly justified.
+- [ ] All stale review threads are resolved before merge.
+- [ ] Any false-positive review findings are explicitly documented and linked.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CONTRIBUTING.md` around lines 48 - 50, Add a checklist item to the PR
template to mechanically enforce the new hygiene rule: update
.github/pull_request_template.md to include an explicit checkbox such as
"Resolve stale review threads and document any false positives" (or similar
wording) in the pre-merge checklist so that the CONTRIBUTING.md requirement
(lines 48–50) is validated during reviews; ensure the new item appears near
existing checklist entries so reviewers must address stale threads and
false-positive documentation before merging.

Comment on lines 24 to 26
afterEach(async () => {
await rm(tempDir, { recursive: true, force: true });
await repo.cleanup();
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard teardown when setup fails.

If beforeEach fails before repo assignment, teardown throws a follow-on error and hides the root failure.

Suggested fix
 afterEach(async () => {
-  await repo.cleanup();
+  if (repo) {
+    await repo.cleanup();
+    repo = undefined;
+  }
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
afterEach(async () => {
await rm(tempDir, { recursive: true, force: true });
await repo.cleanup();
});
afterEach(async () => {
if (repo) {
await repo.cleanup();
repo = undefined;
}
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/context.test.js` around lines 24 - 26, The afterEach teardown should
guard against repo being undefined if beforeEach failed: in the afterEach async
callback (the one calling repo.cleanup()), check that the repo variable exists
before invoking cleanup (e.g., if repo) or use optional chaining to call cleanup
only when repo is set; ensure the same symbol names (repo and the afterEach
callback) are used so teardown won't throw a follow-on error hiding the original
beforeEach failure.

Comment on lines +51 to +53
resolve(relativePath) {
return join(this.root, relativePath);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Block path escape outside fixture root.

join(this.root, relativePath) allows ../ traversal; write()/remove() can touch paths outside the temp repo.

Suggested fix
-import { dirname, join } from 'node:path';
+import { dirname, join, relative, resolve } from 'node:path';
@@
   resolve(relativePath) {
-    return join(this.root, relativePath);
+    const absolutePath = resolve(this.root, relativePath);
+    const rel = relative(this.root, absolutePath);
+    if (rel.startsWith('..') || rel === '') {
+      throw new Error(`Path escapes fixture root: ${relativePath}`);
+    }
+    return absolutePath;
   }

Also applies to: 59-63, 79-81

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/helpers/repo-fixture.js` around lines 51 - 53, The resolve(relativePath)
helper (and callers write() and remove()) currently uses join(this.root,
relativePath) which permits ../ traversal; change them to compute an absolute
resolved path (using path.resolve or path.resolve(this.root, relativePath)) and
then validate that the resolved path stays inside the fixture root (e.g., using
path.relative(this.root, resolvedPath) and rejecting if it starts with '..' or
otherwise falls outside, accounting for equality with this.root); if validation
fails, throw an error and do not perform the write/remove. Update resolve(),
write(), and remove() to use this validation check before touching the
filesystem.

Comment on lines +159 to +161
async merge(ref, message) {
runGit(this.root, ['merge', '--no-ff', '-m', message, ref]);
return this.currentSha();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep merge commits deterministic too.

merge() currently uses wall-clock commit metadata, which breaks deterministic-history guarantees provided by commit().

Suggested fix
   async merge(ref, message) {
-    runGit(this.root, ['merge', '--no-ff', '-m', message, ref]);
-    return this.currentSha();
+    const timestamp = isoTimestamp(this.#commitIndex);
+    runGit(this.root, ['merge', '--no-ff', '-m', message, ref], {
+      env: {
+        GIT_AUTHOR_DATE: timestamp,
+        GIT_COMMITTER_DATE: timestamp,
+      },
+    });
+    this.#commitIndex += 1;
+    return this.currentSha();
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async merge(ref, message) {
runGit(this.root, ['merge', '--no-ff', '-m', message, ref]);
return this.currentSha();
async merge(ref, message) {
const timestamp = isoTimestamp(this.#commitIndex);
runGit(this.root, ['merge', '--no-ff', '-m', message, ref], {
env: {
GIT_AUTHOR_DATE: timestamp,
GIT_COMMITTER_DATE: timestamp,
},
});
this.#commitIndex += 1;
return this.currentSha();
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/helpers/repo-fixture.js` around lines 159 - 161, The merge() helper is
creating merge commits with wall-clock metadata, breaking deterministic history;
modify merge(ref, message) to runGit with the same deterministic commit
timestamp used by commit() (set GIT_COMMITTER_DATE and GIT_AUTHOR_DATE to the
deterministic value the fixture uses) when invoking runGit(this.root, ['merge',
'--no-ff', '-m', message, ref]) so the resulting merge commit metadata matches
commit() and currentSha() remains deterministic.

Comment on lines +239 to +257
async build() {
const prefix = sanitizeName(this.#name);
const root = await mkdtemp(join(tmpdir(), `gitmind-${prefix}-`));
const repo = await new RepoFixture(this.#name, root).init();

if (this.#base) {
await this.#base(repo);
}

for (const step of this.#steps) {
await step(repo);
}

for (const overlay of this.#overlays) {
await overlay(repo);
}

return repo;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clean up temp repos on build failure.

If base/step/overlay throws, build() leaks the mkdtemp directory.

Suggested fix
   async build() {
     const prefix = sanitizeName(this.#name);
     const root = await mkdtemp(join(tmpdir(), `gitmind-${prefix}-`));
-    const repo = await new RepoFixture(this.#name, root).init();
-
-    if (this.#base) {
-      await this.#base(repo);
-    }
-
-    for (const step of this.#steps) {
-      await step(repo);
-    }
-
-    for (const overlay of this.#overlays) {
-      await overlay(repo);
-    }
-
-    return repo;
+    const repo = new RepoFixture(this.#name, root);
+    try {
+      await repo.init();
+
+      if (this.#base) {
+        await this.#base(repo);
+      }
+
+      for (const step of this.#steps) {
+        await step(repo);
+      }
+
+      for (const overlay of this.#overlays) {
+        await overlay(repo);
+      }
+
+      return repo;
+    } catch (error) {
+      await repo.cleanup();
+      throw error;
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/helpers/repo-fixture.js` around lines 239 - 257, The build() method
currently leaks the temporary directory created by mkdtemp when this.#base, any
this.#steps, or this.#overlays throws; wrap the sequence that initializes
RepoFixture and then runs this.#base/this.#steps/this.#overlays in a
try/catch/finally (or try with finally) so that if an error occurs you remove
the created temporary root (the value returned by mkdtemp) before rethrowing;
reference sanitizeName, mkdtemp, RepoFixture, and the this.#base / this.#steps /
this.#overlays calls to locate where to add the cleanup (use fs.rm or
fs.promises.rm with recursive/force or an equivalent cleanup helper) and ensure
you only attempt cleanup if root was created.

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.

workflow: codify PR review hygiene and reviewer context after #314 test: build canonical repo fixture builder with base repos and overlays

1 participant