Commit graph

242 commits

Author SHA1 Message Date
kite
d84d76b6dc fix(session): isolate test sessions to test-sessions subdirectory
Some checks are pending
CI / test (push) Waiting to run
Prevent make test from polluting ~/.opencodereview/sessions/ with
thousands of var-folders-* directories by redirecting test session
writes to ~/.opencodereview/test-sessions/.

Introduce a package-level sessionSubDir variable (default "sessions")
and an exported UseTestSessions() function that switches it to
"test-sessions". Each test package that creates sessions calls
UseTestSessions() from init() in an init_test.go file.
2026-06-30 13:23:21 +08:00
kite
e3813ceeda docs: add timeout_sec and OCR_LLM_TIMEOUT to configuration reference
Some checks are pending
CI / test (push) Waiting to run
2026-06-30 11:29:06 +08:00
kite
c076b8e17f docs(llm): clarify timeout override semantics and resolution-path coverage 2026-06-30 11:25:21 +08:00
MurphyYi
eae863502b
fix: add configurable HTTP timeout for LLM API calls (#238)
* fix: add configurable HTTP timeout for LLM API calls

The LLM HTTP client had no user-configurable request timeout. When the
LLM API becomes unresponsive (e.g., rate limiting, network issues), the
ocr process hangs indefinitely with 0% CPU, holding an ESTABLISHED TCP
connection that never completes.

Changes:
- Add Timeout field to ResolvedEndpoint struct
- Add OCR_LLM_TIMEOUT environment variable (value in seconds)
- Add timeout_sec field to config.json llm and provider sections
- Pass timeout from ResolvedEndpoint to ClientConfig in NewLLMClient

The default timeout remains 5 minutes when not explicitly configured.
Users can now set a shorter timeout via:
  - Environment: OCR_LLM_TIMEOUT=120
  - Config file: {"llm": {"timeout_sec": 120}}

Fixes #237

* fix: address Copilot review feedback

- Make OCR_LLM_TIMEOUT a global override (works with any endpoint strategy)
- Add proper overflow detection for timeout values (check before multiply)
- Add validateTimeoutSec helper with negative/overflow guards
- Add comprehensive tests for timeout parsing, validation, and forwarding
- Reject negative timeout_sec in config files with explicit error

* fix: address review feedback for timeout configuration

- parseTimeoutEnv now returns errors instead of silent fallback for invalid values (negative, non-integer, overflow)
- Reuse validateTimeoutSec in parseTimeoutEnv to eliminate duplicated validation logic
- Remove redundant comment in tryOCREnv
- Add missing tests:
  - TestResolveEndpoint_ProviderConfigTimeoutSec
  - TestResolveEndpoint_ProviderConfigNegativeTimeoutSec
  - TestResolveEndpoint_EnvTimeoutOverridesConfigTimeout
  - TestResolveEndpoint_EnvTimeoutOverridesProviderTimeout
  - TestResolveEndpoint_InvalidEnvTimeoutWithConfig
  - TestResolveEndpoint_NegativeEnvTimeoutWithConfig
2026-06-30 11:22:24 +08:00
kite
62972cbcf8 refactor(pages): improve hero terminal display with semantic colors, reorder lines, and add cursor blink
Some checks failed
CI / test (push) Waiting to run
Deploy Pages / build (push) Has been cancelled
Deploy Pages / deploy (push) Has been cancelled
- Reorder terminal lines: move Summary above the separator line
- Change command from range mode (--from/--to) to workspace mode (ocr review)
- Apply semantic color scheme: brand, command, path, success, action, dim
- Remove unused terminal prompt icon and hasIcon field
- Add blinking cursor animation for the last terminal line
- Reduce line number container width after icon removal
2026-06-29 22:52:29 +08:00
kite
403335ef5a docs: add official website link to READMEs and update screenshots
Some checks are pending
CI / test (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
Add official website URL to the "What is Open Code Review?" section
across all localized READMEs. Update highlights and benchmark
screenshots for en/zh, add Japanese versions (highlights-ja.png,
benchmark-ja.png), and add id="highlights" to HighlightsSection
for screenshot tool targeting.
2026-06-29 17:20:39 +08:00
kite
86d474c5d7 feat(i18n): auto-detect browser language for default locale selection
Use navigator.languages to detect the user's preferred language and
automatically select the matching locale (zh/ja/en) on first visit,
falling back to English when no match is found.
2026-06-29 16:43:04 +08:00
kite
dc30b81ad6 fix(i18n): correct ocr viewer description from "review results" to "session logs"
The ocr viewer command is a session history viewer, not a results browser.
Updated the description in all three locales (en, zh, ja) to accurately
reflect its purpose.
2026-06-29 16:19:46 +08:00
hezheng.lsw
3e01d0db17
feat(pages): consolidate icons, add scroll-to-top, responsive titles (#241)
* feat(pages): redesign landing page UI with i18n support

- Redesign all sections based on design file: Navbar, Hero, Highlights, UseCases, Features, Benchmark, QuickStart, Footer
- Add scroll fade-in animation with IntersectionObserver
- Implement full i18n (English/Chinese) with language toggle button
- Add SVG icons and image assets
- Style refinements: table borders, step containers, button styles, spacing

* feat(pages): redesign Docs page with i18n, responsive sidebar, and aligned copy interaction

- Redesign DocsPage UI based on reference HTML design
- Add i18n support for all Docs content (en/zh/ja)
- Fix right sidebar CONTENTS nav with fixed positioning
- Add container backgrounds (4% opacity, 16% border)
- Hide CONTENTS sidebar on mobile instead of alternative UI
- Align copy icon and toast interaction with QuickStart section
- Add new SVG icon assets for docs page
- Add Japanese language support
- Add ColorBends animated background component
- Add responsive hooks and FadeInSection animation
- Add Benchmark, Features, QuickStart standalone pages
- Update Navbar, Footer, and LandingPage components

* refactor: cleanup design drafts, rename Chinese assets, UI improvements

- Remove unused design draft folders (html-files, html-files (1), inpt, doc)
- Rename Chinese-named image files (容器-4_*.svg → provider-*.svg)
- Add language switcher icon to Navbar with dynamic character display
- Align Footer padding with Navbar (32px desktop, 16px mobile)
- Fix CONTENTS sidebar position on wide screens
- Add i18n support for Docs CONTENTS title
- Fix clipboard copy fallback for HTTP/LAN environments
- Adjust Toast padding, benchmark medal sizes
- Swap highlight stats positions (Adoption Rate ↔ Active Users)
- Update stat4 value to 25.10% and stat5 caption to Battle-tested
- Unify Hero buttons size with Navbar Get Started button

* refactor: rename icon assets with semantic English names and cleanup unused files

- Rename all svg_*.svg icons to semantic names based on usage context:
  - icon-feature-*.svg for feature section icons
  - icon-usecase-*.svg for use case section icons
  - icon-chevron-*.svg, icon-copy.svg, icon-play.svg for UI controls
  - icon-github.svg, icon-language.svg, icon-sort.svg, icon-terminal-prompt.svg
- Remove unused assets: 5 unreferenced svg icons, image_9e7821.png, provider-8.svg
- Remove debug screenshots: debug-screenshot.png, debug-wide.png
- Remove .vsix build artifact and add *.vsix to .gitignore
- Update all import paths in components accordingly

* fix: address PR review feedback - bugs and improvements

- Fix copy-paste bug: step3Label1 had wrong text in all 3 languages
  - en: 'Interactive Setup (Recommended)' → 'Review Commands'
  - zh: '交互式设置(推荐)' → '运行审查命令'
  - ja: '対話式セットアップ(推奨)' → 'レビュー実行'
- Fix inconsistent indentation (4 spaces → 2 spaces) in i18n files
- Add .catch() handler for navigator.clipboard.writeText() in QuickStartSection
- Check document.execCommand('copy') return value before showing toast
- Extract fallbackCopy helper to deduplicate clipboard logic
- Remove unused useCallback import from HighlightsSection
- Move @types/three from dependencies to devDependencies
- Add i18n key 'hero.terminal' for hardcoded Terminal label

* fix: revert vscode .gitignore change and remove duplicate root SVGs

- Revert extensions/vscode/.gitignore to upstream state (remove *.vsix rule)
- Remove root-level brandicon.svg, claude code icon.svg, codex icon.svg
  (identical copies already exist in pages/src/assets/images/ with proper names)

* fix: reorder highlights stats to match design reference

- Reorder stats: 20K+ Active Users → > 30% Adoption Rate → 1M+ Tasks → 1/9 Token Cost → 25.10% AACR-BENCH
- Update stat1 value from 30K+ to 20K+
- Sync all three languages (en/zh/ja)

* chore: remove unused debug screenshots

* chore: remove unused image_9e7821.png

* feat(pages): consolidate icons, add scroll-to-top, responsive titles

- Merge provider-1~7.svg into single icon-ocr-source.svg
- Add ScrollToTop component for tab navigation reset
- Add tablet breakpoint (36px) to section titles for responsive scaling

* refactor(pages): extract shared responsive title hook, fix indentation

- Create useSectionTitleStyle hook to eliminate nested ternaries
- Replace duplicated responsive logic in 4 section components
- Fix fragment children indentation in App.tsx

Addresses code review feedback from PR #241
2026-06-29 15:44:41 +08:00
kite
d22bd7fa3d fix(i18n): correct inaccurate translations in zh and ja locales
- zh: navbar.benchmark '排行榜' → '基准测试' to match benchmark section
- zh: footer.copyright fix year placement to follow convention
- zh: docs.configKeyExtraBody '供应商' → '提供商' for terminology consistency
- ja: highlights.stat4Caption add missing particle 'との'
- ja: benchmark.colPrecision '精度' → '適合率' (standard ML term for precision)
2026-06-29 15:15:51 +08:00
hezheng.lsw
08e7846a37
refactor: cleanup design drafts, rename Chinese assets, UI improvements (#239)
* feat(pages): redesign landing page UI with i18n support

- Redesign all sections based on design file: Navbar, Hero, Highlights, UseCases, Features, Benchmark, QuickStart, Footer
- Add scroll fade-in animation with IntersectionObserver
- Implement full i18n (English/Chinese) with language toggle button
- Add SVG icons and image assets
- Style refinements: table borders, step containers, button styles, spacing

* feat(pages): redesign Docs page with i18n, responsive sidebar, and aligned copy interaction

- Redesign DocsPage UI based on reference HTML design
- Add i18n support for all Docs content (en/zh/ja)
- Fix right sidebar CONTENTS nav with fixed positioning
- Add container backgrounds (4% opacity, 16% border)
- Hide CONTENTS sidebar on mobile instead of alternative UI
- Align copy icon and toast interaction with QuickStart section
- Add new SVG icon assets for docs page
- Add Japanese language support
- Add ColorBends animated background component
- Add responsive hooks and FadeInSection animation
- Add Benchmark, Features, QuickStart standalone pages
- Update Navbar, Footer, and LandingPage components

* refactor: cleanup design drafts, rename Chinese assets, UI improvements

- Remove unused design draft folders (html-files, html-files (1), inpt, doc)
- Rename Chinese-named image files (容器-4_*.svg → provider-*.svg)
- Add language switcher icon to Navbar with dynamic character display
- Align Footer padding with Navbar (32px desktop, 16px mobile)
- Fix CONTENTS sidebar position on wide screens
- Add i18n support for Docs CONTENTS title
- Fix clipboard copy fallback for HTTP/LAN environments
- Adjust Toast padding, benchmark medal sizes
- Swap highlight stats positions (Adoption Rate ↔ Active Users)
- Update stat4 value to 25.10% and stat5 caption to Battle-tested
- Unify Hero buttons size with Navbar Get Started button

* refactor: rename icon assets with semantic English names and cleanup unused files

- Rename all svg_*.svg icons to semantic names based on usage context:
  - icon-feature-*.svg for feature section icons
  - icon-usecase-*.svg for use case section icons
  - icon-chevron-*.svg, icon-copy.svg, icon-play.svg for UI controls
  - icon-github.svg, icon-language.svg, icon-sort.svg, icon-terminal-prompt.svg
- Remove unused assets: 5 unreferenced svg icons, image_9e7821.png, provider-8.svg
- Remove debug screenshots: debug-screenshot.png, debug-wide.png
- Remove .vsix build artifact and add *.vsix to .gitignore
- Update all import paths in components accordingly

* fix: address PR review feedback - bugs and improvements

- Fix copy-paste bug: step3Label1 had wrong text in all 3 languages
  - en: 'Interactive Setup (Recommended)' → 'Review Commands'
  - zh: '交互式设置(推荐)' → '运行审查命令'
  - ja: '対話式セットアップ(推奨)' → 'レビュー実行'
- Fix inconsistent indentation (4 spaces → 2 spaces) in i18n files
- Add .catch() handler for navigator.clipboard.writeText() in QuickStartSection
- Check document.execCommand('copy') return value before showing toast
- Extract fallbackCopy helper to deduplicate clipboard logic
- Remove unused useCallback import from HighlightsSection
- Move @types/three from dependencies to devDependencies
- Add i18n key 'hero.terminal' for hardcoded Terminal label

* fix: revert vscode .gitignore change and remove duplicate root SVGs

- Revert extensions/vscode/.gitignore to upstream state (remove *.vsix rule)
- Remove root-level brandicon.svg, claude code icon.svg, codex icon.svg
  (identical copies already exist in pages/src/assets/images/ with proper names)

* fix: reorder highlights stats to match design reference

- Reorder stats: 20K+ Active Users → > 30% Adoption Rate → 1M+ Tasks → 1/9 Token Cost → 25.10% AACR-BENCH
- Update stat1 value from 30K+ to 20K+
- Sync all three languages (en/zh/ja)

* chore: remove unused debug screenshots

* chore: remove unused image_9e7821.png
2026-06-29 14:42:43 +08:00
kite
0881ad87b8 fix(ci): use --replace-all for git safe.directory to prevent self-hosted runner failure
Some checks are pending
CI / test (push) Waiting to run
On self-hosted runners, _github_home/.gitconfig persists across jobs.
The ocr-review workflow used --add which accumulated multiple safe.directory
values over time. Once multiple values existed, other workflows using plain
git config (without --add/--replace-all) failed with "cannot overwrite
multiple values with a single value".

Unify all workflows to use --replace-all, which clears previous values and
writes exactly one entry regardless of prior state.
2026-06-29 11:37:23 +08:00
dependabot[bot]
0d601eaf58
chore(deps): bump the go-dependencies group with 12 updates (#232)
Some checks failed
CI / test (push) Has been cancelled
Bumps the go-dependencies group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) | `2.0.3` | `2.0.4` |
| [github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go) | `1.47.0` | `1.52.0` |
| [github.com/openai/openai-go/v3](https://github.com/openai/openai-go) | `3.39.0` | `3.41.0` |
| [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/sdk/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |
| [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) | `1.43.0` | `1.44.0` |


Updates `charm.land/lipgloss/v2` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/charmbracelet/lipgloss/releases)
- [Commits](https://github.com/charmbracelet/lipgloss/compare/v2.0.3...v2.0.4)

Updates `github.com/anthropics/anthropic-sdk-go` from 1.47.0 to 1.52.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-go/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-go/compare/v1.47.0...v1.52.0)

Updates `github.com/openai/openai-go/v3` from 3.39.0 to 3.41.0
- [Release notes](https://github.com/openai/openai-go/releases)
- [Changelog](https://github.com/openai/openai-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/openai-go/compare/v3.39.0...v3.41.0)

Updates `go.opentelemetry.io/otel` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/exporters/stdout/stdouttrace` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/metric` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/sdk` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/sdk/metric` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

Updates `go.opentelemetry.io/otel/trace` from 1.43.0 to 1.44.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...v1.44.0)

---
updated-dependencies:
- dependency-name: charm.land/lipgloss/v2
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-dependencies
- dependency-name: github.com/anthropics/anthropic-sdk-go
  dependency-version: 1.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: github.com/openai/openai-go/v3
  dependency-version: 3.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdoutmetric
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/metric
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/sdk/metric
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 18:02:15 +08:00
kite
dde66f1dee docs: update OpenSSF badge to Silver level
Some checks are pending
CI / test (push) Waiting to run
2026-06-27 11:19:28 +08:00
kite
f2a6f7c5c7 ci: add 80% statement coverage threshold check
Add coverage threshold enforcement in CI workflow and Makefile to satisfy
OpenSSF Best Practices Silver badge test_statement_coverage80 criterion.
2026-06-27 11:13:22 +08:00
zephyrq-z
b109baf0c2
Feature/rule link to files (#226)
* feat: support inline content and file path resolution for rule field

- rule field auto-detects: .md/.txt/.markdown ending = file path, otherwise inline
- file paths: project-relative first, then as absolute path
- safety: stat before read (512KB cap), extension whitelist, symlink resolution
- tightened heuristic: values with spaces treated as inline to avoid false positives
- guard against empty repoDir to avoid CWD-relative resolution
- 5-language README docs updated with file path usage and first-match-wins behavior
- 15 new unit tests covering all resolution branches

Closes #67
Supersedes #87

* update readme

* feat: update rule resolution logic to clear rules for missing or invalid files

* feat: update rule field description to clarify file path detection criteria

* feat: enhance rule file resolution to block path traversal and improve validation

* fix: clean up tryReadRuleFile and add missing blank line

- Add blank line between matchProjectRuleEntry and allowedRuleExts (Issue 1)
- Remove dead code '|| repoDir == ' in tryReadRuleFile (Issue 2)
- Remove unnecessary warning when repoDir is empty but path is absolute (Issue 3)
2026-06-27 11:06:38 +08:00
kite
30c083c0de test: improve coverage for tool package from 79.5% to 93.6%
Add tests for response_message, stub providers, code_search Execute/Tool,
filereader commit mode with and without Runner, file_find git repo modes,
file_read error paths, and comment_collector ReplaceSince edge cases.
2026-06-27 11:00:23 +08:00
kite
793bbc6a61 test: improve coverage for telemetry package and exclude extensions from build targets
Add comprehensive tests for events, metrics, provider, shutdown, span,
and exporter in the telemetry package. Update Makefile to exclude the
extensions directory from test, fmt, vet, and check targets.
2026-06-27 10:43:45 +08:00
kite
9a11fc1302 test: improve coverage for cmd/opencodereview package from 42% to 70%
Add comprehensive unit tests covering config dispatch, emit run result,
git helpers, provider commands, provider TUI pure functions and View
rendering, shared utilities, flags parsing, scan command flags, and
small file entry points (version, viewer, llm, rules commands).
2026-06-27 01:47:48 +08:00
kite
38fc691498 fix: skip permission-based tests when running as root in CI 2026-06-27 00:42:41 +08:00
kite
be4b0b0aa9 test: improve coverage for viewer package from 35% to 92%
Add comprehensive tests for handler, server, and store modules including
LoadSession full parsing, template rendering, and error/edge-case paths.
2026-06-27 00:34:12 +08:00
kite
9f71753f68 test: improve coverage for template and pathutil packages
template: 71.2% → 84.9% — add Validate error-branch tests for both
Template and ScanTemplate, ApplyLanguage coverage for optional scan
tasks (DedupTask, ProjectSummaryTask), nil-optional-task path, and
non-system message skip verification.

pathutil: add tests for non-existent path error, relative path
resolution, nested symlink traversal, and additional WithinBase
edge cases.
2026-06-27 00:22:30 +08:00
kite
453c4f9c76 test: add coverage tests for agent, llm, llmloop, and scan packages
Raise statement coverage to 80%+ across four core packages to meet
FLOSS best practice badge criteria. Key additions:

- internal/scan (67% → 90%): getters, lookupDiff, filterScanItems,
  whyExcluded all branches, extFromPath, maybeRunPlan/ProjectSummary/
  Dedup success paths, executeSubtask, Run pipeline, dispatchSubtasks.
- internal/agent (60% → 83%): getters, filterDiffs, findDiff,
  resolveSystemRule, injectDiffMap, executeReviewFilter, executePlanPhase,
  executeSubtask, dispatchSubtasks.
- internal/llmloop (59% → 80%): warnings, tool calls, usage recording,
  compression lifecycle (cancel/tryApply/run/trigger), partitionMessages.
- internal/llm (67% → 80%): parseBpeData, embedded BPE loader, message
  constructors, ExtractText, ChatResponse helpers, parseShellRC.
2026-06-27 00:15:28 +08:00
kite
110e5284fb fix: stabilize TestDiscoverRepos_FindsRepos with explicit mtime ordering
The test relied on filesystem ModTime for sorting repos, but files
created in rapid succession can share the same mtime on CI, making
the sort order non-deterministic. Use os.Chtimes to guarantee repo-b
has a strictly later mtime than repo-a.
2026-06-26 23:31:51 +08:00
kite
b3eb4b3491 test: add unit tests for output_helpers, config, model, stdout, and telemetry packages 2026-06-26 23:26:49 +08:00
kite
5bd291739d chore: remove unused cmd/testdiff debug helper
The testdiff CLI was an early-stage tool for manually testing the
internal/diff package. It has no external references and its role is
fully covered by the existing unit tests in internal/diff/.
2026-06-26 23:19:22 +08:00
kite
904ecd3ae1 test: expand unit test coverage for agent, llm, llmloop, and tool packages
Add integration-style tests with fake LLM clients for agent dispatch and
llmloop runner, plus new unit test files for gitcmd, session/history,
tool/code_comment, tool/filereader_read, and viewer/store packages.
2026-06-26 23:09:11 +08:00
kite
98fe309f03 test: add unit tests for pure logic functions across 6 packages
Add table-driven tests for pure computation functions with no external
dependencies, improving overall coverage from 45.9% to 48.8%.

Covered functions:
- suggestdiff: ComputeLineDiff (LCS algorithm)
- tool: CommentCollector, DiffMap, FileReadDiff, Registry, ParseReviewMode, scanLines
- llmloop: CountMessagesTokens, groupIntoRounds, partitionMessages, StripMarkdownFences
- agent: buildFilterCommentsJSON, parseFilterResponse, extFromPath, formatToolDefs, BuildToolDefs
- viewer: truncateText, formatDuration, formatTime
2026-06-26 22:41:35 +08:00
kite
e1a6a404ba feat(ci): add Sigstore attestation for release artifacts
Add build provenance attestation to the release workflow using
actions/attest-build-provenance with OIDC keyless signing.
Document release signature verification in SECURITY.md.
2026-06-26 22:18:03 +08:00
kite
b3b4f238a3 docs: add security assurance case and use signed tags
Add ASSURANCE_CASE.md covering threat model, secure design principles
(Saltzer & Schroeder), OWASP/CWE countermeasures, and automated
verification. Switch tag command from annotated (-a) to signed (-s) to
match the assurance case's integrity claims.
2026-06-26 21:30:57 +08:00
kite
3f4155170e ci: add govulncheck, job timeout, dependabot and preserve debug symbols in dev builds
- Add govulncheck step to CI pipeline for vulnerability scanning
- Set 15-minute timeout on CI test job
- Add dependabot config for weekly Go module and GitHub Actions updates
- Split LD_FLAGS so dev builds retain debug symbols while release
  builds remain stripped with -s -w
2026-06-26 21:02:33 +08:00
Zheng Feng
491a2ac6d0
docs(examples): update node.js to 24 in the github action yml (#228) 2026-06-26 20:24:33 +08:00
kite
8a987d3d29 docs: add ROADMAP.md with project direction for the next year
Cover planned work (JetBrains plugin, standard MCP integration,
Ultra mode, domain-specific long-term memory) and explicit non-goals.
Satisfies the OpenSSF Best Practices silver badge documentation_roadmap
criterion.
2026-06-26 20:02:04 +08:00
kite
410cabf488 docs: add GOVERNANCE.md, CODE_OF_CONDUCT.md and clean up SECURITY.md
- Rewrite GOVERNANCE.md with expanded structure: goals, scope, project
  values, detailed roles, decision-making process, merge expectations,
  maintainer lifecycle, and continuity sections.
- Add CODE_OF_CONDUCT.md covering expected behavior, unacceptable
  behavior, scope, reporting, and enforcement.
- Remove fictitious email address from SECURITY.md, keeping only
  GitHub Private Vulnerability Reporting as the reporting channel.
2026-06-26 19:38:37 +08:00
wxwxwxw_orange
751602776e
feat: improve config provider TUI interaction (#213)
* feat: improve config provider TUI interaction
- Support wrap-around navigation in provider, custom provider, and model lists
  (up at first item jumps to last, down at last item jumps to first)
- Add d key to delete custom models in model selection step with confirmation prompt
- Add protocol selection (anthropic/openai) to manual configuration flow
  and respect UseAnthropic setting in saved config
- Preserve manual protocol selection when re-entering the form
- Fix manual form input fields losing focus after returning from next step
- Use safe slice removal in removeFromSlice to avoid backing array corruption

* fix: address code review feedback
- Restore Blur() calls in handleManualFormEnter to prevent visual focus artifacts
  when transitioning between manual form steps
- Add empty-providers guard in handleUp/handleDown to avoid negative index
- Consolidate redundant protocolIdx checks into single if/else in viewManualTab
  and viewCustomProviderForm for clarity

* fix: persist custom model deletions and support masked auth token editing
- Track deleted custom models in TUI and apply them on exit
  (both confirm and cancel paths) to keep config.json in sync
- Clear custom provider's active Model field when that model is deleted,
  preventing stale "model" reference in the provider list label
- Add masked display for manual config Auth Token to allow easy re-entry,
  matching the official provider flow (any key clears and starts fresh)

* test: update manual form tests for masked auth token behavior
Update TestProviderTUI_ManualFormPrefilledValues,
TestProviderTUI_ManualFormEscRestoresOriginalValues, and
TestProviderTUI_ManualFormPrefilledWhenProviderSet to assert
the new masked display state (manualTokenMasked + manualTokenOriginal)
instead of the raw token value.

* feat: refine config provider TUI flows and session persistence
Custom provider interactions:
- Simplify create/edit form to Name → Protocol → URL → API Key → Auth Header
- After create or edit save, jump straight into the model list for that provider
- Support comma-separated model names in the custom model input
- Show masked API key in edit form; empty Auth Header defaults to (Authorization)
- Populate edit form from existingCfg to avoid stale list data after in-session saves
Model selection and highlight:
- Green highlight follows the persisted active model, not the cursor position
- Prefer provider entry.model over global cfg.model when resolving active model
- Deleting a non-active model keeps the current green highlight unchanged
Delete and navigation:
- Delete custom providers (d) and custom models (d) with confirmation prompts
- Persist create/edit/model-select/add/delete changes to disk during the session
- Fix custom provider deletion not surviving Esc exe-entry
Tests:
- Add coverage for model highlight, delete-model behavior, and create→model-list flow
- Update manual/custom form tests for masked token and session save behavior

* refactor: address provider TUI code review feedback
- Remove dead helper removeFromSlice (superseded by removeModels)
- Move misplaced doc comment to applyEditCustomProviderSave
- Drop redundant applyProviderDeletions post-TUI call so provider
  deletions rely solely on the in-session save
- Fix brace/indent drift in updateDeleteModelConfirm and cache the
  model list instead of recomputing m.models() twice

* feat: refine provider TUI flows and manual config form
Custom provider flow:
- Default protocol to anthropic on the new-provider form
- Single-name model input; reject duplicates with inline error and
  preserve the typed value so the user can edit instead of re-typing
- Drop the global green highlight; cursor/blue is the only selection cue
Manual configuration form:
- Add Auth Header step (URL → Protocol → Model → Auth Token → Auth Header)
  and persist it to Llm.AuthHeader on confirm
- Reorder so Auth Header is always entered last
- Make Auth Token required; empty Enter stays on the field
- Show every field's label on every render, even when empty, matching
  the custom-provider form style
Tests:
- Cover custom model input add / duplicate paths
- Cover manual form prefill of Llm.AuthHeader
- Cover that deleting a non-active model keeps the active model intact

* Improve provider TUI validation, persistence, and code clarity.

Address code review feedback: align custom Auth Header validation with manual mode; fix savedInSession after model deletion; refactor applyEditCustomProviderSave to return error; remove dead applyModelDeletions/deletedModels; document ExtraBody shallow-copy limit. Also fix manual/custom form UX (token skip on edit, k key input, formError scoping, switch indentation).

* Fix provider/model TUI list ordering and add test coverage.

Address review and UX feedback: remove model list sorting in provider and config model TUIs; preserve Models list order when selecting active model (ensureModelInList); add test for duplicate rename on custom provider edit. Includes prior review fixes for savedInSession, applyEditCustomProviderSave error return, and dead code removal.

* Normalize AuthHeader at apply layer and simplify UseAnthropic assignment.
Call NormalizeAuthHeader in applyManualConfig and applyCustomProviderConfig before save; simplify UseAnthropic assignment in manual config; add unit tests.

* Address review: lowercase error strings and newProviderTUI signature.

Use lowercase "failed to save" errors; replace variadic configPath with string and remove configPathFromArgs; pass "" in tests when no path; gofmt provider_tui.go.
2026-06-26 17:01:57 +08:00
Hyeseong Kim
a1e4cf6b43
feat: support HTTP extra headers (#169)
* feat: support HTTP extra headers

Resolves #166

* update documentation; assisted-by GLM-5.1

* Update cmd/opencodereview/config_cmd.go

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update internal/llm/resolver.go

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* prevent header conflicts

* allow quoted values

* update docs

* add user-agent to extra_headers blocklist

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-26 15:42:29 +08:00
xyJen
02a6423894
fix(vscode): retain sidebar webview context when hidden (#227)
Set retainContextWhenHidden on the sidebar WebviewView registration so
review state survives switching to other sidebar panels (Fixes #224).
2026-06-26 15:36:16 +08:00
kite
c8ff673667
feat: add Cursor plugin support (#221)
Add .cursor-plugin/plugin.json manifest alongside existing Claude Code
and Codex plugin integrations, reusing the shared SKILL.md. Update all
README versions (EN, zh-CN, ja-JP, ko-KR, ru-RU) with Cursor badge and
installation instructions.
2026-06-26 10:35:02 +08:00
kite
779c4a8290 fix: enable code_search to find content in untracked files
git grep defaults to searching only tracked files, causing code_search
to miss untracked directories like internal/mcp/. Add --untracked flag
in workspace mode so both tracked and untracked files are searched.

Also fix non-git-directory detection to use exit code 128 instead of
hardcoded English error string, making it locale-independent.
2026-06-26 00:01:44 +08:00
zephyrq-z
b1db14f4ea
Feature/vscode i18n (#219)
* feat(i18n): add localization support for Chinese and update description in package.json

* feat: add internationalization support to various components and views

- Integrated translation functionality using `useT` from `I18nProvider` across multiple components including CustomProviderManager, EnvSetupGuide, FileList, LogViewer, PasswordInput, Select, and various views (CancelledView, ConfigView, DoneView, EmptyView, FailedView, IdleView, RunningView).
- Replaced hardcoded strings with localized strings to enhance user experience for different languages.
- Updated button labels, titles, and hints to reflect the new translation implementation.

* fix: correct regex for validating command names in resolveBin function(预存代码,非本次 PR 引入,阻塞了 lint,这里进行修复)

* chore: update open-code-review-vscode-0.1.0.vsix binary file

* fix: address OpenCodeReview bot findings for i18n PR

   - Fix singular '1 hour ago' / '1 小时前' in GitService.formatRelative
   - Replace hardcoded 'en' locale with dynamic resolveLocale in CliService.install
   - Move hardcoded full-width colon into i18n translation strings
   - Narrow locale type from string to SupportedLocale in messages, stores
   - Extract toHtmlLang() helper to deduplicate locale→HTML lang mapping
   - Replace nested ternary with mapping object in ConfigView
   - Add missing trailing newlines to 7 files
   - Add jest __mocks__/vscode.js for CliService test
2026-06-25 22:30:52 +08:00
kite
d939b327cf docs: rewrite LLM config section to use provider-based setup
Replace the legacy manual `llm.*` configuration with the modern provider
system across all README localizations (en, zh-CN, ja-JP, ko-KR, ru-RU).
The new structure introduces interactive setup for humans and CLI-based
`ocr config set` commands for CI/CD, covering both built-in and custom
providers.
2026-06-25 21:32:58 +08:00
xyJen
52da795902
fix(vscode): upgrade minimatch to >=9.0.7 for CVE-2026-27903 (#220)
Add yarn resolution for minimatch and refresh yarn.lock to resolve
Dependabot alert #11 (ReDoS in minimatch <9.0.7).
2026-06-25 21:04:48 +08:00
kite
034d512b15
fix: increase REVIEW_FILTER_TASK and RE_LOCATION_TASK timeout from 60s to 180s (#208) (#218)
Slow local models often cannot complete these sub-tasks within the
hardcoded 60-second limit, causing timeouts that the user-provided
--timeout flag cannot override. Raise both to 180s in task_template.json
and scan_template.json to give local models sufficient time.
2026-06-25 20:07:07 +08:00
Ayrton
344f981156
fix: ensure current file path is always injected for code_comment and… (#193)
* fix: ensure current file path is always injected for code_comment and improve line number tracking in resolver

* test: Cover blank-line matching in resolveFromFileContent fallback
Add a regression test for snippets that omit blank lines while the
source file retains them, and document that consecutive matching skips
blank lines on both sides.

* test: Add tests for resolving line numbers with blank lines and CRLF
2026-06-25 16:29:09 +08:00
kite
63b0f02d27
feat: add tool_calls field to JSON output (#216)
* feat: add tool_calls field to JSON output for tool usage statistics

Track per-tool invocation counts in llmloop.Runner and expose them
through the ResultProvider interface so both review and scan modes
report tool call statistics in --format json output.

* fix: correct tool_calls counting and ensure stable JSON schema

Move recordToolCall after lookupTool nil check so only actually-executed
tool calls are counted. Always emit tool_calls field in JSON output for
a consistent schema, initializing by_tool to empty map when nil.

* fix: remove omitempty from tool_calls to ensure stable JSON schema

Drop omitempty from the tool_calls struct tag and initialize ToolCalls
in outputJSONNoFiles so the field is always present in JSON output
regardless of execution path.
2026-06-25 13:53:06 +08:00
xyJen
b6da4e214f
feat(vscode): add full-width BYOK provider config panel (#204)
Some checks are pending
CI / test (push) Waiting to run
* feat(vscode): add full-width BYOK provider config panel

Align VS Code extension provider setup with ocr config provider CLI:
editor panel for official/custom providers, custom provider manager,
in-memory connection test via isolated temp config, active provider
status bar, and OCR CLI version display. Add OCR_CONFIG_PATH support
for draft config testing in the CLI.

* fix(vscode): address PR #204 review comments (batch 1)

* fix(vscode): polish PR #204 review follow-ups

Add readonly ENV_CACHE_TTL_MS, responsive custom-provider URL width,
remove config-panel-only messages from HostToWebview, fix App spacing.

---------

Co-authored-by: xyJen <24266963+xyJen@users.noreply.github.com>
2026-06-25 10:37:25 +08:00
kite
ce11f374fd docs: sync ocr scan documentation to localized READMEs
Some checks are pending
CI / test (push) Waiting to run
Commit 18797f8 added the ocr scan feature but only updated the English
README. This syncs all six categories of changes (intro paragraph, quick
start examples, commands table, --exclude flag, ocr scan flags section,
and scan usage examples) to zh-CN, ja-JP, ko-KR, and ru-RU.
2026-06-24 22:18:28 +08:00
css521
18797f8c05
feat: add ocr scan for full-file code review (#93)
* feat: add ocr scan for full-file code review

Introduce a new top-level subcommand `ocr scan` (alias `s`) that reviews
whole files instead of git diffs. Use cases include reviewing unfamiliar
codebases, pre-migration audits, and ad-hoc per-directory reviews.

Architecture splits scan and diff review at the package level so the two
pipelines can evolve independently:

- internal/scan/      new package: file enumeration via `git ls-files`,
                      full-scan agent, FULL_SCAN_TASK rendering, preview
- internal/llmloop/   new package: shared LLM tool-use loop, three-zone
                      memory compression, CommentWorkerPool, AgentWarning.
                      Both internal/agent and internal/scan delegate to
                      llmloop.Runner; agent and scan never import each other
- internal/agent/     slimmed: LLM loop / compression / token aggregation
                      moved to llmloop; review-only orchestration remains
- internal/model/     new ScanItem (full-file payload) + Preview /
                      PreviewEntry / ExcludeReason shared by both modes
- internal/diff/      new gitignore.go exporting helpers reused by scan
- cmd/opencodereview/ new scan_cmd.go; shared.go consolidates startup
                      (loadCommonContext / loadLLMRuntime), output
                      (emitRunResult, ResultProvider) and stdout silencing
                      (quietHandle); review_cmd.go follows the same shape

Template additions:
- FULL_SCAN_TASK: dedicated prompt with Tool-call discipline guidance to
  reduce gratuitous tool calls per file
- FULL_SCAN_MAX_TOOL_REQUEST_TIMES (default 60): scan-only per-file budget,
  raised over diff's 30 to fit multi-finding files; --max-tools still
  composes (only raise, never lower)

In scan mode, file_read_diff is filtered out of MainToolDefs since it has
no useful semantics without a diff.

Tests cover provider enumeration (with temp git repo), template rendering,
filter passes, dependency budget, flag validation, and excludeToolDef.

* feat(scan): v2 — exclude / non-git / split template / plan / batch / dedup / project-summary

Address design-review feedback by evolving `ocr scan` along seven axes
while keeping `ocr review` behavior unchanged:

1. File size cap is now configurable (ScanTemplate.MaxFileSizeBytes,
   default 2 MiB; previously a hard-coded 5 MiB). The cap exists only to
   bound memory reading; the real review-feasibility gate is the per-file
   token budget downstream.

2. Drop the `--all` flag. Bare `ocr scan` now scans the whole repo;
   `--path` narrows. Less ceremony, fewer redundant flags.

3. New `--exclude` flag on both review and scan. Comma-separated
   gitignore-style patterns; merged with rule.json's exclude layer via
   the new shared.applyCLIExcludes helper.

4. Scan supports non-git directories. internal/scan.Provider chooses
   between `git ls-files` (full .gitignore semantics) and a
   filepath.WalkDir fallback (root .gitignore + ExcludedDirs blocklist)
   per isGitRepo probe. loadCommonContext takes a requireGit bool; review
   keeps the hard requirement, scan relaxes it.

5. Scan configuration lives in its own file. internal/config/template:
   - new ScanTemplate type with LoadScanDefault/ApplyLanguage/Validate
   - new embedded scan_template.json
   - Template loses the FULL_SCAN_* fields (review template unaffected)
   scan.Agent.Args.Template now holds a ScanTemplate; toLoopTemplate
   adapts it for llmloop.Runner.

6. New scan phases — each nil-able in the template and toggleable via a
   CLI flag, so users can revert to v1 behavior trivially:

   * PLAN_TASK (--no-plan): per-file pre-pass that outputs a JSON
     summary + checkpoints, embedded into MAIN_TASK as {{plan_guidance}}.
     formatPlanGuidance renders to markdown; malformed JSON falls back
     to raw text. PLAN_TASK failure never blocks the main loop.

   * BATCH_STRATEGY (--batch): files are grouped before dispatch.
     "none" preserves v1, "by-language" (default) groups by extension,
     "by-directory" groups by first-level subdir. BatchSize caps natural
     groups so a single language with 500 files doesn't form one giant
     batch. Batches are processed sequentially; files within a batch
     remain concurrent up to MaxConcurrency.

   * DEDUP_TASK (--no-dedup): per-batch postprocess that asks the LLM
     to cluster near-duplicate comments. Output is a `groups` JSON;
     every input id must appear exactly once or the result is rejected
     and originals are kept (safety: never silently lose comments).
     CommentCollector grows Snapshot/Since/ReplaceSince for this.

   * PROJECT_SUMMARY_TASK (--no-summary): once-per-run cross-file
     summary appended to text output and surfaced as `project_summary`
     in JSON output. ResultProvider grows ProjectSummary(); agent.Agent
     returns "" (review mode has no project summary).

   All four new LLM steps record token usage via runner.RecordUsage so
   aggregate counters stay accurate.

7. Tests cover the new pure code paths:
   - batch_test.go: 3 strategies, BatchSize cap, language-key edge cases
   - dedup_test.go: groups parser, malformed shapes, fence stripping,
     payload field selection
   - agent_test.go: formatPlanGuidance variants, buildSummaryCommentsList
     truncation, maybeRunPlan skip paths
   - provider_test.go: non-git directory walker fallback
   - template_test.go: ScanTemplate loads / ApplyLanguage / review
     template no longer contains scan fields

The seven phases can be reverted independently by toggling flags or
clearing the corresponding optional template fields; nothing forces the
new behavior on existing review users.

* fix(scan): three real bugs surfaced by SCAN_PLAN_TASK self-review

A v2 end-to-end test (ocr scan --path internal/scan/preview.go) had the
PLAN_TASK phase flag three concrete bugs in the scan package itself.
This commit fixes them and adds regression tests.

1. Preview() mutated a.items as a side-effect.
   Both Preview and Run wrote to a.items. Calling Preview before Run
   silently primed Run with the preview's enumeration instead of
   triggering a fresh listFiles. Preview is documented as a read-only
   dry-run; uphold that. Local variable now; a.items stays nil after
   Preview returns.

2. Preview.result.Entries was nil when there were no items.
   With no items at all the loop never ran, so Entries remained nil and
   JSON marshalling produced "files":null. Pre-allocate to a non-nil
   empty slice so the JSON contract stays "files":[] regardless.

3. Provider.Enumerate and listFilesViaWalk never checked ctx.Done().
   On a large repo a cancelled context would still complete the full
   walk before the caller saw an error (every iteration costs a stat or
   ReadFile syscall). Add the check at the top of each iteration in
   both the git-ls-files path and the walker fallback path; the walker
   returns ctx.Err() so filepath.WalkDir propagates the cancellation.

Three new regression tests pin the contracts:
- TestPreview_DoesNotMutateAgentItems
- TestPreview_EmptyResultEntriesIsNonNilSlice
- TestProvider_Enumerate_RespectsContextCancellation

* feat(scan): cost estimate + token budget cap; fix file_find on non-git dirs

Two cost-control features and one robustness fix, all surfaced by running
the scanner against a real ~870K-token repository.

Cost estimate (internal/scan/estimate.go):
- Before dispatch, Run prints an order-of-magnitude projection of token
  usage (input/output/total), derived from per-file content size × an
  assumed round count, plus the optional plan/dedup/summary phases.
- Deliberately reports tokens only, not dollars — pricing varies per
  provider/model and a precise figure would mislead. Actual usage is still
  reported from the API after the run.

Token budget cap (--max-tokens-budget / ScanTemplate.MaxTokensBudget):
- Caps total token usage for one scan. The gate is checked per file inside
  dispatchBatch, right before acquiring a concurrency slot: if tokens
  already spent plus a look-ahead estimate of the next file would exceed
  the budget, that file and all remaining files are skipped and a
  token_budget_reached warning is recorded.
- An earlier batch-level gate was too coarse: with the default by-language
  batching, a Go-heavy repo puts most files in one batch, so the gate only
  fired between batches and overran the budget ~2.4×. The per-file gate
  bounds overrun to roughly one in-flight file per worker (~1.3× at
  concurrency=1 in testing).
- 0 = unlimited (unchanged default behavior).

Phase-gate helpers (planEnabled/dedupEnabled/summaryEnabled) consolidate
the "template defines it AND --no-* flag not set" checks so the cost
estimate and the dispatch path agree on which phases will actually run.

file_find non-git fallback (internal/tool/file_find.go):
- `git ls-files` exits 128 in a non-git directory, which spammed failures
  when scanning plain directories (scan already supports non-git repos via
  the provider's walker, but the file_find tool did not). Now falls back
  to filepath.WalkDir honoring the root .gitignore and the default
  excluded-dir blocklist when git fails and no specific ref is requested.

Tests:
- estimate_test.go: humanTokens formatting, per-file vs aggregate estimate
  consistency, phase scaling, phase-gate tri-state.
- budget_test.go: fake LLM client drives the gate deterministically —
  verifies dispatch stops before exceeding budget and that 0 = unlimited.
- file_find_test.go: non-git directory fallback finds files, honors
  .gitignore / blocklist, and returns the not-found sentinel correctly.

* docs(readme): document ocr scan subcommand and flags

ocr scan existed but was undiscoverable from the README. Add it to the
intro blurb, Quick Start, the Commands table, Examples, and a dedicated
flags table (path / exclude / preview / max-tokens-budget / no-plan /
no-dedup / no-summary / batch / format / concurrency / rule / repo).
Note non-git support and the pre-run cost estimate. Also backfill the
--exclude flag in the ocr review flags table (added during the v1.3 merge
but never documented).

Flag names and defaults verified against `ocr scan -h`.

* fix(scan): code_search works in non-git directories via git grep --no-index

code_search relied on `git grep`, which exits 128 in a non-git directory —
so `ocr scan` on a plain directory (already supported by file enumeration and
file_find) silently returned errors instead of search results. Detect that
failure and retry with `git grep --no-index --exclude-standard`, which searches
the working tree directly while still honoring .gitignore. Reuses all existing
grep flag/parsing logic; ref-based search still requires a real repo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(scan): preserve context on compression failure; fix NUL parsing in gitLs

Address three real bugs from the PR #93 automated review that regressed when
compression moved into internal/llmloop:

- Sync compression failure / empty summary now return the original messages
  instead of truncating to the frozen zone, which discarded the whole
  per-file conversation context.
- Async compression now abandons the job on error instead of applying a
  truncated snapshot, and re-applies messages appended while it ran
  (snapshotLen), so concurrent tool results are no longer lost.
- scan Provider.gitLs uses cmd.Output() instead of CombinedOutput() so
  stderr can't corrupt the NUL-delimited (-z) filename parsing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-24 22:07:25 +08:00
kite
4a2370f9cd fix: make option-like ref test locale-independent
Replace English git error message matching with a locale-agnostic
"Error:" prefix check to fix test failures on non-English systems.
2026-06-24 21:19:06 +08:00
wxwxwxw_orange
9d129e2c10
feat(llm): update provider model lists (#202)
* feat(llm): update provider model lists
Sync built-in model presets with latest vendor offerings.

* docs: update providers screenshot
Reflect the latest provider list in the config provider TUI.
2026-06-24 19:55:23 +08:00