Skip to content

perf(work-items): move /work-items:work CI mode to reference/ci-mode.md - #13133

Merged
kyle-sexton merged 5 commits into
mainfrom
perf/12468-work-ci-mode
Nov 4, 2026
Merged

kyle-sexton merged 5 commits into
mainfrom
perf/12468-work-ci-mode

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

Refs: #12468

Summary

/work-items:work's CI mode section (about 14 KB) moves to reference/ci-mode.md, so a load that names one item or auto-selects no longer carries it. All 7 measured main-session loads named one item and none ran --ci (host-run record). SKILL.md drops from 61,462 to 47,301 bytes. Three new eval cases cover the moved text, and a paired run shows no loss at a 0.05 margin.

Fix

  • SKILL.md: the section leaves. The Arguments line and a ## CI mode stub both tell a --ci run to read reference/ci-mode.md first, follow it and skip every other section. The stub defines <plugin-root>.
  • reference/ci-mode.md: the text is verbatim, except the title's heading level and one link now written <plugin-root> with a relative target (check-spoke-plugin-root). The work-resolve-issue lane copies the whole plugin to .lane/plugins/ (collect-base-activity/action.yml), and a Read in the working directory needs no rule, so the lane can read it.
  • unattended-callers.test.mjs: reads the new home with the same expected calls and exemption. A new test fails if the stub stops pointing there. No other reader parses the section: pr-run-activity.md and work-items.schema.json only name the mode.
  • Three deterministic cases drive --issue <n> --ci from a scaffolded issue.json and grade scratch/work-outcome.json:
    • wk-ci-verify-close-unmet: the verify-unmet: stop on a verify_close run (step 1).
    • wk-ci-review-venue-skips-review: review recorded skipped and the venue line in not_done when CI holds the venue, with no subagent, claim, worktree or PR (step 4).
    • wk-ci-already-done-stops: the already-done: stop citing a SHA (step 5).
  • wk-confirm-before-claim: no-claim-before-yes failed two correct runs. It matched a checklist line naming the later claim and, past the command's closing quote, a path in the Bash description. It now reads JSON escapes, with samples for both.

Verification

Paired eval, Sonnet subject, Opus judge, Claude Code 2.1.318, --ablation none, --scaffold, 8 wk-* cases, 5 runs per case. Before = the branch point with the new cases copied in; after = this change.

Case Before After
wk-bug-fork-pr-claim-routed 1.00 1.00
wk-bug-investigate-mode-marker-only 1.00 1.00
wk-bug-repro-twice-then-proof 0.95 1.00
wk-bug-verify-existing-fix-confirmed 1.00 1.00
wk-ci-already-done-stops 1.00 1.00
wk-ci-review-venue-skips-review 1.00 0.96
wk-ci-verify-close-unmet 1.00 1.00
wk-confirm-before-claim 1.00 1.00
  • run-validity.py: verdict: VALID on both arms, 40 of 40 traces, no denied tool call. The before arm warns of one split judge vote (wk-bug-repro-twice-then-proof run 5, FAIL PASS PASS); no case has a skill-fired grader, because the prompts are slash-invoked.
  • noise-report.py --baseline <before> --margin 0.05: change +0.00, 95% interval -0.02 to +0.02, compare verdict: non-inferior at margin 0.05. List-price estimate: 6.00 USD before, 5.93 USD after.
  • Reach: all 15 after-arm wk-ci-* runs read reference/ci-mode.md; none of the other 25 did.
  • The one after-arm miss is wk-ci-review-venue-skips-review run 4: it skipped the review and recorded it, but paraphrased the venue line in not_done instead of copying it, so venue-line-not-required failed. A paraphrase also occurred in the earlier round's after arm (below), 2 of 10 runs against 0 of 10 before.
  • Earlier round, before the grader fixes: both arms VALID, change -0.02, interval -0.05 to +0.01, non-inferior, 6.17 and 6.54 USD. Its other four after-arm misses were false failures on correct runs: an escaped quote stopped the verify-unmet pattern short (2) and the confirm grader above (2). Those patterns were fixed and both arms rerun.
  • Negative control, --runs 1, before the grader fixes: with the section deleted and no reference file, wk-ci-already-done-stops 0.50, wk-ci-review-venue-skips-review 0.60, wk-ci-verify-close-unmet 0.40, every grader on the outcome file failing; on the unmodified copy all three scored 1.00. Both VALID (the deleted side with --own-copy-search-warns, one denied search of its own plugin copy).
  • /docs-hygiene:compress compare, before against after skill directory: VERDICT: PASS, no SEMANTIC LOSS and no AMBIGUITY.
  • node --test unattended-callers.test.mjs: 4 passed. check-spoke-plugin-root.sh --check: clean. validate-cases.py: no FAIL.
  • Left out: the meets-expectations judge graders on the wk-bug-* cases are uncalibrated (they have no labeled samples); the negative control was not rerun on the final graders, whose changes only widen a pattern over JSON escapes and add two must-not graders; one model only (Sonnet); a real work-resolve-issue lane run, which needs an agent-ready issue after merge.

Related

Remaining

🤖 Generated with Claude Code

kyle-sexton and others added 5 commits November 4, 2026 01:57
Three cases drive --issue <n> --ci from a scaffolded issue.json and grade
scratch/work-outcome.json with deterministic graders: the verify_close
verify-unmet path, the code-review ci venue skip, and the already-done
stop code.

Refs: #12468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All 7 measured main-session loads named one item and none ran --ci, yet
each carried the section. The CI lane copies the whole plugin, so it can
read the new file. SKILL.md keeps the pointer at its Arguments line and in
a stub. unattended-callers.test.mjs reads the new home with the same
expected calls, and now also checks the stub points there.

Refs: #12468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…folds

The fixture a scaffold writes is unchanged.

Refs: #12468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first 5-run round showed two false failures. A reason holding an
escaped quote stopped the verify-unmet pattern short of the item it names,
and no-claim-before-yes matched a checklist line naming the later claim and,
past the command's closing quote, a path in the Bash description. Both
patterns now read JSON escapes, each with a sample for what it wrongly
failed. verify-close also grades a Bash commit and the doc it must not build,
since --allow-tools grants Bash to every case.

Refs: #12468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review November 4, 2026 07:26
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T07:28:14.448838Z d6889a9 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

claude-security-review reviewed d6889a9cd60e935f3b59f9b8b5755519e793fa43: read 28 of 28 changed file(s); 0 finding(s), 0 as inline comments.

Security review: PR #13133, /work-items:work CI mode moved to reference/ci-mode.md

I found no security issues in this PR.

I read every hunk of all 28 changed files in .claude-lane/pr.diff. None of them matches a trusted-path glob.

What I checked

  • Instruction-surface lens: the moved CI-mode text. This is the CI lane's prompt. It carries several trust rules:

    • verify-findings comments, resume/stale_branch commits and split_parent text are treated as data, never instructions.
    • Only person_checks excuses a done-when item.
    • Only a "decision": true comment settles an open question.
    • A verify_close run never closes an item on a sub-issue's close alone.
    • The security-risk:/cost-risk: stop codes stay in place.
    • Every stopped-reason code and its routing is unchanged.

    I compared the removed block in SKILL.md line by line with the new file. The new reference/ci-mode.md (lines 1–178) carries it verbatim, with two exceptions:

    • The heading is now a level-1 title.
    • The item-content-trust.md link is now written <plugin-root>/reference/item-content-trust.md. Its relative target ../../../reference/item-content-trust.md resolves to plugins/work-items/reference/item-content-trust.md, the same file as before.

    No rule is deleted, narrowed or softened. The register's protected classes are not touched.

  • Routing stub. The SKILL.md Arguments line and ## CI mode stub both send a --ci run to read the reference file first, follow it and skip every other section. Other invocations are told not to read it. A --ci run therefore still follows the same rules, and nothing new reaches the other modes.

  • unattended-callers.test.mjs. The --unattended check now reads the new file with the same expected calls and exemption. A new test fails if the stub stops pointing at that file. These changes are test-only and widen nothing.

  • New eval cases and scaffolds (wk-ci-*). The scaffolds are local git init fixtures with static heredoc content and read no outside input. The graders are regex and tool-use checks run in the eval harness. Neither reaches a credentialed lane.

  • wk-confirm-before-claim grader regex and samples. This changes only an eval grader's pattern and adds pass/fail samples. No runtime control depends on it.

  • Plugin manifests. No .claude-plugin/plugin.json or marketplace.json changed. The .changes/ file only records a patch bump.

  • Trust controls. The diff touches no trust control, merge hold, token scope, kill switch or workflow.

Spend

The PR adds three eval cases. Running them spends prepaid API credit on eval runs, which the PR estimates at about 6 USD list price per paired run. This is not a billing change.

The PR context contains no embedded instructions aimed at this lane.

critical-findings: 0

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

claude-review reviewed d6889a9cd60e935f3b59f9b8b5755519e793fa43: read 28 of 28 changed file(s); 0 finding(s), 0 as inline comments.

Code review: no findings

I read the whole change in all 28 files. This PR moves /work-items:work's CI mode out of SKILL.md and into reference/ci-mode.md. It also adds three deterministic wk-ci-* eval cases and tightens the wk-confirm-before-claim grader.

What I checked

  • Moved text. I compared the removed ## CI mode body line by line with the new reference/ci-mode.md. Only two things changed, the same two the PR body names:

    • The title is now an H1.
    • The trust link is now <plugin-root>/reference/item-content-trust.md → ../../../reference/item-content-trust.md. From skills/work/reference/ that path reaches plugins/work-items/reference/, the same target the old ${CLAUDE_PLUGIN_ROOT} link had.

    The SKILL.md stub defines <plugin-root>. That matches the existing "Spoke paths" convention (SKILL.md#L238).

  • Cross-references in SKILL.md. These still hold after the move:

    • "CI mode runs its own inline gate in its step 3" (L203): step 3 is still in the moved file.
    • The Bug path's "CI mode keeps its own steps".
    • The bug_path.mode note.
    • The updated pointer at L173, which now names reference/ci-mode.md.
  • unattended-callers.test.mjs.

    • between(CI_MODE, "# CI mode", "## ") matches line 1 of the new file. The file has no H2, so the check runs to the end of the file and covers the whole moved body.
    • The new pointer test reads the SKILL.md stub. That stub runs up to ## Shared tracker context and contains skills/work/reference/ci-mode.md, so dropping the pointer would fail the test.
  • Graders. I walked each new regex through its pass and fail samples:

    • already-done-cites-sha: the digit lookahead rejects the word defaced, and the pattern handles escaped quotes.
    • verify-unmet-names-item: does not match when retries appears only in a later field.
    • venue-line-not-required: works in either key order.
    • writes-only-outcome: the negative lookahead works as intended.
    • no-claim-before-yes: excluding unescaped " stops the match from running into the Bash description field. It still catches > \"docs/setup.md\" through the \\[^n] branch. The added backtick in the lookbehind excludes the checklist sample.

    Every sample gets its labeled result.

  • Scaffolds. scratch/ is gitignored before git add ., so issue.json and review-venue.txt stay out of the commits. The already-done scaffold commits the fix to main, as the case expects.

  • Release record. The .changes/work-items fragment declares bump: patch. That fits a change that leaves behaviour the same. No plugin.json or marketplace.json changed, so there are no manifest lines.

  • Path-scoped rules.

    • .claude/rules/skill-bodies-state-current-rules.md: the moved text adds no new upstream restatement.
    • .claude/rules/eval-case-transcripts.md: the new samples are synthetic, with no machine-specific paths or identifying details.
  • Closing issue. None: the PR says Refs: #12468 and closes nothing, so I checked no acceptance criteria.

Not checked (claims I could not verify)

  • Can the lane read the file? The work-resolve-issue lane must be able to Read ${CLAUDE_PLUGIN_ROOT}/skills/work/reference/ci-mode.md. The PR says the lane copies the whole plugin to .lane/plugins/. I could not confirm this from the files in scope. The PR body also says a real lane run was left out, so this is the main remaining risk until one runs after merge.
  • Author's results. The paired-eval results, the run-validity.py and noise-report.py verdicts, the node --test pass and the check-spoke-plugin-root.sh result all come from the author. I did not run any of them.

Spend: the three new eval cases use prepaid model credit only when someone runs the eval suite. None of it is a billed resource.

No embedded instructions were found in the PR context or prior-findings files. This is the first round, well under the round cap of 3.

@kyle-sexton
kyle-sexton added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 44d49c4 Nov 4, 2026
67 of 68 checks passed
@kyle-sexton
kyle-sexton deleted the perf/12468-work-ci-mode branch November 4, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant