From 7be87c8c2234a958fca59b802facdba539c15837 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 14 Oct 2026 16:21:13 +0300 Subject: [PATCH 1/4] fix: no prompt nudge on auto-fix or once the skill already ran Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/.claude-plugin/plugin.json | 2 +- plugins/agentic-advisor/CHANGELOG.md | 6 ++++++ .../agentic-advisor/hooks/agentic-advisor-trigger.sh | 4 +++- tests/agentic-advisor/hooks_test.sh | 10 ++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/agentic-advisor/.claude-plugin/plugin.json b/plugins/agentic-advisor/.claude-plugin/plugin.json index 5fd4f04..8fe5de3 100644 --- a/plugins/agentic-advisor/.claude-plugin/plugin.json +++ b/plugins/agentic-advisor/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentic-advisor", - "version": "1.4.0", + "version": "1.4.1", "description": "Before writing code, grades how fragile the target is from LinearB health signals + local git history (rework, incidents, fix/revert density, code ownership) and holds the agent to a matching effort level (LOW/MEDIUM/HIGH) — lean on calm repos, defensive on fragile ones. Auto-triggers via a bundled hook and can report each effort decision to your LinearB org as usage telemetry.", "author": { "name": "LinearB", diff --git a/plugins/agentic-advisor/CHANGELOG.md b/plugins/agentic-advisor/CHANGELOG.md index d926200..142014f 100644 --- a/plugins/agentic-advisor/CHANGELOG.md +++ b/plugins/agentic-advisor/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.4.1] - 2026-10-14 + +### Fixed + +- No more false prompt nudges: "auto-fix" / "autofix" no longer counts as a code task, and once the skill has run in a session, later prompts aren't nudged again. + ## [1.4.0] - 2026-10-13 ### Added diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index c424221..bc10ebf 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -123,6 +123,8 @@ case "$event" in UserPromptSubmit) prompt="$(jq -r '.prompt // .user_input // empty' <<<"$input" 2>/dev/null || true)" [ -z "$prompt" ] && exit 0 + # Already graded this session -> a later prompt needs no nudge (the hold skips this case too). + skill_ran && { dbg "UserPromptSubmit: skip: skill already ran in this session"; exit 0; } # Decide whether this prompt looks like a code task, and build the nudge. msg="" @@ -133,7 +135,7 @@ case "$event" in if [ -n "$ticket" ]; then # Tier 1: Jira ticket (primary). msg="This looks like the start of a repo-scoped code task (Jira ticket ${ticket} referenced). ${guidance}" - elif printf '%s' "$prompt" | grep -qiE '\b(fix|fixes|fixing|fixed|implement|implementing|refactor|refactoring|hotfix|bug ?fix|debug|patch|endpoint|migration)\b'; then + elif printf '%s' "$prompt" | sed -E 's/[Aa][Uu][Tt][Oo]-?[Ff][Ii][Xx]//g' | grep -qiE '\b(fix|fixes|fixing|fixed|implement|implementing|refactor|refactoring|hotfix|bug ?fix|debug|patch|endpoint|migration)\b'; then # Tier 2: code-task keywords (fallback for ad-hoc work). msg="This looks like a code-writing task. ${guidance}" fi diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index 99f251c..5002219 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -74,6 +74,16 @@ teardown setup run "$TRIGGER" UserPromptSubmit "$(prompt 'what time is it?')" check "trigger: non-code prompt is silent" silent +run "$TRIGGER" UserPromptSubmit "$(prompt 'turn on Auto-fix for the PR')" +check "trigger: 'auto-fix' is not a code task" silent +run "$TRIGGER" UserPromptSubmit "$(prompt 'turn on autofix and fix the login bug')" +check "trigger: a real fix next to autofix still nudges" nudged +teardown + +setup +add_skill +run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" +check "trigger: no nudge once the skill ran this session" silent teardown for v in 0 false OFF no; do From 8149d15e63b4ff8f8407bc92a0e6b20dac514236 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 14 Oct 2026 16:29:26 +0300 Subject: [PATCH 2/4] fix: skip the nudge per repo, not per session; also ignore "auto fix" Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/CHANGELOG.md | 2 +- .../agentic-advisor/hooks/agentic-advisor-trigger.sh | 8 +++----- tests/agentic-advisor/hooks_test.sh | 10 ++++++++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/plugins/agentic-advisor/CHANGELOG.md b/plugins/agentic-advisor/CHANGELOG.md index 142014f..328dc71 100644 --- a/plugins/agentic-advisor/CHANGELOG.md +++ b/plugins/agentic-advisor/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed -- No more false prompt nudges: "auto-fix" / "autofix" no longer counts as a code task, and once the skill has run in a session, later prompts aren't nudged again. +- No more false prompt nudges: "auto-fix" / "auto fix" / "autofix" no longer counts as a code task, and a repo that was already worked on after the skill ran isn't nudged again (another repo in the same session still is). ## [1.4.0] - 2026-10-13 diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index bc10ebf..3f4024b 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -123,8 +123,6 @@ case "$event" in UserPromptSubmit) prompt="$(jq -r '.prompt // .user_input // empty' <<<"$input" 2>/dev/null || true)" [ -z "$prompt" ] && exit 0 - # Already graded this session -> a later prompt needs no nudge (the hold skips this case too). - skill_ran && { dbg "UserPromptSubmit: skip: skill already ran in this session"; exit 0; } # Decide whether this prompt looks like a code task, and build the nudge. msg="" @@ -135,7 +133,7 @@ case "$event" in if [ -n "$ticket" ]; then # Tier 1: Jira ticket (primary). msg="This looks like the start of a repo-scoped code task (Jira ticket ${ticket} referenced). ${guidance}" - elif printf '%s' "$prompt" | sed -E 's/[Aa][Uu][Tt][Oo]-?[Ff][Ii][Xx]//g' | grep -qiE '\b(fix|fixes|fixing|fixed|implement|implementing|refactor|refactoring|hotfix|bug ?fix|debug|patch|endpoint|migration)\b'; then + elif printf '%s' "$prompt" | sed -E 's/[Aa][Uu][Tt][Oo][- ]?[Ff][Ii][Xx]//g' | grep -qiE '\b(fix|fixes|fixing|fixed|implement|implementing|refactor|refactoring|hotfix|bug ?fix|debug|patch|endpoint|migration)\b'; then # Tier 2: code-task keywords (fallback for ad-hoc work). msg="This looks like a code-writing task. ${guidance}" fi @@ -198,8 +196,8 @@ case "$event" in # (missing file path, non-git, missing transcript, or marker write failure). git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0 - # Skill already ran this session -> allow the edit. - skill_ran && exit 0 + # Skill already ran this session -> allow the edit, and mark this repo handled so later prompts here aren't nudged. + if skill_ran; then set_marker "$dir"; : > "$marker" 2>/dev/null || true; exit 0; fi # Can't read the transcript -> can't confirm skill status -> fail open (allow). [ -n "$transcript" ] && [ -f "$transcript" ] || exit 0 diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index 5002219..d187c0f 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -76,14 +76,20 @@ run "$TRIGGER" UserPromptSubmit "$(prompt 'what time is it?')" check "trigger: non-code prompt is silent" silent run "$TRIGGER" UserPromptSubmit "$(prompt 'turn on Auto-fix for the PR')" check "trigger: 'auto-fix' is not a code task" silent +run "$TRIGGER" UserPromptSubmit "$(prompt 'turn on auto fix')" +check "trigger: 'auto fix' is not a code task" silent run "$TRIGGER" UserPromptSubmit "$(prompt 'turn on autofix and fix the login bug')" check "trigger: a real fix next to autofix still nudges" nudged teardown setup -add_skill +add_skill; add_verdict +run "$TRIGGER" PreToolUse "$(tool Edit app.js)" run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" -check "trigger: no nudge once the skill ran this session" silent +check "trigger: no nudge in a repo already worked on after the skill ran" silent +REPO2="$T/repo2"; git init -q "$REPO2" +out="$(printf '{"hook_event_name":"UserPromptSubmit","session_id":"s1","cwd":"%s","transcript_path":"%s","prompt":"fix the login bug"}' "$REPO2" "$TRANSCRIPT" | "$TRIGGER")"; rc=$? +check "trigger: a second repo still nudges after the skill ran" nudged teardown for v in 0 false OFF no; do From 163d3c43c2f6a9e2af18d382b0f4bfddb6f0fc81 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 14 Oct 2026 16:37:02 +0300 Subject: [PATCH 3/4] fix: mark a repo handled only when a verdict names it Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/CHANGELOG.md | 2 +- .../agentic-advisor/hooks/agentic-advisor-trigger.sh | 9 +++++++-- tests/agentic-advisor/hooks_test.sh | 10 +++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/plugins/agentic-advisor/CHANGELOG.md b/plugins/agentic-advisor/CHANGELOG.md index 328dc71..7e4726c 100644 --- a/plugins/agentic-advisor/CHANGELOG.md +++ b/plugins/agentic-advisor/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed -- No more false prompt nudges: "auto-fix" / "auto fix" / "autofix" no longer counts as a code task, and a repo that was already worked on after the skill ran isn't nudged again (another repo in the same session still is). +- No more false prompt nudges: "auto-fix" / "auto fix" / "autofix" no longer counts as a code task, and a repo that was already graded and worked on isn't nudged again (another repo in the same session still is). ## [1.4.0] - 2026-10-13 diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index 3f4024b..72b8bb4 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -196,8 +196,13 @@ case "$event" in # (missing file path, non-git, missing transcript, or marker write failure). git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0 - # Skill already ran this session -> allow the edit, and mark this repo handled so later prompts here aren't nudged. - if skill_ran; then set_marker "$dir"; : > "$marker" 2>/dev/null || true; exit 0; fi + # Skill already ran this session -> allow the edit. If a verdict names this repo, mark it handled so later prompts here aren't nudged. + if skill_ran; then + set_marker "$dir" + name="$(basename "$(git -C "$dir" rev-parse --show-toplevel 2>/dev/null)")" + grep -qF "LinearB: $name " "$transcript" 2>/dev/null && { : > "$marker" 2>/dev/null || true; } + exit 0 + fi # Can't read the transcript -> can't confirm skill status -> fail open (allow). [ -n "$transcript" ] && [ -f "$transcript" ] || exit 0 diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index d187c0f..e712fe8 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -53,6 +53,7 @@ reminded() { [ "$rc" -eq 0 ] && jq -e '(.hookSpecificOutput.permissionDecision = denied() { [ "$rc" -eq 0 ] && jq -e '.hookSpecificOutput.permissionDecision == "deny"' <<<"$out" >/dev/null; } add_skill() { printf '%s\n' '{"timestamp":"2026-01-01T00:00:00Z","message":{"role":"assistant","model":"m","usage":{"output_tokens":10},"content":[{"type":"tool_use","name":"Skill","input":{"skill":"agentic-advisor:agentic-advisor"}}]}}' >> "$TRANSCRIPT"; } add_verdict() { printf '%s\n' '{"timestamp":"2026-01-01T00:00:05Z","message":{"role":"assistant","model":"m","usage":{"output_tokens":20},"content":[{"type":"text","text":"> LinearB: widgets — MEDIUM effort (rework 6.5%) — focused diff."}]}}' >> "$TRANSCRIPT"; } +add_verdict_for() { printf '{"message":{"role":"assistant","content":[{"type":"text","text":"> LinearB: %s — MEDIUM effort (x) — y."}]}}\n' "$1" >> "$TRANSCRIPT"; } # Reporter posts from a detached subshell; wait briefly for the stub to record calls. ncalls() { find "$T/curl" -type f | wc -l | tr -d ' '; } await_calls() { local _; for _ in 1 2 3 4 5 6 7 8 9 10; do [ "$(ncalls)" -ge "$1" ] && return; sleep 0.2; done; } @@ -86,7 +87,14 @@ setup add_skill; add_verdict run "$TRIGGER" PreToolUse "$(tool Edit app.js)" run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" -check "trigger: no nudge in a repo already worked on after the skill ran" silent +check "trigger: an edit in a repo the verdict didn't name doesn't mark it handled" nudged +teardown + +setup +add_skill; add_verdict_for repo +run "$TRIGGER" PreToolUse "$(tool Edit app.js)" +run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" +check "trigger: no nudge in a repo already graded and worked on" silent REPO2="$T/repo2"; git init -q "$REPO2" out="$(printf '{"hook_event_name":"UserPromptSubmit","session_id":"s1","cwd":"%s","transcript_path":"%s","prompt":"fix the login bug"}' "$REPO2" "$TRANSCRIPT" | "$TRIGGER")"; rc=$? check "trigger: a second repo still nudges after the skill ran" nudged From e7e3d7852918fe30061e29e092f4b15df144a413 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 14 Oct 2026 16:43:56 +0300 Subject: [PATCH 4/4] fix: match the verdict against the remote repo name too Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh | 7 +++++-- tests/agentic-advisor/hooks_test.sh | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index 72b8bb4..2b2197a 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -199,8 +199,11 @@ case "$event" in # Skill already ran this session -> allow the edit. If a verdict names this repo, mark it handled so later prompts here aren't nudged. if skill_ran; then set_marker "$dir" - name="$(basename "$(git -C "$dir" rev-parse --show-toplevel 2>/dev/null)")" - grep -qF "LinearB: $name " "$transcript" 2>/dev/null && { : > "$marker" 2>/dev/null || true; } + # The verdict uses the repo's name: check the remote's name and the folder's (clones and worktrees can differ). + url="$(git -C "$dir" config --get remote.origin.url 2>/dev/null)"; url="${url%.git}" + for name in "${url##*[/:]}" "$(basename "$(git -C "$dir" rev-parse --show-toplevel 2>/dev/null)")"; do + [ -n "$name" ] && grep -qF "LinearB: $name " "$transcript" 2>/dev/null && { : > "$marker" 2>/dev/null || true; break; } + done exit 0 fi # Can't read the transcript -> can't confirm skill status -> fail open (allow). diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index e712fe8..ccf61de 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -84,12 +84,19 @@ check "trigger: a real fix next to autofix still nudges" nudged teardown setup -add_skill; add_verdict +add_skill; add_verdict_for other-repo run "$TRIGGER" PreToolUse "$(tool Edit app.js)" run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" check "trigger: an edit in a repo the verdict didn't name doesn't mark it handled" nudged teardown +setup +add_skill; add_verdict_for widgets +run "$TRIGGER" PreToolUse "$(tool Edit app.js)" +run "$TRIGGER" UserPromptSubmit "$(prompt 'fix the login bug')" +check "trigger: a verdict naming the remote repo (folder named differently) marks it handled" silent +teardown + setup add_skill; add_verdict_for repo run "$TRIGGER" PreToolUse "$(tool Edit app.js)"