a73x

e1d774ff

feat(scanner): tagged marker reporting, size cap, binary sniff

a73x   2026-04-29 05:46

Commit message
feat(scanner): tagged marker reporting, size cap, binary sniff

internal/scanner/scanner.go
Old New
@@ -2,6 +2,7 @@ package scanner
2 2
3 import ( 3 import (
4 "bufio" 4 "bufio"
5 "bytes"
5 "os" 6 "os"
6 "path/filepath" 7 "path/filepath"
7 "regexp" 8 "regexp"
@@ -58,6 +59,32 @@ func Scan(path string) ([]Marker, error) {
58 return nil, nil 59 return nil, nil
59 } 60 }
60 61
62 const maxBytes = 1 << 20 // 1 MB
63
64 st, err := os.Stat(path)
65 if err != nil {
66 return nil, err
67 }
68 if st.Size() > maxBytes {
69 return nil, nil
70 }
71
72 // Binary sniff: read first 8 KB, look for null byte.
73 sniffN := int64(8192)
74 if st.Size() < sniffN {
75 sniffN = st.Size()
76 }
77 sniff := make([]byte, sniffN)
78 sf, err := os.Open(path)
79 if err != nil {
80 return nil, err
81 }
82 n, _ := sf.Read(sniff)
83 sf.Close()
84 if bytes.IndexByte(sniff[:n], 0) >= 0 {
85 return nil, nil
86 }
87
61 f, err := os.Open(path) 88 f, err := os.Open(path)
62 if err != nil { 89 if err != nil {
63 return nil, err 90 return nil, err
internal/scanner/scanner_test.go
Old New
@@ -3,6 +3,7 @@ package scanner
3 import ( 3 import (
4 "os" 4 "os"
5 "path/filepath" 5 "path/filepath"
6 "strings"
6 "testing" 7 "testing"
7 ) 8 )
8 9
@@ -109,3 +110,46 @@ func TestScanMakefileByName(t *testing.T) {
109 t.Fatalf("got %#v", markers) 110 t.Fatalf("got %#v", markers)
110 } 111 }
111 } 112 }
113
114 func TestScanTaggedMarkerNotFiredButReported(t *testing.T) {
115 dir := t.TempDir()
116 path := writeFile(t, dir, "foo.go", "// @claude[fw-a1b2c3d4] write a test\n")
117 markers, err := Scan(path)
118 if err != nil {
119 t.Fatal(err)
120 }
121 if len(markers) != 1 {
122 t.Fatalf("want 1 marker, got %d", len(markers))
123 }
124 if !markers[0].Tagged || markers[0].UUID != "fw-a1b2c3d4" {
125 t.Errorf("got %#v, want Tagged=true UUID=fw-a1b2c3d4", markers[0])
126 }
127 }
128
129 func TestScanLargeFileSkipped(t *testing.T) {
130 dir := t.TempDir()
131 big := strings.Repeat("// filler line\n", 80_000) // > 1 MB
132 path := writeFile(t, dir, "big.go", big+"// @claude do it\n")
133 markers, err := Scan(path)
134 if err != nil {
135 t.Fatal(err)
136 }
137 if markers != nil {
138 t.Fatalf("expected nil for oversized file, got %#v", markers)
139 }
140 }
141
142 func TestScanBinaryFileSkipped(t *testing.T) {
143 dir := t.TempDir()
144 path := filepath.Join(dir, "blob.go")
145 if err := os.WriteFile(path, []byte{0x00, 0x01, 0x02, '/', '/', ' ', '@', 'c', 'l', 'a', 'u', 'd', 'e', ' ', 'x'}, 0o644); err != nil {
146 t.Fatal(err)
147 }
148 markers, err := Scan(path)
149 if err != nil {
150 t.Fatal(err)
151 }
152 if markers != nil {
153 t.Fatalf("expected nil for binary file, got %#v", markers)
154 }
155 }