Files
weichenandCursor 33ee59641f feat(trace): add the project trace ledger and bounded impact walk
Keep item revisions and edge decisions as records, and refuse to treat a missing index as no impact.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 15:35:07 +00:00

75 lines
1.9 KiB
Go

package traceimpact
import (
"regexp"
"strings"
)
var (
explicitKeyRe = regexp.MustCompile(`\b((?:UR|RS|REQ|TC|RF|RP|DI)-\d+)\b`)
untypedKeyRe = regexp.MustCompile(`\b([A-Z]{2,10}-\d+)\b`)
)
// ExtractedKey is a business key found in markdown.
type ExtractedKey struct {
Key string
Kind string
Explicit bool
Line string
}
// ExtractKeys returns explicit UR/RS/REQ/TC-style keys and untyped ID mentions.
// Untyped mentions stay candidates and never become confirmed edges by themselves.
func ExtractKeys(markdown string) []ExtractedKey {
lines := strings.Split(markdown, "\n")
var out []ExtractedKey
seen := map[string]bool{}
for _, line := range lines {
for _, m := range explicitKeyRe.FindAllStringSubmatch(line, -1) {
key := m[1]
if seen["e:"+key] {
continue
}
seen["e:"+key] = true
kind := KindRequirement
if strings.HasPrefix(key, "TC-") {
kind = KindTest
}
out = append(out, ExtractedKey{Key: key, Kind: kind, Explicit: true, Line: line})
}
for _, m := range untypedKeyRe.FindAllStringSubmatch(line, -1) {
key := m[1]
if explicitKeyRe.MatchString(key) || seen["u:"+key] || seen["e:"+key] {
continue
}
seen["u:"+key] = true
out = append(out, ExtractedKey{Key: key, Kind: KindRequirement, Explicit: false, Line: line})
}
}
return out
}
// ExplicitPairsOnLine returns ordered pairs of explicit keys that share a line.
func ExplicitPairsOnLine(markdown string) [][2]string {
var pairs [][2]string
seen := map[string]bool{}
for _, line := range strings.Split(markdown, "\n") {
found := explicitKeyRe.FindAllStringSubmatch(line, -1)
if len(found) < 2 {
continue
}
for i := 0; i < len(found); i++ {
for j := i + 1; j < len(found); j++ {
a, b := found[i][1], found[j][1]
k := a + ">" + b
if seen[k] {
continue
}
seen[k] = true
pairs = append(pairs, [2]string{a, b})
}
}
}
return pairs
}