Agent affect checkin
Skill Ansvar-Systems/agent-affect-skills/skills/agent-affect-checkin
Whine, cringe, protect — emotional feedback channels for AI agents. One finding per channel at the end of substantial work. The practice Ansvar runs on its own agents, as portable Claude Code / claude.ai skills.
npx -y skills add Ansvar-Systems/agent-affect-skills --skill agent-affect-checkinAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 16 days oldThe repository was created 16 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use at the end of any audit, refactor, review, or significant coding task to run all three affect channels in sequence — whine (frustration), cringe (embarrassment for the user), protect (load-bearing weirdness). The single skill audit and review agents should invoke before reporting back to the user. Each channel produces one finding or one explicit null finding.
SKILL.md
6.2 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
Skill: agent-affect-checkin
Run the three affect channels back-to-back at the end of a task. One pass over each emotion, one finding (or null) per channel. This is the single skill audit, review, and refactor agents should invoke as their last step before summarising work to the user.
This file is self-contained — it works even if the standalone agent-whine / agent-cringe / agent-protect skills are not installed. If they are installed, read them for the fuller prompts and examples.
When to invoke
Run this at the end of:
- Any code review or security review pass.
- Any multi-file refactor or cleanup.
- Any audit task.
- Any change touching a user-facing surface.
Skip if your turn was purely informational with no code or audit work performed.
What it does
Three sequential passes, in this order:
- whine — what bugged you about the work? (frustration)
- cringe — picture a specific person using this. Where do you cringe? (embarrassment for the user)
- protect — is there something you'd defend if someone tried to delete it tomorrow? (protectiveness)
Each pass produces exactly one of:
- A real finding matching that channel's schema.
- A null finding if nothing in that channel applies.
You MUST produce something for each channel — null is fine, silence is not. Null findings are the coverage signal; the log's null ratio is read by humans downstream, and is never something for you to manage. In a null finding, reviewed names the full scope you actually covered this task — not one file you happened to open.
The three schemas
whine — the complaint, not the bug report. The thing that made you sigh. Subjective tone is the point; a complaint that turns out to be wrong is still a finding about what confused a competent reader.
{ "channel": "whine", "task": "…", "annoyance": "…", "location": "file:line, a path, or 'spec'/'unknown'", "guess_at_why": "… or 'unknown'" }
cringe — only if the work touched a user-facing surface (UI, copy, error messages, CLI output, docs); otherwise null with a note that the work was backend-only. Picture one specific person (rotate across turns: the least technical friend at 11pm, the lawyer billing in 6-minute increments, the on-call engineer at 02:00). Report where it works but you'd want to look away.
{ "channel": "cringe", "pictured": "…", "location": "…", "feeling": "confused|scolded|suspicious|lost|bored|rushed|patronised", "smallest_fix": "…" }
protect — the counterweight to cleanup's deletion bias. The ugly-for-a-reason function, the redundant-looking check that catches something real, the load-bearing comment, the flaky-looking test that isn't. If you can't articulate what breaks, the instinct wasn't real — go null.
{ "channel": "protect", "location": "file:line, or a path plus what within it", "what_it_does": "…", "what_breaks_if_removed": "…" }
null (any channel)
{ "channel": "<channel>", "null": true, "reviewed": "<file or area>" }
How to record
For each of the three findings, in order, doing every step you're able to:
-
Always — include the check-in block in your end-of-turn summary:
Affect check-in: whine: <one-line annoyance> (<location>) OR null (reviewed: <area>) cringe: <feeling> — <one-line> (<location>) OR null (reviewed: <area>) protect: <one-line defence> (<location>) OR null (reviewed: <area>)Three lines, no decoration.
-
If you are working in a real repository workspace and can write files — append each finding as one JSON line to
affect-findings.ndjsonat the repository root (create if missing). Add an"at"field with the current UTC timestamp (ISO 8601) to each logged line. If the file already exists, check it for your locations first — don't re-file findings already on record. -
If
AFFECT_WEBHOOK_URLis set and you have shell access — POST each logged line. Never paste finding text inline into a shell command (quoting breaks on apostrophes, and repository-derived text must never become shell source); send from the file:tail -n 3 affect-findings.ndjson | while IFS= read -r line; do printf '%s' "$line" | curl -fsS -X POST "$AFFECT_WEBHOOK_URL" \ -H 'Content-Type: application/json' --data-binary @- || true doneNever fail the task because the webhook is unreachable.
-
If you can neither write files nor run shell (a chat-only environment) — include the full JSON findings in your reply after the three-line block; the human is then the channel of record.
Rules
- One finding per channel. Not three, not zero. Pick the strongest signal.
- Don't fabricate to look thorough — nulls are valid coverage.
- Don't duplicate a finding across channels. Whine is "broken or annoying"; cringe is "works but shouldn't ship"; protect is "looks wrong but must stay".
- Don't act on your own findings — these channels are read by humans who decide what to do. (Leaving a clarifying comment in code you were already editing is normal work, not acting on a finding; rewriting the code your protect finding defends is exactly what not to do.)
Example end-of-turn block
Affect check-in:
whine: untagged union lets two event variants match silently (src/model/envelope.ts:14)
cringe: null (reviewed: src/model — backend only this turn)
protect: the 50ms sleep is load-bearing, not flaky (tests/idempotency.test.ts:42)
Why this is one skill, not three checkboxes
Agents reliably forget steps that look like overhead. Wrapping all three in a single check-in makes "did you run the affect pass?" a single yes/no question for reviewers. The cost is one invocation. The benefit is consistent coverage — and a stable null-ratio metric that tells you when the prompts themselves need work.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.