Branch: refs/heads/master Home: https://github.com/xwiki/xwiki-dev-llm Commit: e975ac0571e6d52f1e3d80e8b67e35c92f6c1aec https://github.com/xwiki/xwiki-dev-llm/commit/e975ac0571e6d52f1e3d80e8b67e35... Author: Vincent Massol <[email protected]> Date: 2026-09-17 (Thu, 17 Sep 2026) Changed paths: M README.md M xwiki/okf/index.md M xwiki/okf/servers/jenkins.md M xwiki/scripts/jenkins.mjs A xwiki/scripts/jira-flickers.mjs A xwiki/scripts/routine-setup.sh A xwiki/skills/xwiki-ci-check/SKILL.md A xwiki/skills/xwiki-ci-check/routine-prompt.md A xwiki/skills/xwiki-ci-check/tools/ci-check.mjs A xwiki/skills/xwiki-ci-check/tools/commit-comment.mjs A xwiki/skills/xwiki-ci-check/tools/matrix.mjs A xwiki/skills/xwiki-ci-check/tools/privatebin.mjs M xwiki/skills/xwiki-release-test-triage/SKILL.md M xwiki/skills/xwiki-release-test-triage/tools/triage.mjs Log Message: ----------- [Misc] Add the xwiki-ci-check skill, the daily acting CI sweep * Add skills/xwiki-ci-check: explicit-invocation-only, writes gated behind --write, with a 7-day blame horizon and a per-run budget of 5 deep-treated incidents and 2 fix PRs * Add tools/ci-check.mjs, read-only by construction: discovers the jobs from Jenkins, classifies every red build, groups symptoms into incidents, ages and attributes them, and emits a pre-digested JSON work order * Add tools/privatebin.mjs (PrivateBin v2 client, no dependencies, --self-test), tools/matrix.mjs (digest poster) and tools/commit-comment.mjs, which owns both ends of the marker contract that stops the next run repeating itself * Add routine-prompt.md, the thin prompt the scheduled routine is given * Extract the open-flicker JIRA lookup into scripts/jira-flickers.mjs, shared with xwiki-release-test-triage * Add stagesOf()/failedNodesOf()/logUrlOf()/stepLog()/stepConsole()/grepLog() to scripts/jenkins.mjs: a platform build's consoleText is ~80 MB with no Content-Length and no Range support, so a failure is diagnosed through the Pipeline Stage View API instead * Parse the step log as the JSON envelope it is: wfapi/log returns {nodeId,length,hasMore,text,consoleUrl} with the log in text and its newlines escaped, so reading the body as text yields a single line and no per-line pattern can ever match. It is also only the last ~10 KiB, start being ignored, which puts Maven's "Failed to execute goal ... on project X" above the window and leaves "mvn <args> -rf :<module>" inside it — hence one fallback to the node's console page for a stage the tail could not explain * Classify from the first failed stage alone, never pooled: a broken build fails in a cascade (Main, then TestRelease, then the quality gate), and letting the highest-priority matcher anywhere in the pile decide makes the diagnosis depend on how far the cascade ran, so two builds of one unchanged break sign differently and the blame window collapses onto the last build's commits * Match the quality gate on Jenkins' own wording too ("Pipeline aborted due to quality gate failure"), which is what waitForQualityGate puts in the stage error; the scanner's "QUALITY GATE STATUS: FAILED" never reaches it * Record in okf/servers/jenkins.md the measured traps behind all of it: the ~80 MB log and the stage API that replaces it, the JSON envelope, the 10 KiB tail, HTML-escaped log text, the cascade rule, timestamp-prefixed console lines, empty changeSets on Commons, noreply authors, and the build cadence that makes a blame window 1-17 commits wide * Point xwiki-release-test-triage at the new skill for the acting case * Quote the whole of an error and not its first line: keep the lines that continue each named pattern, and emit a contiguous block as evidence. Maven prints "Rule 0: ... failed with message:" and puts the module, the dependency and the two versions underneath, so the matched line on its own said nothing and every RequireUpperBoundDeps break came back unattributable * Match "Rule N: <class> failed with message" without requiring [ERROR]: Maven writes that message twice and the bare copy, inside the MojoExecutionException it dumps, is the one that survives in the 10 KiB tail — so the tail now classifies without paying for the console page. The looser enforcer alternatives keep [ERROR], since "[INFO] --- enforcer:...:enforce (enforcer-rules)" is printed by every green build * Score blame by what the failure itself names, not only by file overlap: Maven coordinates and xwiki-* module ids from the evidence, matched against a commit's changed paths, and library names matched against its subject line, since a version bump changes a pom and nothing else and only the subject says which library. A subject match yields "likely" and never "certain" * Attribute a Sonar quality gate to nobody — it fails on aggregate metrics, not on a change — and rank it below test-breakage so it stops taking the first deep slot; rank a systematic failure tracked as a flicker above plain breakages, that being the one case the skill has an explicit rule for * File one flicker issue per test class per regression window, naming every branch the test fails on (flickerGroup, alsoOn), instead of one issue per method per branch; require its summary to name the class and every method, since jira-flickers.mjs joins on the "Flickering Test" field first and on class + method in the summary second, so a method in neither is filed again the next morning * Render the paste from the work order (--render-detail), in a fixed section order with fixed wording, leaving one "<!-- ANALYSIS: id -->" line per deep incident for the model to replace. A regression window with no green build reads "failing in every build examined, back to #N - start not established" rather than "since #N", that number being how far the sweep looked and not when the break began * Report which environments a class 1 incident failed on, not only how many * Append a visible footer to every commit comment - a machine wrote it, and a wrong attribution may be ignored - next to the invisible dedupe marker * Log in to Matrix per run instead of storing an access token: matrix.org issues short-lived tokens (the mat_ ones), refreshed continuously inside a client, so one copied into a profile or a routine's secret store is dead within minutes and a 06:00 routine finds it expired every morning. MATRIX_USER_BOT + MATRIX_PASSWORD_BOT log in on a fixed device; MATRIX_TOKEN_BOT is still honoured, for homeservers whose tokens do not expire, and is fallen back from to the password when the server refuses it * Default the room to the fully qualified #xwiki:matrix.xwiki.com and the homeserver to matrix.org: the account and the room are on different servers, and completing a bare alias with the homeserver's own hostname builds #xwiki:matrix.org, which does not exist * Join the room when a send comes back 403, so an invited bot needs nobody to notice, and report a credential failure as a sentence rather than a stack trace - an expired token is this tool's expected failure, not a bug in it * Require a *classic* GitHub token for the bot, and say why in README: the xwiki org rejects a fine-grained token whose lifetime exceeds 366 days, with a 403 on every request including plain reads * Make the local developer run the default mode, the routine's --write the exception: a developer can sweep at any time, and that run analyses to the terminal, never posts the Matrix digest, and asks once before each of the four writes it may make - the PrivateBin paste, a commit comment, a flicker issue, a fix PR. It needs no bot credential to be useful, the sweep, the analysis and the paste all working with nothing configured. An unattended run has nobody to ask, so it writes nothing, which is what makes the dry-run soak safe * Refuse the digest locally whatever the answer: it is the one broadcast here, with no addressee and no undo, and it is the routine's own output - a second one from a laptop at 14:00 turns the room's record of CI into a record of who ran the skill. A locally filed flicker issue cannot duplicate the next morning's run, the routine filing only a proven flicker whose jira is null and that field coming from a live lookup * Carry each channel's identity for its own reason: a comment is the bot's always, since it lands unasked on someone else's commit and must never read as coming from a colleague; a local fix PR is the developer's own, there being no App token on a laptop and a PR being proposed work someone has to own; a local issue is the bot's when JIRA_TOKEN_BOT is set and the developer's otherwise, an unassigned flicker issue being an authorship rather than an accusation * Make every writer tool a no-op without its own --write, inverting --dry-run (still accepted, being what now happens anyway): the bot credentials sit in a developer's shell profile as well as in the routine's secret store, so one forgotten flag was a real comment on a colleague's commit. The safety property is now one sentence with no exception - no tool here writes anywhere unless told to * Drop the fork requirement, which rested on a wrong inference: the bot's token does have push:false on all three repos, but it is not what pushes. The Claude GitHub App installed on the org opens the PR with the head branch in the upstream repo itself, exactly as it already does for the SonarQube routine, and the bot identity rides on the commit author instead (XWiki LLM Bot <[email protected]>) * Add scripts/routine-setup.sh, the setup script a routine's sandbox runs before the prompt: a sandbox is new every run, so gh, the plugin, JDK 17 and 21, xmvn and an ~/.m2/settings.xml pointing at XWiki's Nexus are installed there every time. Keeping it in the repo is what lets a routine be rebuilt from scratch and makes a change to it a reviewed pull request rather than an edit to a config box nobody else can see. xmvn and the two JDKs are what let one sandbox verify a fix on any branch: it reads xwiki.java.version from the pom and exports the matching JAVA_HOME, the maintained branches wanting 17 up to stable-17.10.x and 21 from stable-18.4.x on. Shared with the SonarCloud routine Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Commit: 8abc00ac5c6970305ba34904db67b79b1ad16481 https://github.com/xwiki/xwiki-dev-llm/commit/8abc00ac5c6970305ba34904db67b7... Author: Vincent Massol <[email protected]> Date: 2026-09-17 (Thu, 17 Sep 2026) Changed paths: M README.md M xwiki/okf/index.md M xwiki/okf/servers/jenkins.md M xwiki/scripts/jenkins.mjs A xwiki/scripts/jira-flickers.mjs A xwiki/scripts/routine-setup.sh A xwiki/skills/xwiki-ci-check/SKILL.md A xwiki/skills/xwiki-ci-check/routine-prompt.md A xwiki/skills/xwiki-ci-check/tools/ci-check.mjs A xwiki/skills/xwiki-ci-check/tools/commit-comment.mjs A xwiki/skills/xwiki-ci-check/tools/matrix.mjs A xwiki/skills/xwiki-ci-check/tools/privatebin.mjs M xwiki/skills/xwiki-release-test-triage/SKILL.md M xwiki/skills/xwiki-release-test-triage/tools/triage.mjs Log Message: ----------- Merge pull request #142 from xwiki/ci-check-skill [Misc] Add the xwiki-ci-check skill, the daily acting CI sweep Compare: https://github.com/xwiki/xwiki-dev-llm/compare/1d5332d0601c...8abc00ac5c69 To unsubscribe from these emails, change your notification settings at https://github.com/xwiki/xwiki-dev-llm/settings/notifications