Skip to content

Fix document inspector UI issues and improve accessibility#644

Merged
Wirasm merged 3 commits intomainfrom
fix-ui-issues-document-inspector
Sep 12, 2025
Merged

Fix document inspector UI issues and improve accessibility#644
Wirasm merged 3 commits intomainfrom
fix-ui-issues-document-inspector

Conversation

@Wirasm
Copy link
Copy Markdown
Collaborator

@Wirasm Wirasm commented Sep 12, 2025

Summary

Fixes UI issues in the document inspector where copy buttons were being pushed off-screen by long summaries, and improves overall accessibility and user experience.

Problem

  • Copy button became inaccessible when document summaries or metadata were too long
  • Long file paths and text content would overflow without proper truncation
  • Missing accessibility features for screen readers

Solution

Layout Fixes

  • Added proper flex constraints (min-w-0, flex-1, flex-shrink-0) to prevent overflow
  • Implemented text truncation with truncate and line-clamp-2 classes
  • Made copy button non-shrinkable to guarantee visibility

Accessibility Improvements

  • Added comprehensive ARIA labels and attributes
  • Improved keyboard navigation support
  • Enhanced focus states with visible rings
  • Added semantic HTML structure

UI Enhancements

  • Better metadata display in footer with relevance scores
  • Added "View Source" links for documents
  • Improved loading states with spinners
  • Enhanced empty state messages
  • Added tooltips for truncated text
  • Better scrollbar styling
  • Motion effects with Framer Motion for better interactivity

Testing

  • Tested with various content lengths
  • Verified copy button remains visible with long summaries
  • Checked accessibility with keyboard navigation
  • Validated all metadata displays correctly

Screenshots

Before: Copy button was pushed off-screen with long summaries
After: Copy button stays visible, text properly truncates

Related Issues

Addresses user-reported issues with document inspector UI

Summary by CodeRabbit

  • New Features
    • Always-visible content footer with relevance, “View Source” (when available), and item type label; distinct metadata views for documents vs. code.
  • Bug Fixes
    • Better truncation and overflow for long titles, file paths, and summaries; more reliable copy action feedback.
  • Style
    • Polished header/layout, relaxed document typography, thin/custom scrollbars, and consistent copy button sizing.
  • Refactor
    • Improved accessibility and interactions: semantic sidebar, ARIA labels/live regions, focus rings, clearer loading/empty states, and tactile feedback.

- Fixed copy button visibility when summaries overflow
- Added proper flex constraints and text truncation
- Enhanced metadata display in footer with relevance scores
- Improved accessibility with ARIA labels and semantic HTML
- Added better loading states and error handling
- Enhanced visual feedback with motion effects
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 12, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Reworks ContentViewer header/body/footer for proper truncation and metadata display; InspectorSidebar gains semantic aside, ARIA improvements, better loading/empty states, and overflow/truncation fixes; KnowledgeInspector memoizes handlers (copy, selection, mode changes) and hardens clipboard logic. No public API changes.

Changes

Cohort / File(s) Summary of Changes
Content Viewer layout and footer
archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx
Rebuilt header using flex + min-w-0/flex-1 for truncation; distinct document vs code metadata blocks (icons, badges, truncated title/section/file_path); copy button set flex-shrink-0; content body restyled with scrollbar-thin and code fallback; footer always rendered showing relevance, view source (when present), and right-aligned type label; clamped summaries and minor UI polish.
Inspector sidebar accessibility and UX
archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx
Root changed to aside with aria-label; search input gains aria-label; loading replaced by an aria-live="polite" loader; empty state shows contextual hint when searching; item buttons gain press feedback, focus ring, aria-selected and descriptive aria-label; icon container fixed size, content uses min-w-0 for truncation; relevance icon marked aria-hidden; improved “Load More” button semantics and sr-only hints.
Inspector handlers and memoization
archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx
Added useCallback for handleCopy, handleItemSelect, and handleViewModeChange; handleCopy wraps navigator.clipboard.writeText in try/catch, sets transient copiedId cleared after 2s; selection derives title/section/url fallbacks for documents and content/title fallbacks for code; behavior and public signatures unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant IS as InspectorSidebar
  participant KI as KnowledgeInspector
  participant CV as ContentViewer
  participant CB as Clipboard API

  U->>IS: Search / Select item
  IS->>KI: onItemSelect(item, viewMode)
  KI->>KI: set selectedItem (memoized)
  KI-->>CV: selectedItem props update
  CV-->>U: Render content, metadata, footer

  U->>CV: Click Copy
  CV->>KI: onCopy(contentId, text)
  KI->>CB: navigator.clipboard.writeText(text)
  alt Copy success
    KI->>KI: set copiedId, clear after 2s
    KI-->>CV: copied state updates
  else Copy failure
    KI->>KI: log error
  end

  U->>KI: Change view mode
  KI->>KI: set viewMode, clear selectedItem, reset search
  KI-->>IS: props update (viewMode, query)
  IS-->>U: Render list / loading / empty state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I nibble on bytes with a whiskered grin,
Headers trimmed snug so long texts tuck in.
An aside whispers ARIA, clear and bright,
Copy hops to clipboard, then rests for the night.
Modes shift, lists tidy — a rabbit’s delight. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3db2025 and 678e3a0.

📒 Files selected for processing (2)
  • archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx (2 hunks)
  • archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx (2 hunks)
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-ui-issues-document-inspector

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.

Copy link
Copy Markdown

@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: 3

🧹 Nitpick comments (2)
archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx (2)

84-103: Add an explicit accessible label to the Copy button.

Improves SR clarity when focus lands on the control.

-        <Button
+        <Button
           size="sm"
           variant="ghost"
           onClick={() => onCopy(selectedItem.content, selectedItem.id)}
-          className="text-gray-400 hover:text-white flex-shrink-0"
+          className="text-gray-400 hover:text-white flex-shrink-0"
+          aria-label={`Copy ${selectedItem.type} content`}
         >

109-121: Optional: expose language for future syntax highlighting.

If a highlighter is introduced later, pre-adding a class or data attr avoids refactors.

Example:

-            <pre className="bg-black/30 border border-white/10 rounded-lg p-4 overflow-x-auto scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent">
-              <code className="text-sm text-gray-300 font-mono">
+            <pre className="bg-black/30 border border-white/10 rounded-lg p-4 overflow-x-auto scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent">
+              <code
+                className={cn(
+                  "text-sm text-gray-300 font-mono",
+                  selectedItem.metadata && "language" in selectedItem.metadata && selectedItem.metadata.language
+                    ? `language-${selectedItem.metadata.language.toLowerCase()}`
+                    : undefined,
+                )}
+                data-language={
+                  selectedItem.metadata && "language" in selectedItem.metadata ? selectedItem.metadata.language : undefined
+                }
+              >
                 {selectedItem.content || "// No code content available"}
               </code>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94aed6b and 3db2025.

📒 Files selected for processing (3)
  • archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx (3 hunks)
  • archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx (2 hunks)
  • archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
archon-ui-main/src/features/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

archon-ui-main/src/features/**/*.{ts,tsx}: Implement optimistic updates with rollback in TanStack Query mutations
Use Biome formatting and lint rules in /src/features with 120-character lines, double quotes, and trailing commas
Implement HTTP polling patterns: 1–2s for active ops, 5–10s for background, smart pausing on tab inactivity, use ETag caching where applicable

archon-ui-main/src/features/**/*.{ts,tsx}: Follow TanStack Query patterns: query-keys factory, smart polling via useSmartPolling, optimistic updates with rollback
Biome formatting in features: 120-character lines, double quotes, trailing commas

Files:

  • archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx
  • archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx
  • archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx
archon-ui-main/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use state naming conventions: is[Action]ing for loading, [resource]Error for errors, selected[Resource] for selections

archon-ui-main/src/**/*.{ts,tsx}: Use TanStack Query for all data fetching; avoid prop drilling
TypeScript: strict mode with no implicit any in frontend code
State naming: is[Action]ing for loading flags, [resource]Error for errors, selected[Resource] for current selection
Use HTTP polling with ETag caching; do not introduce WebSocket-based updates in the frontend

Files:

  • archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx
  • archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx
  • archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx
🧬 Code graph analysis (3)
archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx (1)
archon-ui-main/src/features/knowledge/types/knowledge.ts (2)
  • DocumentChunk (73-85)
  • CodeExample (49-62)
archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx (1)
archon-ui-main/src/features/ui/primitives/button.tsx (1)
  • Button (11-130)
archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx (3)
archon-ui-main/src/features/ui/primitives/input.tsx (1)
  • Input (8-29)
archon-ui-main/src/features/ui/primitives/styles.ts (1)
  • cn (139-141)
archon-ui-main/src/features/knowledge/types/knowledge.ts (1)
  • CodeExample (49-62)
🔇 Additional comments (8)
archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx (2)

6-6: Importing useCallback for stable handlers — good call.

This aligns with your re-render and performance goals.


127-131: Stable view-mode change handler — LGTM.

Resets selection and search predictably; dependency [] is correct.

archon-ui-main/src/features/knowledge/inspector/components/ContentViewer.tsx (2)

30-41: Header truncation and non-shrinking icon — solid.

The min-w-0/flex-1 pattern fixes overflow regressions.


124-147: Footer relevance/view-source UX — looks good.

Semantic link, percentage formatting, and stable footer wrapper are on point.

archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx (4)

64-71: Using

with aria-label — nice accessibility upgrade.

Icon marked aria-hidden and non-interactive is correct.


85-94: Loading/empty states are accessible and informative.

aria-live="polite" and contextual hints on empty search are well done.


125-138: Title and description truncation with tooltips — solid.

Good min-w-0 usage and language badge non-shrinking.


153-173: Load-more control UX/a11y — LGTM.

Clear labeling, spinner hidden from SR when not needed, and full-width target.

Comment on lines +101 to 112
whileTap={{ scale: 0.98 }}
onClick={() => onItemSelect(item)}
className={cn(
"w-full text-left p-3 rounded-lg mb-1 transition-colors",
"hover:bg-white/5",
selectedItemId === item.id ? "bg-cyan-500/10 border border-cyan-500/30" : "border border-transparent",
"w-full text-left p-3 rounded-lg mb-1 transition-all",
"hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-cyan-500/50",
selectedItemId === item.id
? "bg-cyan-500/10 border border-cyan-500/30 ring-1 ring-cyan-500/20"
: "border border-transparent",
)}
aria-selected={selectedItemId === item.id}
aria-label={`${getItemTitle(item)}. ${getItemDescription(item)}`}
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Button semantics conflict with aria-selected.

aria-selected is intended for options in selectable containers (e.g., listbox). For buttons, either use aria-pressed or switch items to role="option".

Minimal change to keep current structure:

-              <motion.button
+              <motion.button
                 type="button"
                 key={item.id}
                 whileHover={{ x: 2 }}
                 whileTap={{ scale: 0.98 }}
                 onClick={() => onItemSelect(item)}
                 className={cn(
                   "w-full text-left p-3 rounded-lg mb-1 transition-all",
                   "hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-cyan-500/50",
                   selectedItemId === item.id
                     ? "bg-cyan-500/10 border border-cyan-500/30 ring-1 ring-cyan-500/20"
                     : "border border-transparent",
                 )}
-                aria-selected={selectedItemId === item.id}
+                role="option"
+                aria-selected={selectedItemId === item.id}
                 aria-label={`${getItemTitle(item)}. ${getItemDescription(item)}`}
               >

If you prefer staying with buttons, alternatively use:

- aria-selected={selectedItemId === item.id}
+ aria-pressed={selectedItemId === item.id}
📝 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
whileTap={{ scale: 0.98 }}
onClick={() => onItemSelect(item)}
className={cn(
"w-full text-left p-3 rounded-lg mb-1 transition-colors",
"hover:bg-white/5",
selectedItemId === item.id ? "bg-cyan-500/10 border border-cyan-500/30" : "border border-transparent",
"w-full text-left p-3 rounded-lg mb-1 transition-all",
"hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-cyan-500/50",
selectedItemId === item.id
? "bg-cyan-500/10 border border-cyan-500/30 ring-1 ring-cyan-500/20"
: "border border-transparent",
)}
aria-selected={selectedItemId === item.id}
aria-label={`${getItemTitle(item)}. ${getItemDescription(item)}`}
>
<motion.button
type="button"
key={item.id}
whileHover={{ x: 2 }}
whileTap={{ scale: 0.98 }}
onClick={() => onItemSelect(item)}
className={cn(
"w-full text-left p-3 rounded-lg mb-1 transition-all",
"hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-cyan-500/50",
selectedItemId === item.id
? "bg-cyan-500/10 border border-cyan-500/30 ring-1 ring-cyan-500/20"
: "border border-transparent",
)}
role="option"
aria-selected={selectedItemId === item.id}
aria-label={`${getItemTitle(item)}. ${getItemDescription(item)}`}
>
🤖 Prompt for AI Agents
In
archon-ui-main/src/features/knowledge/inspector/components/InspectorSidebar.tsx
around lines 101 to 112, the element is a button but uses aria-selected (meant
for selectable listbox/options), so either (A) keep the button semantics and
replace aria-selected with aria-pressed and ensure keyboard/toggle behavior
reflects a pressed state, or (B) treat the items as options by changing role to
"option" on the element, ensure the parent has the appropriate listbox/combobox
role, update keyboard handling to option semantics, and remove aria-pressed;
implement the chosen approach consistently across selection styling and event
handlers.

Comment on lines +82 to +90
const handleCopy = useCallback(async (text: string, id: string) => {
try {
await navigator.clipboard.writeText(text);
setCopiedId(id);
setTimeout(() => setCopiedId(null), 2000);
} catch (error) {
console.error("Failed to copy to clipboard:", error);
}
};
}, []);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Copy success timeout can clear a newer “Copied!” state (race).

If users copy A then B within 2s, A’s timer nulls B’s state. Guard the clear by id and prefer clearing any prior timer.

Apply within this block:

-      setTimeout(() => setCopiedId(null), 2000);
+      setTimeout(() => setCopiedId((v) => (v === id ? null : v)), 2000);

Additionally, consider centralizing timeout management:

// Add near state declarations:
const copyTimeoutRef = useRef<number | null>(null);

// In handleCopy:
if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);
copyTimeoutRef.current = window.setTimeout(() => {
  setCopiedId((v) => (v === id ? null : v));
}, 2000);

// Cleanup on unmount:
useEffect(() => () => copyTimeoutRef.current && clearTimeout(copyTimeoutRef.current), []);
🤖 Prompt for AI Agents
In
archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx
around lines 82 to 90, the current copy timeout can race and clear a newer
"Copied!" state; change handleCopy to use a ref-based timeout: add a
copyTimeoutRef via useRef<number | null>(null) near the state declarations,
clear any existing timeout at the start of handleCopy, set copiedId and then set
copyTimeoutRef to window.setTimeout that only clears the state if the current
copiedId matches the id (i.e., setCopiedId(v => v === id ? null : v)), and add a
useEffect cleanup to clear copyTimeoutRef on unmount. Ensure typings use number
for the timeout id and that clearTimeout is called on the stored id before
reassigning.

Comment on lines +92 to +125
const handleItemSelect = useCallback(
(item: DocumentChunk | CodeExample) => {
if (viewMode === "documents") {
const doc = item as DocumentChunk;
setSelectedItem({
type: "document",
id: doc.id || "",
content: doc.content || "",
metadata: {
title: doc.metadata?.title,
section: doc.metadata?.section,
relevance_score: doc.metadata?.relevance_score,
url: doc.metadata?.url,
tags: doc.metadata?.tags,
},
});
} else {
const code = item as CodeExample;
setSelectedItem({
type: "code",
id: String(code.id),
content: code.content || code.code || "",
metadata: {
language: code.language,
file_path: code.file_path,
summary: code.summary,
relevance_score: code.metadata?.relevance_score,
title: code.title || code.example_name,
},
});
}
},
[viewMode],
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Document selection metadata misses top-level fallbacks (title/section/url).

Manual selection uses only metadata fields, while auto-select uses top-level fields first. This causes inconsistent headers and missing URLs.

-          metadata: {
-            title: doc.metadata?.title,
-            section: doc.metadata?.section,
-            relevance_score: doc.metadata?.relevance_score,
-            url: doc.metadata?.url,
-            tags: doc.metadata?.tags,
-          },
+          metadata: {
+            title: doc.title || doc.metadata?.title,
+            section: doc.section || doc.metadata?.section,
+            relevance_score: doc.metadata?.relevance_score,
+            url: doc.url || doc.metadata?.url,
+            tags: doc.metadata?.tags,
+          },
📝 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
const handleItemSelect = useCallback(
(item: DocumentChunk | CodeExample) => {
if (viewMode === "documents") {
const doc = item as DocumentChunk;
setSelectedItem({
type: "document",
id: doc.id || "",
content: doc.content || "",
metadata: {
title: doc.metadata?.title,
section: doc.metadata?.section,
relevance_score: doc.metadata?.relevance_score,
url: doc.metadata?.url,
tags: doc.metadata?.tags,
},
});
} else {
const code = item as CodeExample;
setSelectedItem({
type: "code",
id: String(code.id),
content: code.content || code.code || "",
metadata: {
language: code.language,
file_path: code.file_path,
summary: code.summary,
relevance_score: code.metadata?.relevance_score,
title: code.title || code.example_name,
},
});
}
},
[viewMode],
);
const handleItemSelect = useCallback(
(item: DocumentChunk | CodeExample) => {
if (viewMode === "documents") {
const doc = item as DocumentChunk;
setSelectedItem({
type: "document",
id: doc.id || "",
content: doc.content || "",
metadata: {
title: doc.title || doc.metadata?.title,
section: doc.section || doc.metadata?.section,
relevance_score: doc.metadata?.relevance_score,
url: doc.url || doc.metadata?.url,
tags: doc.metadata?.tags,
},
});
} else {
const code = item as CodeExample;
setSelectedItem({
type: "code",
id: String(code.id),
content: code.content || code.code || "",
metadata: {
language: code.language,
file_path: code.file_path,
summary: code.summary,
relevance_score: code.metadata?.relevance_score,
title: code.title || code.example_name,
},
});
}
},
[viewMode],
);
🤖 Prompt for AI Agents
In
archon-ui-main/src/features/knowledge/inspector/components/KnowledgeInspector.tsx
around lines 92 to 125, the document-selection branch only pulls
title/section/url from metadata causing missing headers/URLs; update the
document case to fallback to top-level fields when metadata is absent (e.g.,
title: doc.metadata?.title || doc.title, section: doc.metadata?.section ||
doc.section, url: doc.metadata?.url || doc.url) and similarly ensure
tags/relevance_score also fall back to top-level equivalents if present so auto-
and manual-selection produce consistent metadata.

- Fixed copy timeout race condition using functional setState
- Added role="option" for proper aria-selected semantics
- Align manual selection with auto-selection pattern
- Use top-level fields as primary source with metadata as fallback
- Ensures consistent display of titles, sections, and URLs
@Wirasm Wirasm merged commit 3d5753f into main Sep 12, 2025
7 checks passed
@Wirasm Wirasm deleted the fix-ui-issues-document-inspector branch September 12, 2025 14:41
leonj1 pushed a commit to leonj1/Archon that referenced this pull request Oct 13, 2025
)

* Fix document inspector UI issues and improve accessibility

- Fixed copy button visibility when summaries overflow
- Added proper flex constraints and text truncation
- Enhanced metadata display in footer with relevance scores
- Improved accessibility with ARIA labels and semantic HTML
- Added better loading states and error handling
- Enhanced visual feedback with motion effects

* Fix CodeRabbit review issues

- Fixed copy timeout race condition using functional setState
- Added role="option" for proper aria-selected semantics

* Fix document metadata inconsistency in manual selection

- Align manual selection with auto-selection pattern
- Use top-level fields as primary source with metadata as fallback
- Ensures consistent display of titles, sections, and URLs
coleam00 added a commit that referenced this pull request Apr 7, 2026
Fix all Windows test failures across 6 packages by addressing three
root causes: path separator mismatches, symlink permission errors,
and SQLite test isolation.

**Production bug fixes (2 files):**
- `packages/paths/src/archon-paths.ts`: Fix `resolveProjectRootFromCwd`
  splitting on '/' only — now splits on both '/' and '\' via regex
- `packages/git/src/worktree.ts`: Same fix in `getWorktreeBase` and
  `isProjectScopedWorktreeBase`

**Test fixes (8 files):**
- `packages/paths/src/archon-paths.test.ts`: Use `path.join()` for Docker
  and ARCHON_HOME tests; skip symlink tests on Windows via `test.skipIf`
- `packages/git/src/git.test.ts`: Use `path.join()` for ARCHON_HOME path
- `packages/core/src/utils/worktree-sync.test.ts`: Add `normPath()` helper,
  normalize all path comparisons in mocks
- `packages/core/src/utils/defaults-copy.test.ts`: Add `normPath()` helper,
  normalize `includes()` checks and mkdir assertions
- `packages/isolation/src/providers/worktree.test.ts`: Normalize orphan
  directory path assertion for Windows backslashes
- `packages/isolation/src/worktree-copy.test.ts`: Use `path.join()` for
  copy/mkdir path expectations
- `packages/workflows/src/loader.test.ts`: Skip symlink test on Windows
- `packages/core/src/db/adapters/sqlite.test.ts`: Unique DB path per test

Closes #644

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tyone88 pushed a commit to Tyone88/Archon that referenced this pull request Apr 16, 2026
Fix all Windows test failures across 6 packages by addressing three
root causes: path separator mismatches, symlink permission errors,
and SQLite test isolation.

**Production bug fixes (2 files):**
- `packages/paths/src/archon-paths.ts`: Fix `resolveProjectRootFromCwd`
  splitting on '/' only — now splits on both '/' and '\' via regex
- `packages/git/src/worktree.ts`: Same fix in `getWorktreeBase` and
  `isProjectScopedWorktreeBase`

**Test fixes (8 files):**
- `packages/paths/src/archon-paths.test.ts`: Use `path.join()` for Docker
  and ARCHON_HOME tests; skip symlink tests on Windows via `test.skipIf`
- `packages/git/src/git.test.ts`: Use `path.join()` for ARCHON_HOME path
- `packages/core/src/utils/worktree-sync.test.ts`: Add `normPath()` helper,
  normalize all path comparisons in mocks
- `packages/core/src/utils/defaults-copy.test.ts`: Add `normPath()` helper,
  normalize `includes()` checks and mkdir assertions
- `packages/isolation/src/providers/worktree.test.ts`: Normalize orphan
  directory path assertion for Windows backslashes
- `packages/isolation/src/worktree-copy.test.ts`: Use `path.join()` for
  copy/mkdir path expectations
- `packages/workflows/src/loader.test.ts`: Skip symlink test on Windows
- `packages/core/src/db/adapters/sqlite.test.ts`: Unique DB path per test

Closes coleam00#644

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
joaobmonteiro pushed a commit to joaobmonteiro/Archon that referenced this pull request Apr 26, 2026
Fix all Windows test failures across 6 packages by addressing three
root causes: path separator mismatches, symlink permission errors,
and SQLite test isolation.

**Production bug fixes (2 files):**
- `packages/paths/src/archon-paths.ts`: Fix `resolveProjectRootFromCwd`
  splitting on '/' only — now splits on both '/' and '\' via regex
- `packages/git/src/worktree.ts`: Same fix in `getWorktreeBase` and
  `isProjectScopedWorktreeBase`

**Test fixes (8 files):**
- `packages/paths/src/archon-paths.test.ts`: Use `path.join()` for Docker
  and ARCHON_HOME tests; skip symlink tests on Windows via `test.skipIf`
- `packages/git/src/git.test.ts`: Use `path.join()` for ARCHON_HOME path
- `packages/core/src/utils/worktree-sync.test.ts`: Add `normPath()` helper,
  normalize all path comparisons in mocks
- `packages/core/src/utils/defaults-copy.test.ts`: Add `normPath()` helper,
  normalize `includes()` checks and mkdir assertions
- `packages/isolation/src/providers/worktree.test.ts`: Normalize orphan
  directory path assertion for Windows backslashes
- `packages/isolation/src/worktree-copy.test.ts`: Use `path.join()` for
  copy/mkdir path expectations
- `packages/workflows/src/loader.test.ts`: Skip symlink test on Windows
- `packages/core/src/db/adapters/sqlite.test.ts`: Unique DB path per test

Closes coleam00#644

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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