Imported from ashita-planning/laravel-error-monitor-github (
AGENTS.md). Install upstream withnpx skills add ashita-planning/laravel-error-monitor-github. Copyright stays with the author.
AGENTS.md
Rules for anyone - person or agent - working in this repository.
What this package is
The GitHub Issue adapter for ashita-planning/laravel-error-monitor. It files
failures the core package found, and does nothing else.
ashita-planning/laravel-error-monitor log analysis, aggregation, contracts
ashita-planning/laravel-error-monitor-xserver XServer stored log retrieval
ashita-planning/laravel-error-monitor-github GitHub Issue publishing <- this one
Never add to this package
Log parsing, fingerprint generation, masking, daily aggregation, or anything that reads a log file. Those belong to the core and duplicating them here would guarantee the two drift apart.
Idempotency comes first
GitHub's issue creation endpoint takes no idempotency key. Every rule below exists because of that, and none of them are negotiable.
- Never retry a POST or PATCH inside the client. A
ConnectionExceptionon a write is handed back to the caller, because only the caller knows how to check whether it landed. The client may retryGETfreely. - After a failed write, confirm the side effect before retrying. Re-read the issue list, the comments, the issue state or the labels - whichever the write would have changed - and only send it again once it is known not to have happened.
- Never recover a lost write through the Search API alone. The search index is eventually consistent, so "not indexed yet" and "never created" look identical through it. Read the repository's issue list, which is not.
- Never choose between issues. If two issues carry the same fingerprint marker, stop and report it. Picking one orphans the other.
- Look inside the lock. The gap between checking and creating is what a distributed lock exists to close; a check made before waiting for the lock is stale by the time it matters.
What may fail, and what may not
- Reopening a closed issue and posting the recurrence comment are required.
If either fails, return
failedso the core records nothing and the next run resumes from wherever it got to. - Adding the
regressionlabel is best effort. It is supporting detail, and failing the whole publication over it would leave the state worse: the next run would find an open issue with a comment already posted and never return to the labelling path. Record the outcome in the result metadata and log it. - If the label ever has to become mandatory, add a persistent
label_pendingstate first. Do not simply make it fatal.
Secrets
Never put a token, an Authorization header, an issue body or a whole response
body into an exception, a log line, a status output or a test failure message.
GitHub error bodies can echo the request back, and the request carried the
token. Read the response's message field and nothing else.
Tests
Every test runs against Http::fake(). No test may reach GitHub.
Keep fake URL patterns narrow. */issues?* also matches /search/issues?q=,
and because Http::fake() evaluates every stub eagerly, a loose pattern lets
one request advance another stub's response sequence. Use
*/repos/*/issues?* and the like.
Sleeper and Clock are contracts so tests can assert the exact wait sequence
without spending it. Never call sleep() or now() directly.
Changes
Update CHANGELOG.md and the tests in the same change as any public API change.
If the core's contracts need to change, open an issue or PR on the core
repository - do not work around them here.
Do not use Closes, Fixes or Resolves against the core repository's issues
in a commit message or PR body.