Make agent identity catalog configurable
ober
4d8f2737f74f911663a548d6d7c059f37f22b631
--- a/GAPS.md +++ b/GAPS.md @@ -322,6 +322,11 @@ Acceptance criteria: Known AI tools are detected through hard-coded strings. +Status: implemented with a default identity catalog plus user-defined +`known_agents` config entries. Matching now uses token/phrase matching instead +of raw substring checks, with fixture coverage for provider-substring false +positives and custom identities. + Acceptance criteria: - Move known tool/provider identity patterns into config/data. --- a/main-binary.ss +++ b/main-binary.ss @@ -349,12 +349,20 @@ (count-where (lambda (line) (not (blank? line))) (bounded-added-lines-for-paths repo rev (numstat-paths (changed-files repo rev file)) file))) -(def known-agents - '("codex" "copilot" "claude" "cursor" "openai" "anthropic" "aider" "windsurf" "cody" "tabnine" "ai-agent")) - +(def default-known-agents + '("codex" "copilot" "github copilot" "claude" "cursor" "openai" "anthropic" "aider" "windsurf" "cody" "tabnine" "ai-agent")) +(def current-known-agents default-known-agents) +(def (set-known-agents! parts) + (if (list? parts) + (set! current-known-agents (unique (append default-known-agents (filter string? parts)))))) +(def (identity-token-hit? tokens marker) + (let ([parts (source-lexemes (list marker))]) + (and (pair? parts) + (every (lambda (part) (member part tokens)) parts)))) (def (metadata-hits author-name author-email subject body note) - (let ([text (down (string-join (list author-name author-email subject body note) "\n"))]) - (filter (lambda (marker) (contains? text marker)) known-agents))) + (let* ([text (down (string-join (list author-name author-email subject body note) "\n"))] + [tokens (source-lexemes (list text))]) + (filter (lambda (marker) (identity-token-hit? tokens marker)) current-known-agents))) (def (sig name category score weight confidence reason evidence limitations) (make-signal name category (clamp01 score) weight confidence reason evidence limitations)) @@ -1528,6 +1536,7 @@ (set! current-excludes (append (config-string-list obj "exclude" '()) current-excludes)) (set-local-provider-command! (config-string-list obj "local_provider_command" current-local-provider-command)) (set-local-embedding-provider-command! (config-string-list obj "local_embedding_provider_command" current-local-embedding-provider-command)) +(set-known-agents! (config-string-list obj "known_agents" current-known-agents)) (make-options (options-command opts) (config-string obj "path" (options-path opts)) (config-number obj "count" (options-count opts)) --- a/tests/fixture-smoke.sh +++ b/tests/fixture-smoke.sh @@ -10,7 +10,8 @@ timing_fixture=$(mktemp -d) normal_timing_fixture=$(mktemp -d) similarity_fixture=$(mktemp -d) baseline_fixture=$(mktemp -d) -trap 'rm -rf "$fixture" "$shallow" "$provider_tmp" "$shape_fixture" "$timing_fixture" "$normal_timing_fixture" "$similarity_fixture" "$baseline_fixture"' EXIT +identity_fixture=$(mktemp -d) +trap 'rm -rf "$fixture" "$shallow" "$provider_tmp" "$shape_fixture" "$timing_fixture" "$normal_timing_fixture" "$similarity_fixture" "$baseline_fixture" "$identity_fixture"' EXIT git -C "$fixture" init -q git -C "$fixture" config user.name "Human Dev" @@ -86,6 +87,28 @@ if printf '%s\n' "$json" | grep -q 'vendor/library.py'; then exit 1 fi +git -C "$identity_fixture" init -q +git -C "$identity_fixture" config user.name "Human Decoder" +git -C "$identity_fixture" config user.email "decodex@example.test" +printf 'identity false positive guard\n' > "$identity_fixture/README.md" +git -C "$identity_fixture" add README.md +GIT_AUTHOR_DATE='2026-07-29T07:30:00-06:00' \ +GIT_COMMITTER_DATE='2026-07-29T07:30:00-06:00' \ + git -C "$identity_fixture" commit -q -m 'openair cursorial cleanup' +identity_json=$("$root/bin/jerboa-aigit" scan "$identity_fixture" --format json --count 1) +printf '%s\n' "$identity_json" | grep -q '"metadata_hits":\[\]' +git -C "$identity_fixture" config user.name "MyBot" +git -C "$identity_fixture" config user.email "mybot@example.test" +printf 'custom identity\n' >> "$identity_fixture/README.md" +git -C "$identity_fixture" add README.md +GIT_AUTHOR_DATE='2026-07-29T07:31:00-06:00' \ +GIT_COMMITTER_DATE='2026-07-29T07:31:00-06:00' \ + git -C "$identity_fixture" commit -q -m 'custom bot change' +identity_config="$identity_fixture/aigit.json" +printf '{"known_agents":["mybot"]}\n' > "$identity_config" +identity_custom_json=$("$root/bin/jerboa-aigit" scan "$identity_fixture" --config "$identity_config" --format json --count 1) +printf '%s\n' "$identity_custom_json" | grep -q '"metadata_hits":\["mybot"\]' + git -C "$shape_fixture" init -q git -C "$shape_fixture" config user.name "Human Dev" git -C "$shape_fixture" config user.email "human@example.test"