Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
node_modules/
ui/node_modules/
coverage/
ui/coverage/
src/
tests/
specs/
.specify/
.agents/
.claude/
*.log
.env*
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gitlocal Development Guidelines

Auto-generated from all feature plans. Last updated: 2026-04-04
Auto-generated from all feature plans. Last updated: 2026-04-08

## Active Technologies
- **Runtime**: Node.js 22+ (active LTS), TypeScript 5.x
Expand All @@ -19,6 +19,8 @@ Auto-generated from all feature plans. Last updated: 2026-04-04
- TypeScript 5.x on Node.js 22+ for server and CLI, TypeScript + React 18 for the UI + Hono, @hono/node-server, React 18, @tanstack/react-query, react-markdown, remark-gfm, rehype-highlight, Vite 7, Vitest, React Testing Library, esbuild (007-editor-empty-repo)
- TypeScript 5.x on Node.js 22+ + Hono, React 18, Vite 7, @tanstack/react-query, react-markdown, remark-gfm, rehype-highlight, Vitest, React Testing Library (007-editor-empty-repo)
- None; runtime state is derived from local filesystem metadata, git metadata, browser URL state, and in-memory server/UI state (007-editor-empty-repo)
- TypeScript 5.x on Node.js 22+ + Hono, React 18, Vite 7, @tanstack/react-query, Vitest, React Testing Library (008-ignored-files-visibility)
- None; runtime state is derived from local filesystem contents, git metadata, browser URL state, and in-memory server/UI state (008-ignored-files-visibility)

## Project Structure

Expand All @@ -44,9 +46,9 @@ npm run verify # Run tests, builds, and dependency audits
TypeScript 5.x + Node.js 22+: follow standard conventions. Use `.js` extensions on all imports (NodeNext module resolution). No Go, no Makefile, no shell scripts.

## Recent Changes
- 008-ignored-files-visibility: Added TypeScript 5.x on Node.js 22+ + Hono, React 18, Vite 7, @tanstack/react-query, Vitest, React Testing Library
- 007-editor-empty-repo: Added TypeScript 5.x on Node.js 22+ + Hono, React 18, Vite 7, @tanstack/react-query, react-markdown, remark-gfm, rehype-highlight, Vitest, React Testing Library
- 007-editor-empty-repo: Added TypeScript 5.x on Node.js 22+ for server and CLI, TypeScript + React 18 for the UI + Hono, @hono/node-server, React 18, @tanstack/react-query, react-markdown, remark-gfm, rehype-highlight, Vite 7, Vitest, React Testing Library, esbuild
- 007-editor-empty-repo: Added TypeScript 5.x on Node.js 22+ for server and CLI, TypeScript + React 18 for the UI + Hono, @hono/node-server, React 18, @tanstack/react-query, Vite 7, Vitest, React Testing Library, esbuild

<!-- MANUAL ADDITIONS START -->
<!-- MANUAL ADDITIONS END -->
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.4.7

- Added ignored file and folder visibility across the repository tree, folder listings, and search so local-only content remains discoverable in the UI.
- Marked ignored content consistently as local-only in navigation and active file context to clarify that it exists only on the local machine and will not be pushed to a remote.
- Fixed ignored-only directories and roots so they no longer fall into misleading empty states when ignored content is the only visible content.
- Updated Hono, Vitest, and Vite dependencies to publish-safe versions so the release verification audit passes cleanly.

## 0.4.6

- Reserved the next release version for the upcoming editor workspace and empty-repository UX improvements captured in `007-editor-empty-repo`.
Expand Down
489 changes: 250 additions & 239 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gitlocal",
"version": "0.4.6",
"version": "0.4.7",
"description": "Browse any local git repository in your browser",
"keywords": [
"git",
Expand Down Expand Up @@ -43,18 +43,18 @@
"prepublishOnly": "npm run verify"
},
"dependencies": {
"@hono/node-server": "^1.13.7",
"hono": "^4.7.5",
"@hono/node-server": "^1.19.13",
"hono": "^4.12.12",
"open": "^10.1.0"
},
"devDependencies": {
"@emnapi/core": "^1.9.1",
"@emnapi/runtime": "^1.9.1",
"@types/node": "^22.0.0",
"@vitest/coverage-v8": "^4.1.2",
"@vitest/coverage-v8": "^4.1.3",
"esbuild": "^0.27.4",
"typescript": "^5.8.3",
"vitest": "^4.1.2"
"vitest": "^4.1.3"
},
"license": "MIT",
"repository": {
Expand Down
35 changes: 35 additions & 0 deletions specs/008-ignored-files-visibility/checklists/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Specification Quality Checklist: Ignored Local File Visibility

**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-04-08
**Feature**: [spec.md](../spec.md)

## Content Quality

- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed

## Requirement Completeness

- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified

## Feature Readiness

- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification

## Notes

- Validated on 2026-04-08 after drafting. No open clarification markers remain.
- Scope intentionally includes current working-tree search results so ignored-item visibility stays consistent across the main browsing surfaces.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Local-Only Visibility Contract

## Repository Tree Contract

- `GET /api/tree` remains the source for repository tree and folder-list entries.
- The response entry shape adds:
- `localOnly: boolean`
- For the current working tree:
- Entries include tracked items, untracked local items already visible today, and ignored local items that match the feature rules.
- Ignored files and ignored folders are returned as normal browse entries with `localOnly: true`.
- Repository internals such as `.git` remain excluded.
- For non-current branches or historical views:
- Responses continue to come from git tree data.
- Returned entries use the same shape but `localOnly` is always `false`.

## Repository Info Contract

- `GET /api/info` continues to return repository summary metadata used by the app shell.
- `rootEntryCount` now counts visible ignored local root items in the current working tree.
- `rootEntryCount` still excludes repository internals and hidden dotfile entries that the landing-state logic intentionally ignores.

## Search Contract

- `GET /api/search` keeps its existing query parameters and response structure.
- Each search result adds:
- `localOnly: boolean`
- Current working-tree search behavior:
- Name searches can return ignored local files and folders with `localOnly: true`.
- Content searches, when used, can return ignored local files with `localOnly: true`.
- Non-current branch and historical search behavior remains unchanged apart from the added `localOnly: false` field.

## Active View Contract

- If a user opens an ignored local file or folder from the tree, folder list, or search results, the resulting active view continues to expose that item through the normal browsing flow.
- The active context must preserve a visible local-only cue near the selected item identity so users do not lose that explanation after opening the item.
- This feature does not add new ignore-management or tracking actions.

## Presentation Contract

- The file tree, content-panel directory list, and search results all use the same local-only wording pattern.
- The cue must:
- Be readable in mixed lists that include normal items.
- Avoid warning or error styling that implies failure.
- Distinguish local-only items without hiding open actions or making the item feel disabled.

## Test Coverage Contract

- Backend tests must cover:
- Current working-tree tree listings that include ignored files and ignored folders.
- Root-entry counting when visible content is ignored-only.
- Search responses that include local-only matches for current working-tree searches.
- Historical branch responses that continue excluding current working-tree ignored items.
- UI tests must cover:
- Local-only cue rendering in the file tree.
- Local-only cue rendering in the content-panel folder list.
- Local-only cue rendering in search results and preserved context after opening an ignored item.
- Ignored-only roots or folders avoiding misleading empty states.
70 changes: 70 additions & 0 deletions specs/008-ignored-files-visibility/data-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Data Model: Ignored Local File Visibility

## Browse Entry

- **Description**: A single repository item returned for current working-tree browsing and rendered in the left tree or content-panel directory list.
- **Fields**:
- `path`: Repository-relative path for the item.
- `name`: Display name derived from the final path segment.
- `type`: `file` or `dir`.
- `localOnly`: Whether the item is visible only in the local working tree and is not currently part of the tracked remote-facing repository state.
- **Validation rules**:
- `path` must remain inside the opened repository boundary.
- `localOnly` is `true` only for current working-tree items that match ignore rules.
- Repository internals such as `.git` must never be returned as browse entries.
- Ignored directories may appear as a single `dir` entry even when their descendants are also ignored.
- **Relationships**:
- Returned by the tree browsing contract.
- Consumed by the file tree and the content-panel directory list.

## Search Match

- **Description**: A repository item returned from working-tree or historical search.
- **Fields**:
- `path`: Repository-relative match path.
- `type`: `file` or `dir`.
- `matchType`: `name` or `content`.
- `line`: Matching line number for content matches when available.
- `snippet`: Short matching text for content matches when available.
- `localOnly`: Whether the matched item is a visible ignored local item.
- **Validation rules**:
- Current working-tree searches may return `localOnly: true`.
- Non-current branch or historical searches always return `localOnly: false`.
- `snippet` and `line` remain optional and are present only for content matches.
- **Relationships**:
- Produced by the search handler.
- Consumed by the quick-search UI and any future content-search UI using the same response shape.

## Repository Summary

- **Description**: Lightweight repository metadata used to decide initial landing behavior and other top-level UI state.
- **Fields**:
- `name`: Repository display name.
- `path`: Opened repository path.
- `currentBranch`: Current working-tree branch name.
- `isGitRepo`: Whether the opened folder is a valid git repository.
- `pickerMode`: Whether the app is in repository-picker mode.
- `version`: Running application version.
- `hasCommits`: Whether the repository has at least one reachable commit.
- `rootEntryCount`: Count of immediate visible root entries used for landing-state decisions.
- **Validation rules**:
- `rootEntryCount` includes visible ignored local items at the repository root.
- `rootEntryCount` excludes `.git` and hidden dotfiles that are still intentionally omitted from the landing-state count.
- **Relationships**:
- Returned by the repository info contract.
- Used by the app shell and content panel to avoid false empty states.

## Local-Only Presentation State

- **Description**: The presentation metadata that keeps the local-only explanation consistent wherever an ignored item is shown or selected.
- **Fields**:
- `label`: Short visible copy presented to users, expected to communicate "Local only".
- `supportingText`: Optional explanatory copy for surfaces with more room, clarifying that the item is not part of the remote-facing repository state.
- `emphasisLevel`: Lightweight visual treatment that distinguishes the item without presenting it as an error.
- **Validation rules**:
- The label must be understandable without assuming git expertise.
- The cue must remain readable beside normal browse metadata and actions.
- Selected ignored items continue showing the cue in their active context.
- **Relationships**:
- Derived from `BrowseEntry.localOnly` and `SearchMatch.localOnly`.
- Consumed by tree, folder-list, search-result, and active-item presentation components.
111 changes: 111 additions & 0 deletions specs/008-ignored-files-visibility/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Implementation Plan: Ignored Local File Visibility

**Branch**: `008-ignored-files-visibility` | **Date**: 2026-04-08 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `specs/008-ignored-files-visibility/spec.md`

## Summary

Surface ignored local files and folders in GitLocal's current working-tree browsing flows without making them look tracked. The implementation will extend shared tree and search entry metadata with a local-only flag, keep historical branch views unchanged, count visible ignored items when deciding whether a repository or folder is empty, and render a consistent local-only cue across the file tree, folder list, search results, and active item context.

## Technical Context

**Language/Version**: TypeScript 5.x on Node.js 22+
**Primary Dependencies**: Hono, React 18, Vite 7, @tanstack/react-query, Vitest, React Testing Library
**Storage**: None; runtime state is derived from local filesystem contents, git metadata, browser URL state, and in-memory server/UI state
**Testing**: Vitest, React Testing Library, existing unit and integration test suites
**Target Platform**: Local desktop browser served by the Node-based local server
**Project Type**: Full-stack web application
**Performance Goals**: Preserve current interactive browsing and search responsiveness for typical local repositories while adding local-only metadata
**Constraints**: Offline-capable, no database, no remote calls, GitHub-like browsing clarity, >=90% per-file branch coverage, repository-relative documentation only
**Scale/Scope**: Single local repository session with tree browsing, folder navigation, active file viewing, and quick file search

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- `TypeScript-first`: Pass. The feature extends existing TypeScript server and React client types instead of adding a parallel model layer.
- `Test coverage`: Pass. The change fits the current unit, handler, integration, and UI test suites and can preserve the required per-file coverage thresholds.
- `Fully local`: Pass. Ignored-item detection and presentation rely only on local filesystem and local git metadata.
- `Node.js-served React UI`: Pass. The work stays within the existing Hono server and Vite-served React SPA.
- `Clean & useful UI`: Pass. The plan adds a lightweight, consistent local-only cue rather than introducing a separate status workflow or visually noisy warning system.
- `Repository-relative paths`: Pass. This plan and the generated artifacts use repository-relative paths and links suitable for contributors on other machines.
- `Post-Phase-1 re-check`: Pass. The research, data model, quickstart, and contracts keep the feature local, typed, testable, and scoped to the existing browsing experience with no constitution violations introduced.

## Project Structure

### Documentation (this feature)

```text
specs/008-ignored-files-visibility/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── local-only-visibility.md
└── tasks.md
```

### Source Code (repository root)

```text
src/
├── handlers/
│ ├── files.ts
│ ├── git.ts
│ └── search.ts
├── git/
│ ├── repo.ts
│ └── tree.ts
└── types.ts

tests/
├── integration/
│ └── server.test.ts
└── unit/
├── git/
│ ├── repo.test.ts
│ └── tree.test.ts
└── handlers/
├── git.test.ts
└── search.test.ts

ui/
└── src/
├── App.tsx
├── App.css
├── App.test.tsx
├── services/
│ └── api.ts
├── types/
│ └── index.ts
└── components/
├── ContentPanel/
│ ├── ContentPanel.tsx
│ └── ContentPanel.test.tsx
├── FileTree/
│ ├── FileTree.tsx
│ ├── FileTree.test.tsx
│ └── FileTreeNode.tsx
└── Search/
├── SearchPanel.test.tsx
└── SearchResults.tsx
```

**Structure Decision**: Keep the existing single server + single UI structure. Server work will enrich current working-tree entry/search metadata and root-entry counting, while UI work will apply a shared local-only presentation across the tree, folder list, search results, and active item context.

## Phase 0: Research Focus

- Choose the smallest shared server/client metadata shape that can mark ignored local items across tree entries, folder rows, and search results.
- Confirm how to enumerate current working-tree items so ignored files and ignored folders become visible while repository internals remain hidden.
- Confirm how repository-empty logic should treat ignored visible items so ignored-only roots and folders do not render misleading empty states.

## Phase 1: Design Focus

- Define the normalized browse-entry and search-result shapes, including the local-only flag used by both server and UI.
- Define cue placement and wording for the file tree, content-panel directory list, search results, and active item header so users understand the item remains local.
- Define the verification approach for ignored files, ignored directories, ignored-only roots, and transitions where an item's local-only status changes or the item disappears.

## Complexity Tracking

No constitution violations are expected for this feature.
Loading