Skip to content

Handle deleted git directories as non-repositories#1907

Merged
juliusmarminge merged 7 commits intomainfrom
t3code/handle-missing-directories
Apr 11, 2026
Merged

Handle deleted git directories as non-repositories#1907
juliusmarminge merged 7 commits intomainfrom
t3code/handle-missing-directories

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Apr 10, 2026

Summary

  • Treat missing or deleted cwd paths as explicit non-repository states instead of surfacing git/fs errors.
  • Add a shared non-repo status shape in GitCore so status callers return stable defaults for deleted directories.
  • Update statusDetails, branch lookup, and manager-level status handling to degrade cleanly when the working directory no longer exists.
  • Add integration coverage for both GitCore and GitManager to verify deleted directories return isRepo: false with empty status data.

Testing

  • bun run test apps/server/src/git/Layers/GitCore.test.ts
  • bun run test apps/server/src/git/Layers/GitManager.test.ts
  • Not run: bun fmt
  • Not run: bun lint
  • Not run: bun typecheck

Note

Medium Risk
Changes error-handling paths in GitCore/GitManager so missing working directories and upstream refresh failures now degrade to non-repo defaults instead of surfacing errors, which can affect status/branch reporting behavior. Adds shared GitHub PR JSON decoding/normalization that may change how PR metadata is accepted/filtered from gh output.

Overview
Treat deleted/missing git working directories as explicit non-repositories. GitCore.statusDetailsLocal, statusDetails, and listBranches now detect “missing cwd” failures and return stable isRepo: false results (via a new NON_REPOSITORY_STATUS_DETAILS constant) rather than throwing.

Centralize and tighten GitHub PR JSON parsing. Adds githubPullRequests.ts to decode/normalize gh PR JSON (trims fields, normalizes state, skips invalid entries) and updates GitHubCli and GitManager to use it with clearer schema-formatted errors.

Tests updated/added to cover deleted-directory behavior for GitCore/GitManager and PR metadata trimming/invalid-entry filtering in GitHubCli and manager status.

Reviewed by Cursor Bugbot for commit 99e0eb4. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Handle deleted git directories as non-repositories in status and branch listing

  • listBranches, statusDetails, and statusDetailsLocal in GitCore.ts now return a non-repository result instead of throwing when the working directory no longer exists on disk.
  • Adds isMissingGitCwdError to detect ENOENT/invalid-directory errors from git commands, and a NON_REPOSITORY_STATUS_DETAILS constant as the canonical non-repo response.
  • Centralizes GitHub PR JSON decoding into a new githubPullRequests.ts module with schema-driven normalization; GitHubCli and GitManager now use these shared decoders instead of ad-hoc parsing.
  • Invalid PR list entries are silently dropped by the decoder; decode failures produce structured schema-based error messages.

Macroscope summarized 99e0eb4.

- Treat deleted/missing cwd paths as explicit non-repo status
- Cover GitCore and GitManager with integration tests
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e7f8bfc4-c6aa-4175-8e0b-ad4200414ef2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/handle-missing-directories

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

@github-actions github-actions bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Apr 10, 2026
- Normalize PR title, URL, and branch names before publishing status
- Skip entries whose required fields become empty after trimming
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 10, 2026

Approvability

Verdict: Approved

This PR adds defensive error handling for deleted git directories (returning non-repo status instead of erroring) and refactors GitHub PR JSON parsing into a shared module. Both changes have comprehensive test coverage, the author is the primary maintainer of these files, and there are no security or significant runtime implications beyond the intended edge case fix.

You can customize Macroscope's approvability policy. Learn more.

- Trim GitHub CLI pull request fields before use
- Share PR JSON decoding between GitHub CLI and git manager
- Improve errors when gh returns invalid PR JSON
@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Strict array decode replaces lenient per-entry skipping
    • Changed decodeGitHubPullRequestListJson to first parse the JSON as an array of unknowns, then decode each entry individually with Schema.decodeUnknownExit, skipping invalid entries instead of failing the entire list.

Create PR

Or push these changes by commenting:

@cursor push dce2f708e0
Preview (dce2f708e0)
diff --git a/apps/server/src/git/githubPullRequests.ts b/apps/server/src/git/githubPullRequests.ts
--- a/apps/server/src/git/githubPullRequests.ts
+++ b/apps/server/src/git/githubPullRequests.ts
@@ -1,4 +1,4 @@
-import { Cause, Result, Schema } from "effect";
+import { Cause, Exit, Result, Schema } from "effect";
 import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts";
 import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson";
 
@@ -84,7 +84,8 @@
   };
 }
 
-const decodeGitHubPullRequestList = decodeJsonResult(Schema.Array(GitHubPullRequestSchema));
+const decodeJsonArray = decodeJsonResult(Schema.Array(Schema.Unknown));
+const decodeGitHubPullRequestEntry = Schema.decodeUnknownExit(GitHubPullRequestSchema);
 const decodeGitHubPullRequest = decodeJsonResult(GitHubPullRequestSchema);
 
 export const formatGitHubJsonDecodeError = formatSchemaError;
@@ -95,11 +96,19 @@
   ReadonlyArray<NormalizedGitHubPullRequestRecord>,
   Cause.Cause<Schema.SchemaError>
 > {
-  const result = decodeGitHubPullRequestList(raw);
-  if (Result.isSuccess(result)) {
-    return Result.succeed(result.success.map(normalizeGitHubPullRequestRecord));
+  const arrayResult = decodeJsonArray(raw);
+  if (!Result.isSuccess(arrayResult)) {
+    return Result.fail(arrayResult.failure);
   }
-  return Result.fail(result.failure);
+
+  const normalized: NormalizedGitHubPullRequestRecord[] = [];
+  for (const entry of arrayResult.success) {
+    const decoded = decodeGitHubPullRequestEntry(entry);
+    if (Exit.isSuccess(decoded)) {
+      normalized.push(normalizeGitHubPullRequestRecord(decoded.value));
+    }
+  }
+  return Result.succeed(normalized);
 }
 
 export function decodeGitHubPullRequestJson(

You can send follow-ups to the cloud agent here.

- Skip malformed or blank GitHub PR list entries instead of failing the whole parse
- Keep valid PRs normalized so status can still report directories with usable matches
- Add regression coverage for CLI and manager PR listing
macroscopeapp[bot]
macroscopeapp bot previously approved these changes Apr 11, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: State normalization drops lowercase "merged" and "closed" handling
    • Added toUpperCase() normalization of the state string before comparison, so both lowercase and uppercase variants (e.g., "merged", "MERGED") are correctly matched.

Create PR

Or push these changes by commenting:

@cursor push 7ae5b33934
Preview (7ae5b33934)
diff --git a/apps/server/src/git/githubPullRequests.ts b/apps/server/src/git/githubPullRequests.ts
--- a/apps/server/src/git/githubPullRequests.ts
+++ b/apps/server/src/git/githubPullRequests.ts
@@ -50,13 +50,14 @@
   state?: string | null | undefined;
   mergedAt?: string | null | undefined;
 }): "open" | "closed" | "merged" {
+  const upperState = typeof input.state === "string" ? input.state.toUpperCase() : undefined;
   if (
     (typeof input.mergedAt === "string" && input.mergedAt.trim().length > 0) ||
-    input.state === "MERGED"
+    upperState === "MERGED"
   ) {
     return "merged";
   }
-  if (input.state === "CLOSED") {
+  if (upperState === "CLOSED") {
     return "closed";
   }
   return "open";

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 6f6e035. Configure here.

- Treat lowercase `merged` and `closed` states from `gh` JSON as expected
- Add a GitManager test covering lowercase PR states
@macroscopeapp macroscopeapp bot dismissed their stale review April 11, 2026 01:02

Dismissing prior approval to re-evaluate 99e0eb4

@juliusmarminge juliusmarminge merged commit e0e01b4 into main Apr 11, 2026
12 checks passed
@juliusmarminge juliusmarminge deleted the t3code/handle-missing-directories branch April 11, 2026 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant