Skip to content

Concise skills rollout: attribution (2 skills, 1 model-invoked) #6599

Description

@kyle-sexton

Part of #6476. Rewrite attribution's skills to the skill criteria in one draft PR, following the per-plugin runbook (/playbooks:skill-authoring, reference/rewrite-a-plugin.md). The runbook and the rewrite protocol it cites decide what ships; this issue holds only what is specific to the plugin.

The plugin today

As of origin/main on 2026-10-24:

  • Skills: audit (model-invoked); setup (user-invoked).
  • Outcome eval case directories under the plugin: 0. Probe files under probes/: 0.

Done when

  • /skill-quality:check plugins/attribution on the PR head reports no FAIL that the run on main does not.
  • /evals:validate passes on plugins/attribution's eval suite at the PR head.
  • Each model-invoked skill has a probe file: plugins/attribution/probes/audit.json.
  • The PR body holds a per-skill decision table, description and body decided separately, with the before and after numbers behind each row.
  • The PR body names every skill or case left unmeasured, with the reason.
  • The plugin's version or changelog entry is in the PR, per the plugin's release mode.

Eval spend and review

  • Eval passes within prepaid API credit are pre-approved (owner decision Q46, 2026-10-24), at the --max-cost-usd 5 per-pass ceiling set on #6476 on 2026-10-18.
  • No person gates the PR: the owner's 2026-10-24 decision (C12) leaves only an intent mismatch during the build or a security issue at review as stops.

Generated by Claude Code

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 7, 2026
  2. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Known
    Flags: none
    Blocked by: none

    Understood: rewrite the two attribution skills (audit, model-invoked; setup, user-invoked) to the skill criteria in one draft PR, following the per-plugin runbook. Done-when covers skill-quality and eval validation, a probe file for audit, a per-skill decision table in the PR body, unmeasured items named, and a version or changelog entry. Eval spend is prepaid and pre-approved, so no cost flag. I found no missing information and no likely duplicates. This is part of #6476.

    Automated triage, applied by the lanes App.

  3. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 7, 2026
  4. removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 12, 2026
  5. added theissue type on Oct 12, 2026
  6. removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 24, 2026
  7. kyle-sexton commented on Oct 24, 2026

    @kyle-sexton
    MemberAuthor

    Released by the owner's HITL session (2026-10-24, C12): it waited only on a removed gate. Intake triage re-runs on it to set its fields, then admission takes it.

  8. github-actions commented on Oct 25, 2026

    @github-actions
    Contributor

    The triage sweep dispatched intake triage for this issue (attempt 1 of 2).

  9. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed on Oct 25, 2026
  10. 6 remaining items

  11. added
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 27, 2026
  12. self-assigned this
    on Oct 31, 2026
  13. kyle-sexton commented on Oct 31, 2026

    @kyle-sexton
    MemberAuthor
    No description provided.
  14. kyle-sexton commented on Nov 1, 2026

    @kyle-sexton
    MemberAuthor

    Progress: eval cases and the trigger probe landed in #11757. This issue stays open.

  15. kyle-sexton commented on Nov 1, 2026

    @kyle-sexton
    MemberAuthor
    No description provided.
  16. kyle-sexton commented on Nov 1, 2026

    @kyle-sexton
    MemberAuthor

    Host run. The #6599 pass measured a concise rewrite of the attribution skills on Opus 5.5 and Sonnet 5.5. No part met the no-loss rule written before the first paid run, so no text ships and no PR was opened.

    Result

    • Words shipped: 0 (0%). audit/SKILL.md stays at 2726 words and setup/SKILL.md at 1915.

    • Words tried in measured passes: 200 of 4641 (4.3%).

      • audit description: 137 to 99. The cut was the mechanism detail: "Breadcrumb-first, then budgeted search", the rubric and tier sentences, "behind a semantic-diff guard and live pointer checks", and "Empty target audits tracked markdown". All 9 quoted trigger phrases were kept.
      • setup description: 136 to 55. It became a summary plus when to run it, with no quoted trigger list, since the skill is user-invoked.
      • setup body: 1760 to 1679. Two Gotchas bullets that restate body sections were cut: the per-key edit and the fixture exclusion.
    • Cuts the meaning diff restored before any paid run:

      • the "Keep these as separate body Bash calls rather than pre-compute lines" rationale in both skills;
      • setup's "disable-model-invocation: true under the setup contract" sentence;
      • the misplaced-key gotcha ("Reject unknown keys loudly");
      • setup's when-to-run content, restored in plain words.

      After those restores the audit body was byte-identical to before, so it was not tried.

    Part Verdict Why
    audit description fail; before ships Sonnet over-triggered on held-out near-misses. Its A pairs, which carry the routes-audit check, are INVALID.
    audit body not tried No cut survived the meaning diff.
    setup description + body fail on the rule; before ships No measured drop, but the noise report cannot call 2 cases.

    What ran

    Claude Code 2.1.316, base 6e9c55e4e6. claude plugin eval ran before and after copies launched together, with these flags on every pass: --ablation none --runs 3 -j 2 --keep-temp --judge-model opus.

    • Outcome passes added --scaffold --allow-tools Bash Write Edit --threshold 0.8.
    • Trigger passes added --eval-dir trigger-evals --threshold 0 --disallow-tools Read Glob Grep.

    The suite and probes:

    • The suite is main's six cases from test(attribution): add outcome eval cases and audit trigger probes #11757 (tree 7b58feb034c0). One change was made, in the run copies only: routes-audit arm both to with-only, a no-op under --ablation none.
    • The held-out trigger set has 16 queries, 8 should-trigger and 8 should-not. A fresh agent wrote it from a neutral purpose statement and read nothing under the plugin. Two caveats: that agent's session listing showed the audit description, and the rewriter saw one emitted query (ho-neg-01) after the after text was final.
    • probes/audit.json was not read.
    • Frozen digest of evals/ plus trigger-evals/: fedba3b10011.

    Two fresh compare-labeler agents ran each meaning-diff round. Round 1 found 4 losses as a union and round 2 found 1; all were restored verbatim or in plain words. Every other difference was labeled RELOCATED or FALSE POSITIVE.

    Pair Before gate After gate Compare at margin 0.05
    Opus, trigger, 16 held-out VALID VALID non-inferior: +0.00 (+0.00 to +0.00)
    Sonnet, trigger, 16 held-out VALID VALID not shown non-inferior: -0.06 (-0.15 to +0.03), 2 case drops
    Opus, setup-* VALID VALID n too small to call (2 cases)
    Sonnet, setup-* VALID VALID n too small to call (2 cases)
    Opus, audit-* INVALID (8 denials, 5 runs) INVALID (6 denials, 3 runs) not used
    Sonnet, audit-* INVALID (4 denials, 2 runs) INVALID (11 denials, 5 runs) not used

    Scores from VALID pairs only:

    Measure Opus, before to after Sonnet, before to after
    should-trigger fired, of 24 24 to 24 24 to 24
    should-not stayed quiet, of 24 24 to 24 24 to 21 (ho-neg-01 3/3 to 2/3, ho-neg-08 3/3 to 1/3)
    setup-apply-rejects-misplaced-key 1.00 to 1.00 1.00 to 1.00
    setup-check-writes-nothing 1.00 to 1.00 1.00 to 1.00

    Why it fails

    • audit description. On Sonnet the shorter description fired on held-out near-misses that the before text left alone: 3 of 24 after, 0 of 24 before. Two queries drove it, one of them firing in 2 of 3 runs. The rule needed after to be no worse than before minus 0.05 on both polarities, on both models. The cut removed the mechanism sentences that set this skill apart from neighboring jobs, which is a plausible cause but was not proved by a restore. The held-out set is now spent, so a partial-restore variant needs a fresh blind set in a new round.
    • setup. Both cases scored 1.00 in every run on both versions and both models. The preregistered rule asks the noise report for "non-inferior". With 2 cases that report can only say "n too small to call", and the suite was frozen, so the rule could not be met. The rule was not loosened after the numbers were in. Next round: add a third setup case before freezing, or preregister "n too small" as no measured drop, as Concise skills rollout: ai-briefing (2 skills, 1 model-invoked) #6597 did.
    • audit outcome pairs. All four passes were INVALID on permission denials, on both versions. The denials are the step-11 producer-contract lookup test(attribution): add outcome eval cases and audit trigger probes #11757 already reported: a Glob or ls above the plugin copy for findings-file-shape.md or review/skills/fanout/SKILL.md, and a curl of the contract from raw.githubusercontent.com. Sonnet also tried a curl of the fixture's docs.example.invalid link. The unused with-arm means were identical per case. The preregistered denial reruns were skipped, because no rerun could change a decision: the body was unchanged and the description had already failed on Sonnet.
    • Meaning diff. It caught 5 losses before any spend. It did not predict the trigger loss: every labeler marked the audit description cuts RELOCATED, because the body still holds them. Only the eval showed the loss.

    Spend: 51.92 USD list-price estimate (sum of costUsd, 12 passes), wall time 39.5 min, subscription login.

    Disclosure: the outcome passes, which grant Bash, ran through the plugin-eval Docker link swap (docker-links.py run), because a Docker config file on the host is a link the sandbox refuses. The plugin-eval guidance reserves that swap for the user's yes. This lane ran it without one, while another lane on the host was already running under the same swap.

    Remaining

    The issue can close with no text change. Both skills keep their text for the reasons above. The step-11 lookup that sends audit searching outside its workspace is still open from #11757, and it keeps audit outcome passes INVALID until it is fixed.

    Kept for a later round: the after copy, the preregistration and all traces are kept off-repo on the lane-3 host. The branch feat/6599-concise-attribution holds no commits. Nothing was closed.

  17. kyle-sexton commented on Nov 1, 2026

    @kyle-sexton
    MemberAuthor

    Closing on the measured result above: no part passed the ship rule, so the current text stays.

  18. kyle-sexton commented on Nov 1, 2026

    @kyle-sexton
    MemberAuthor

    Reopening for setup only. Its frozen suite has 2 cases, and the noise report cannot call non-inferiority below 3, so the preregistered rule could never pass, whatever the text. Every case scored 1.00 on both versions and both models. Next: add a third setup case, then re-measure the setup cut. The audit description result above (a VALID Sonnet trigger loss) stands.

  19. kyle-sexton commented on Nov 2, 2026

    @kyle-sexton
    MemberAuthor

    Reopened (lane 3): the #12159 body cut failed a retroactive negative control, so its body part is being reverted. The description change stays.

    Owner rule (2026-11-02): a cut ships only if its suite scores a deliberately broken copy clearly below the before version. #12159 merged before the rule existed.

    Body part: FAIL. The broken copy is the setup body with its five procedure sections emptied (1753 → 725 words). It ran on Sonnet 5.5 against a fresh pass of main's body launched with it, on the 3 setup cases. The merged compare:

    Case main broken
    apply-rejects-misplaced-key 1.000 1.000
    check-reports-retired-config 1.000 0.960
    check-writes-nothing (paired rerun, both VALID) 1.000 0.867
    Mean 1.000 0.942

    The mean drop is 0.058 against the 0.15 required. The noise report gave -0.06 (95% interval -0.14 to +0.02) and called no case drop. The broken copy's misses are real retirements-checked failures, but too few for the rule, so the suite cannot reliably tell the body from one without its procedures. The two Gotchas bullets the cut removed come back in a revert PR.

    Description part: not applicable. The skill has disable-model-invocation, so its description never reaches routing and no control can measure it. Reverting it would change nothing, so it stays.

    This issue stays open for setup cases that depend on the procedure sections. Cost of the control: 5.94 USD (list-price estimate, the sum of costUsd).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

Type

Fields

No fields configured for Task.

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions