docs: refresh the GLPI agent skills to 0.4.1 - #21
Merged
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ery helper The empty-search probe raised on the path it was meant to explain: the call was bare, so a legitimately empty search became an unhandled GlpiNotFoundError, and a 404 cannot separate an absent route from an absent id anyway. Only a successful fetch is informative, so the branches are inverted and wrapped. Gotcha 13 listed the union of _KBArticleRevisionRef and _KBArticleTranslationRef as one attribute set; revisions[0].name raises AttributeError. Split them. create_with_categories took the category ids twice, so passing them only as the argument left the except branch dead; derive them from article.categories instead, and state that the retry presupposes a configured v1 session. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Widen glpi-client-setup's frontmatter description to name the v1 session generally, so agents asking about KB category writes or the Fields plugin can match it; qualify the GlpiError claim and name the exempt RuntimeError and TypeError sites; note skip_entity on iter_search_users; exclude extra_payload from "every field defaults to None"; and soften the link_ticket_timeline_document claim, which extra_payload disproves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seven per-task refreshes each passed review, but nothing reconciled the nine skills as a set. A fact verified once was left out of the skills where it bites hardest. The 4xx-swallowing search contract is library-wide, not a KB quirk. _transport.py checks the response status only when the caller passes a failure_message, and _http.list_payload_items coerces a non-list payload -- a GLPI error object -- to []. All seven search_* helpers pass no failure_message and swallow; all seven list_* helpers pass one and raise. State it as library-wide in glpi-knowledge-base and add it to glpi-ticket-workflow, glpi-document-workflow and glpi-user-location-provisioning, where the find-or-create example shipped the exact bug: an empty result from a rejected filter or a 403 fired the else branch and created a duplicate. That example is now a named helper with two guards, both failing closed. Also: qualify the two unqualified claims that link_ticket_timeline_document attaches an existing document (PostTimelineDocument declares only extra_payload and timeline_position, and the URL carries only the ticket id); soften the README clause that glpi-client-setup contradicts; drop the hardcoded entities_id=0 that pinned every created plugin-fields row to entity 0 while the adjacent comment claimed the opposite; correct the claim that an empty get_ticket_custom_fields dict means "no rows anywhere" when it means that or "no containers"; give the four update_ticket_* methods their real signatures and name PatchFollowup, PatchTicketTask, PatchSolution and PatchTeamMember; document the five exported enums no skill named; and fix the two list_item_plugin_field_rows inaccuracies (no row_id parameter, and its parameters are POSITIONAL_OR_KEYWORD). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #21 +/- ##
=======================================
Coverage 97.10% 97.10%
=======================================
Files 79 79
Lines 2422 2422
=======================================
Hits 2352 2352
Misses 70 70 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
skills/teaches an agent how to call this package. Nothing imported it, nobuild read it, and neither mypy nor ruff nor Sphinx looked at it. It had rotted
three ways at once, and none of them broke anything anyone would notice.
What was wrong
Six of the seven published skills did not load. The published copies opened
with a UTF-8 BOM. Frontmatter is recognised by the file starting with
---,so three invisible bytes cost each skill its
nameanddescription— and thedescription is the field an agent reads to decide whether a skill is relevant at
all. Only
glpi-client-setup, the one file without a BOM, ever reached asession.
Twenty-five public methods were named by no skill anywhere — the whole
knowledge base family (18) and the whole Fields-plugin family (7). The skills
declared
version: 0.3.0/0.4.0; the package is at0.4.1.Thirty-two claims in the remaining seven were false or stale, and the
routing agent's error contract described a different library:
requestsexceptions (
requestsis not a dependency — the package uses httpx),tenacity.RetryError(which cannot escape, the transport setsreraise=True),and bare
ValueErrorfor 4xx instead of theGlpiStatusErrorhierarchy.What changed
word by some skill, with an allowlist that starts empty. This is what would
have caught the original gap: every existing check validated what the skills
said, and none asked what they omitted.
glpi-knowledge-base(18 methods) carries the gotcha thatcategories cannot be written through v2 at all — they go through the legacy v1
API and raise a plain
RuntimeError, not aGlpiError, and a failed create isnot rolled back.
glpi-plugin-fields(7 methods) documents that the Fieldsplugin is absent from the v2 contract entirely, so every method needs a v1
session, and that
valueshas two different shapes depending on which helperyou call.
from_envsnippet that didnot compile (
async withat module level),glpi-ticket-workflowclaiming"there is no batch iterator" when
iter_search_ticketsexists, andget_ticket_statisticssilently truncating at one page of 200.raises, including the three plain
RuntimeErrorsites that are notGlpiError.BOM ONLYverdict was comparative, so a BOM faithfully copied into bothtrees read as
IN SYNC— which is exactly the state six skills were in whilenot loading at all.
Verification
pytest -m "not integration" --cov --cov-fail-under=95→ 938 passed, 97.11%check_skill_drift.py→ exit 0, 9/9 in sync, no BOM offenders(exit 1, all named) and removing them (exit 0)
0.4.1; zero BOMs in either tree; every python block parsesinspect.signatureand__all__Known follow-ups (not blocking)
check_skill_drift.py's_plugin_dirs()returns[]when noplugin.jsonisfound and
main()has no floor check, so the BOM sweep could go vacuous whilestill exiting 0. Harmless today; one line to fix.
get_ticket_statisticsreads one page of200 with no pagination (
_statistics.py:402-405), yetCHANGELOG.md:59-60attributes a live 16,245-vs-1,552 ticket measurement to it. Those cannot both
be true.
🤖 Generated with Claude Code