From 58f8a9e5122f1b9be887393a462a3f49ebe04bd5 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 21 Oct 2026 11:43:08 +0300 Subject: [PATCH 1/4] LINBEE-30104 | fix: don't grade tasks that change no code (v1.4.6) Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/.claude-plugin/plugin.json | 2 +- plugins/agentic-advisor/CHANGELOG.md | 7 +++++++ plugins/agentic-advisor/README.md | 2 +- .../hooks/agentic-advisor-trigger.sh | 6 +++--- .../skills/agentic-advisor/SKILL.md | 6 +++++- tests/agentic-advisor/hooks_test.sh | 14 ++++++++++++++ 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/plugins/agentic-advisor/.claude-plugin/plugin.json b/plugins/agentic-advisor/.claude-plugin/plugin.json index a0d9b6e..b3e0d77 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.5", + "version": "1.4.6", "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 7a7272b..36d397f 100644 --- a/plugins/agentic-advisor/CHANGELOG.md +++ b/plugins/agentic-advisor/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.4.6] - 2026-10-21 + +### Changed + +- A task that changes no code (reading, answering a question, reviewing a doc or screenshot, writing a comment) is no longer graded LOW: the skill prints `> LinearB: — skipped (not a code task)`, makes no calls, reports nothing, and the agent works with its normal care. LOW stays for trivial code edits (comments, formatting, renames). +- The skill states that the effort level governs code changes only and never lowers the care of reading, analysis or writing. + ## [1.4.5] - 2026-10-18 ### Changed diff --git a/plugins/agentic-advisor/README.md b/plugins/agentic-advisor/README.md index 344c5ae..f210092 100644 --- a/plugins/agentic-advisor/README.md +++ b/plugins/agentic-advisor/README.md @@ -30,7 +30,7 @@ The agent prints a one-line verdict before writing code, e.g.: - **Effort bands** match LinearB's own rework benchmark: ELITE <3% / STRONG 3–6% → **LOW**; FAIR 6–7% → **MEDIUM**; NEEDS FOCUS >7% → **HIGH**. Effort = the highest-firing signal (rework, unreviewed merges, or a recent serious incident). - **Task complexity:** the request itself is graded too (scope, breadth, tricky logic, blast radius), so a demanding change in a calm repo still gets real care. If the prompt or branch names a ticket, its type, priority and estimate from LinearB count too (a Highest-priority bug raises the grade). The final effort is the highest of repo health, task complexity and (when it runs) phase 2. - **Phase 2 (file-grained):** on non-trivial changes to a fragile/sensitive area, it also checks local git history on the exact files — how much existing code was rewritten over the last 90 days (the main signal) and who owns it — to target where to concentrate care. Commit messages saying "fix"/"revert" count only as a weak hint. -- **Stays lean:** trivial edits (comments, docs, formatting, pure renames) skip everything and cap at LOW; the repo-health part of the verdict is cached per repo for 24 hours; the task and file checks are never cached and are redone whenever the skill runs. +- **Stays lean:** a task that changes no code (questions, reviews, writing a comment) is not graded at all; trivial code edits (comments, formatting, pure renames) skip everything and cap at LOW; the repo-health part of the verdict is cached per repo for 24 hours; the task and file checks are never cached and are redone whenever the skill runs. ## Triggers diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index 2b2197a..6493697 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -53,7 +53,7 @@ skill_ran() { # Is the LATEST advisor Skill call still missing its verdict (assistant text, or the # hold's `printf` Bash call)? Prints "pending" or "ok"; prints nothing on parse failure. verdict_state() { - jq -rs --arg n "agentic-advisor" --arg re 'LinearB: .+ (LOW|MEDIUM|HIGH) effort' ' + jq -rs --arg n "agentic-advisor" --arg re 'LinearB: .+ ((LOW|MEDIUM|HIGH) effort|skipped \(not a code task\))' ' [.[] | select(.message.role? == "assistant") | .message.content? // [] | .[]?] as $c | [$c | to_entries[] | select(.value.type? == "tool_use" and .value.name? == "Skill" and ((.value.input.skill? // "") | tostring | contains($n))) | .key] as $sk @@ -94,7 +94,7 @@ set_marker() { # $1 = a directory inside the repo } # Imperative, silent guidance — no permission question, no announcement. -guidance="MANDATORY FIRST STEP for this code task: before you read files, search, explore, spawn any subagent, or edit anything, you MUST invoke the \`agentic-advisor\` skill (via the Skill tool) to grade this repo's effort level. Do not start the task, do not touch code, until you have run it and printed its verdict line verbatim in this shape: > LinearB: — effort () — (a hook parses that line; a prose summary is not recorded). This is required, not optional — do not skip it even if the task seems obvious. Invoke it directly (no need to ask the user or announce it). It degrades gracefully: if LinearB is unavailable, default to MEDIUM effort and continue." +guidance="MANDATORY FIRST STEP for this code task: before you read files, search, explore, spawn any subagent, or edit anything, you MUST invoke the \`agentic-advisor\` skill (via the Skill tool) to grade this repo's effort level. Do not start the task, do not touch code, until you have run it and printed its verdict line verbatim in this shape: > LinearB: — effort () — (a hook parses that line; a prose summary is not recorded). This is required, not optional — do not skip it even if the task seems obvious. Invoke it directly (no need to ask the user or announce it). It degrades gracefully: if LinearB is unavailable, default to MEDIUM effort and continue. If the task will not change any code, print > LinearB: — skipped (not a code task) instead of a grade." # Mark handled (this session+repo) and emit additionalContext for the event. emit() { # $1 = hookEventName, $2 = context text @@ -158,7 +158,7 @@ case "$event" in state="$(verdict_state)" if [ -n "$state" ] && : > "$vdone" 2>/dev/null && [ "$state" = "pending" ]; then dbg "PreToolUse: reminded the agent to print the verdict line" - note "LinearB: your effort grade isn't recorded yet. It's only recorded from the verdict line, not from thinking, so print it now: > LinearB: — effort () — . If you aren't writing text, run: printf '%s\\n' '> LinearB: — effort () — '" + note "LinearB: your effort grade isn't recorded yet. It's only recorded from the verdict line, not from thinking, so print it now: > LinearB: — effort () — . If you aren't writing text, run: printf '%s\\n' '> LinearB: — effort () — '. If no code will change, print > LinearB: — skipped (not a code task) instead." fi fi fi diff --git a/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md b/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md index 0fee01d..0d0b9ba 100644 --- a/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md +++ b/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md @@ -22,6 +22,7 @@ Right after the repo sweep, your first assistant text **must be this verdict lin - **A hook parses this exact line** to record the decision. Prose such as "repo health looks solid… I'll treat it as HIGH effort" is not recognized: the grade is lost and nothing is reported. - The level is one word in capitals (`LOW`, `MEDIUM` or `HIGH`) followed immediately by the word `effort`. - Explanation may follow on later lines, but the verdict line comes first and is never reworded. +- **No code will change?** Print `> LinearB: — skipped (not a code task)` instead of a grade and stop (see the cheap exits). Nothing is reported. - If you aren't writing visible text at this point, record it with one Bash call instead: `printf '%s\n' '> LinearB: — effort () — '`. If neither exists, a hook reminds you on your next file read or edit. Example: `> LinearB: api-service — HIGH effort (rework 3.4%, calm repo — but auth refactor with wide blast radius) — small behavior-preserving steps, tests green, confirm scope first.` @@ -44,7 +45,8 @@ set -o pipefail # with curl -f, a failed request fails the whole pipeline inst Two checks that prevent wasted work — do them before any LinearB call: -- **Trivial edit → skip everything.** If the task changes **no code behavior** (comments, docs, formatting/whitespace, a pure rename), skip signal gathering entirely: effort is **LOW**, add no defensive guards (there's no logic to protect), and don't call LinearB at all — this holds **even on a fragile repo**. Anything that changes behavior is **not** trivial and warrants the sweep below — note that a **constant-value change counts as behavioral** (e.g. a timeout, retry count, or feature-flag default), as does any conditional or logic edit. +- **Not a code task → no grade at all.** If the task will not change any code (reading or explaining code, answering a question, reviewing a doc, ticket or screenshot, writing a comment or message), don't grade it: print `> LinearB: — skipped (not a code task)`, call nothing, and work with your normal care. A grade measures the risk of a code change; a LOW here would wrongly tell you to go light on accuracy. If the task later turns into a code change, run the sweep then, before the first edit. +- **Trivial code edit → LOW, skip everything.** If the task edits code but changes **no code behavior** (comments, docs, formatting/whitespace, a pure rename), skip signal gathering entirely: effort is **LOW**, add no defensive guards (there's no logic to protect), and don't call LinearB at all — this holds **even on a fragile repo**. Anything that changes behavior is **not** trivial and warrants the sweep below — note that a **constant-value change counts as behavioral** (e.g. a timeout, retry count, or feature-flag default), as does any conditional or logic edit. - **Already graded recently → reuse (persistent 24h cache).** The repo-level verdict is daily-stable, so compute it at most **once per repo per ~24h**, not once per task/session — this is the main token/time saver. Cache file, keyed by repo root: ```text @@ -260,6 +262,8 @@ Phase 2 was only ever deferred because it needs the target file paths. So: ## Coding Posture +The effort level governs **code changes only**: it never lowers the care, accuracy or thoroughness of reading, analysis, answers or writing. + Use the effort level to guide the implementation silently. The aim is to **spend effort proportional to repo health** — go light (saving tokens and time) on calm repos, dig in on fragile ones. Don't waste effort. LOW effort — repo confirmed healthy, go light and token-efficient (an active repo can still be LOW — busy ≠ risky): diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index ccf61de..3a0071a 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_skipped() { printf '%s\n' '{"message":{"role":"assistant","content":[{"type":"text","text":"> LinearB: widgets — skipped (not a code task)"}]}}' >> "$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 ' '; } @@ -171,6 +172,12 @@ run "$TRIGGER" PreToolUse "$(tool Read app.js)" check "trigger: skill ran without verdict -> reminder, not a block" reminded teardown +setup +add_skill; add_skipped +run "$TRIGGER" PreToolUse "$(tool Read app.js)" +check "trigger: a skipped (not a code task) line counts as answered -> no reminder" silent +teardown + setup add_skill; add_verdict run "$TRIGGER" PreToolUse "$(tool Edit app.js)" @@ -195,6 +202,13 @@ await_calls 2 # decision + tokens, posted concurrently check "report: SessionEnd backfills a missed DECISION" backfilled teardown +setup +add_skill; add_skipped +run "$REPORT" SessionEnd +sleep 0.5 # a wrong post would arrive from a detached subshell +check "report: a skipped (not a code task) session reports nothing" no_calls +teardown + # Both exit before any background post, so no wait is needed. setup add_skill; add_verdict From ed815e92519f3a664ba44dda5908697bac110821 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 21 Oct 2026 11:50:26 +0300 Subject: [PATCH 2/4] fix: address gitstream/Copilot review (round 1) Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/CHANGELOG.md | 1 + plugins/agentic-advisor/README.md | 2 +- plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh | 5 +++-- plugins/agentic-advisor/skills/agentic-advisor/SKILL.md | 4 ++-- tests/agentic-advisor/hooks_test.sh | 9 +++++++++ 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/plugins/agentic-advisor/CHANGELOG.md b/plugins/agentic-advisor/CHANGELOG.md index 36d397f..687bcec 100644 --- a/plugins/agentic-advisor/CHANGELOG.md +++ b/plugins/agentic-advisor/CHANGELOG.md @@ -6,6 +6,7 @@ - A task that changes no code (reading, answering a question, reviewing a doc or screenshot, writing a comment) is no longer graded LOW: the skill prints `> LinearB: — skipped (not a code task)`, makes no calls, reports nothing, and the agent works with its normal care. LOW stays for trivial code edits (comments, formatting, renames). - The skill states that the effort level governs code changes only and never lowers the care of reading, analysis or writing. +- "Skipped" means the task modifies no file; any file edit with no behavior change (code comments, doc files, formatting) is still LOW. The edit hold now waits for a real grade, so code work that follows a skipped run is graded first. ## [1.4.5] - 2026-10-18 diff --git a/plugins/agentic-advisor/README.md b/plugins/agentic-advisor/README.md index f210092..9ae32ac 100644 --- a/plugins/agentic-advisor/README.md +++ b/plugins/agentic-advisor/README.md @@ -30,7 +30,7 @@ The agent prints a one-line verdict before writing code, e.g.: - **Effort bands** match LinearB's own rework benchmark: ELITE <3% / STRONG 3–6% → **LOW**; FAIR 6–7% → **MEDIUM**; NEEDS FOCUS >7% → **HIGH**. Effort = the highest-firing signal (rework, unreviewed merges, or a recent serious incident). - **Task complexity:** the request itself is graded too (scope, breadth, tricky logic, blast radius), so a demanding change in a calm repo still gets real care. If the prompt or branch names a ticket, its type, priority and estimate from LinearB count too (a Highest-priority bug raises the grade). The final effort is the highest of repo health, task complexity and (when it runs) phase 2. - **Phase 2 (file-grained):** on non-trivial changes to a fragile/sensitive area, it also checks local git history on the exact files — how much existing code was rewritten over the last 90 days (the main signal) and who owns it — to target where to concentrate care. Commit messages saying "fix"/"revert" count only as a weak hint. -- **Stays lean:** a task that changes no code (questions, reviews, writing a comment) is not graded at all; trivial code edits (comments, formatting, pure renames) skip everything and cap at LOW; the repo-health part of the verdict is cached per repo for 24 hours; the task and file checks are never cached and are redone whenever the skill runs. +- **Stays lean:** a task that modifies no file (questions, reviews, drafting a reply) is not graded at all; edits with no behavior change (code comments, doc files, formatting, pure renames) skip everything and cap at LOW; the repo-health part of the verdict is cached per repo for 24 hours; the task and file checks are never cached and are redone whenever the skill runs. ## Triggers diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index 6493697..012cb53 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -196,8 +196,9 @@ 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. If a verdict names this repo, mark it handled so later prompts here aren't nudged. - if skill_ran; then + # Skill already graded this session -> allow the edit. A "skipped (not a code task)" line alone doesn't count: editing now is code work. + # If a verdict names this repo, mark it handled so later prompts here aren't nudged. + if skill_ran && grep -qE 'LinearB: .+ (LOW|MEDIUM|HIGH) effort' "$transcript" 2>/dev/null; then set_marker "$dir" # 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}" diff --git a/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md b/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md index 0d0b9ba..69c4807 100644 --- a/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md +++ b/plugins/agentic-advisor/skills/agentic-advisor/SKILL.md @@ -45,8 +45,8 @@ set -o pipefail # with curl -f, a failed request fails the whole pipeline inst Two checks that prevent wasted work — do them before any LinearB call: -- **Not a code task → no grade at all.** If the task will not change any code (reading or explaining code, answering a question, reviewing a doc, ticket or screenshot, writing a comment or message), don't grade it: print `> LinearB: — skipped (not a code task)`, call nothing, and work with your normal care. A grade measures the risk of a code change; a LOW here would wrongly tell you to go light on accuracy. If the task later turns into a code change, run the sweep then, before the first edit. -- **Trivial code edit → LOW, skip everything.** If the task edits code but changes **no code behavior** (comments, docs, formatting/whitespace, a pure rename), skip signal gathering entirely: effort is **LOW**, add no defensive guards (there's no logic to protect), and don't call LinearB at all — this holds **even on a fragile repo**. Anything that changes behavior is **not** trivial and warrants the sweep below — note that a **constant-value change counts as behavioral** (e.g. a timeout, retry count, or feature-flag default), as does any conditional or logic edit. +- **Not a code task → no grade at all.** If the task will not modify any file (reading or explaining code, answering a question, reviewing a doc, ticket or screenshot, drafting a reply or message in chat), don't grade it: print `> LinearB: — skipped (not a code task)`, call nothing, and work with your normal care. A grade measures the risk of a code change; a LOW here would wrongly tell you to go light on accuracy. If the task later turns into a file edit, run the sweep then, before the first edit (a hook holds that edit until a real grade exists). +- **Trivial code edit → LOW, skip everything.** If the task edits any file but changes **no code behavior** (code comments, doc files, formatting/whitespace, a pure rename), skip signal gathering entirely: effort is **LOW**, add no defensive guards (there's no logic to protect), and don't call LinearB at all — this holds **even on a fragile repo**. Anything that changes behavior is **not** trivial and warrants the sweep below — note that a **constant-value change counts as behavioral** (e.g. a timeout, retry count, or feature-flag default), as does any conditional or logic edit. - **Already graded recently → reuse (persistent 24h cache).** The repo-level verdict is daily-stable, so compute it at most **once per repo per ~24h**, not once per task/session — this is the main token/time saver. Cache file, keyed by repo root: ```text diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index 3a0071a..e65f278 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -178,6 +178,15 @@ run "$TRIGGER" PreToolUse "$(tool Read app.js)" check "trigger: a skipped (not a code task) line counts as answered -> no reminder" silent teardown +setup +add_skill; add_skipped +run "$TRIGGER" PreToolUse "$(tool Edit app.js)" +check "trigger: an edit after a skipped (not a code task) run is held until a real grade" denied +add_verdict +run "$TRIGGER" PreToolUse "$(tool Edit app.js)" +check "trigger: ...and goes through once the grade is printed" silent +teardown + setup add_skill; add_verdict run "$TRIGGER" PreToolUse "$(tool Edit app.js)" From fe76b1588dc83ca9012572e369d0a12eb973d7e9 Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 21 Oct 2026 11:56:11 +0300 Subject: [PATCH 3/4] fix: address gitstream/Copilot review (round 2) Co-Authored-By: Claude Opus 5.5 --- plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh | 9 ++++++--- tests/agentic-advisor/hooks_test.sh | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh index 012cb53..ee830e0 100755 --- a/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh +++ b/plugins/agentic-advisor/hooks/agentic-advisor-trigger.sh @@ -52,8 +52,10 @@ skill_ran() { # Is the LATEST advisor Skill call still missing its verdict (assistant text, or the # hold's `printf` Bash call)? Prints "pending" or "ok"; prints nothing on parse failure. -verdict_state() { - jq -rs --arg n "agentic-advisor" --arg re 'LinearB: .+ ((LOW|MEDIUM|HIGH) effort|skipped \(not a code task\))' ' +VERDICT_RE='LinearB: .+ ((LOW|MEDIUM|HIGH) effort|skipped \(not a code task\))' +GRADED_RE='LinearB: .+ (LOW|MEDIUM|HIGH) effort' +verdict_state() { # $1 = the verdict regex required (default: a grade or a skip) + jq -rs --arg n "agentic-advisor" --arg re "${1:-$VERDICT_RE}" ' [.[] | select(.message.role? == "assistant") | .message.content? // [] | .[]?] as $c | [$c | to_entries[] | select(.value.type? == "tool_use" and .value.name? == "Skill" and ((.value.input.skill? // "") | tostring | contains($n))) | .key] as $sk @@ -198,7 +200,8 @@ case "$event" in # Skill already graded this session -> allow the edit. A "skipped (not a code task)" line alone doesn't count: editing now is code work. # If a verdict names this repo, mark it handled so later prompts here aren't nudged. - if skill_ran && grep -qE 'LinearB: .+ (LOW|MEDIUM|HIGH) effort' "$transcript" 2>/dev/null; then + # "pending" only when parsed and no grade yet; a parse failure prints nothing and fails open. + if skill_ran && [ "$(verdict_state "$GRADED_RE")" != "pending" ]; then set_marker "$dir" # 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}" diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index e65f278..5058a78 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -53,6 +53,8 @@ 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"; } +# The loaded SKILL.md lands in the transcript as a user message, example verdict line included. +add_skill_body() { printf '%s\n' '{"type":"user","isMeta":true,"message":{"role":"user","content":[{"type":"text","text":"Example: `> LinearB: api-service — HIGH effort (rework 3.4%) — small steps.`"}]}}' >> "$TRANSCRIPT"; } add_skipped() { printf '%s\n' '{"message":{"role":"assistant","content":[{"type":"text","text":"> LinearB: widgets — skipped (not a code task)"}]}}' >> "$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. @@ -179,7 +181,7 @@ check "trigger: a skipped (not a code task) line counts as answered -> no remind teardown setup -add_skill; add_skipped +add_skill; add_skill_body; add_skipped run "$TRIGGER" PreToolUse "$(tool Edit app.js)" check "trigger: an edit after a skipped (not a code task) run is held until a real grade" denied add_verdict From 9b5485aad2ee95fc836ce796bb54b3e79af7294e Mon Sep 17 00:00:00 2001 From: nivSwisa1 Date: Wed, 21 Oct 2026 11:59:15 +0300 Subject: [PATCH 4/4] fix: shellcheck SC2016 in the skill-body test fixture Co-Authored-By: Claude Opus 5.5 --- tests/agentic-advisor/hooks_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/agentic-advisor/hooks_test.sh b/tests/agentic-advisor/hooks_test.sh index 5058a78..9bcbc7c 100755 --- a/tests/agentic-advisor/hooks_test.sh +++ b/tests/agentic-advisor/hooks_test.sh @@ -54,7 +54,7 @@ denied() { [ "$rc" -eq 0 ] && jq -e '.hookSpecificOutput.permissionDecision == 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"; } # The loaded SKILL.md lands in the transcript as a user message, example verdict line included. -add_skill_body() { printf '%s\n' '{"type":"user","isMeta":true,"message":{"role":"user","content":[{"type":"text","text":"Example: `> LinearB: api-service — HIGH effort (rework 3.4%) — small steps.`"}]}}' >> "$TRANSCRIPT"; } +add_skill_body() { printf '%s\n' '{"type":"user","isMeta":true,"message":{"role":"user","content":[{"type":"text","text":"Example: > LinearB: api-service — HIGH effort (rework 3.4%) — small steps."}]}}' >> "$TRANSCRIPT"; } add_skipped() { printf '%s\n' '{"message":{"role":"assistant","content":[{"type":"text","text":"> LinearB: widgets — skipped (not a code task)"}]}}' >> "$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.