* chore: add SPDX license headers to all source files
Add Apache-2.0 SPDX license identifiers and copyright notices to all
tracked .go, .sh, .js, .mjs, .ts, and .tsx source files.
Introduce scripts/verify-license.sh and scripts/add-license.sh for
automated verification and bulk addition of license headers. Integrate
the check into CI (ci.yml) and the Makefile (license-check target as
a prerequisite of the existing check target).
This satisfies the OpenSSF Best Practices Badge requirements for
copyright_per_file and license_per_file.
* fix: restore execute permissions on scripts
* docs: add license header instructions to CONTRIBUTING guides
* docs: add license header instructions to pages contributing guides
* fix(pages): strip unclosed HTML comment markers to satisfy CodeQL
* fix: apply code review suggestions for license scripts
- Fix portability: detect macOS vs Linux stat for permission copy
- Fix has_header: check both SPDX and copyright (match verify logic)
- Fix is_ignored: match on path boundaries to avoid false positives
- Fix year extraction: use consistent pipeline across both scripts
- Fix Bash 3.2 compat: quote array length expansion for set -u
* fix(pages): use loop-until-clean for HTML comment stripping (CodeQL)
* fix(pages): use split/join instead of replace to avoid CodeQL false positive
CodeQL's js/incomplete-multi-character-sanitization rule flags any
.replace() that removes multi-character sequences like '<!--...-->',
regardless of context. The data here comes from readFileSync on the
project's own index.html (no untrusted input), making this a false
positive. Using split(regex).join('') achieves the same result without
triggering the taint-tracking rule.
The module path was github.com/open-code-review/open-code-review but the
repo lives at github.com/alibaba/open-code-review. This mismatch prevents
pkg.go.dev indexing and breaks Go Report Card resolution.
ParseDiffText classified lines with two unanchored heuristics:
- binaryRe ("Binary files ") matched anywhere in a file's diff section,
including hunk content, so a text file whose change merely mentions the
phrase (docs, comments, log strings) was marked binary and silently
excluded from review.
- Insertions/Deletions counted "+"/"-" lines while excluding anything
starting with "+++"/"---" to skip file headers — but that guard also
drops real content lines, e.g. an added line "++i" renders as "+++i".
Besides skewing the reported stats, the undercounted changeLines total
gates the plan phase in the review agent.
Track hunk state instead: a line belongs to a hunk only after the "@@"
header, and inside a hunk every content line carries a leading marker, so
"+"/"-" lines always count and the header strings can never appear.
Anchor binaryRe to column 0 (git always emits the marker there) and
restrict the "/dev/null" header markers to the pre-hunk region, where an
added line "++ /dev/null" cannot be misread as a deleted-file header.
When a file was renamed on the target branch, ocr review emitted
'[ocr] WARNING: cannot read file <old path> at ref <to>: exit status 128'.
Two compounding bugs:
1. The parser required 'a/'/'b/' prefixes when matching '--- /dev/null' /
'+++ /dev/null', but git emits these lines without prefixes, so
IsNew/IsDeleted were never set and deleted files fell through to a
doomed 'git show ref:<old path>'.
2. 'rename from' / 'rename to' extended headers were never parsed, and
git diff/show call sites did not force rename detection, so renames
degraded to delete+add whenever the user had diff.renames=false.
Fixes:
- Parse 'rename from'/'rename to', 'new file mode', 'deleted file mode'
and unprefixed /dev/null markers in ParseDiffText.
- Pass --find-renames to all git diff/show invocations so rename
detection no longer depends on user config.
- Add IsRenamed to model.Diff (json: is_renamed) and prefer it in
diffStatus.
- Add parser unit tests and a range-mode rename regression test.
Fixes#99
Introduce gitcmd.Runner with channel-based semaphore to cap concurrent
git subprocesses (default 16, configurable via --max-git-procs). Route
all tool-layer and diff-layer git calls through the shared runner.
Also fix diff.Provider.runGit lacking context.Context — now the full
chain (GetDiff → MergeBase → ParseDiffText → finalizeDiff) propagates
the caller's context for proper cancellation and timeout support.
file_find and finalizeDiff always read from the working tree, even in
range/commit mode where the review targets a specific git ref. This
caused inconsistent file versions compared to file_read and code_search
which correctly used git show. Fix file_find to use git ls-tree and
finalizeDiff to use git show when a ref is specified.