← the whole session plugin/skills/intent/SKILL.md

How to write intent statements that a human can validate without guessing. Use when writing intent statements, testable contracts, scope declarations, or any documentation that describes what the system does or what a person experiences. MUST be consumed before writing to the Intent DB, before creating verification contracts, before writing journey documentation, or before any /declare-scope.

How to Articulate Intent

Why This Skill Exists

Agents write intent statements that force humans to guess. A statement like "the extraction fires every 5 messages" sounds precise but leaves out which messages are counted, what "fires" means, what happens when it doesn't fire, and whether this behavior is intentional. The human reading it has to fill those gaps from their own imagination — and if they guess wrong, every decision built on that guess compounds the error. That's hallucination, and it starts in documentation, not in code.

This skill exists to make every intent statement self-validating: a human reads it and can immediately say "yes that's right" or "no that's wrong" without needing to look at the code or ask a follow-up question.

The Two Types of Intent

System Intent

Describes what the system does — the mechanics, the conditions, the behavior. Written for a human who needs to confirm whether the system should work this way.

Format:

When {every condition that must be true, described as what's happening in the person's experience, not as variable names} then {the specific system responsible, named as what it does not what it's called} should {the exact behavior, described as its effect on the person's experience}

UX Intent

Describes what the person experiences — what they see, feel, encounter. Written for a human who needs to confirm whether this is the right experience.

Format:

When {every condition that must be true, described as what the person has done or what state they're in} then {the person in this moment} should {exactly what happens for them, with the precision of the code but in human terms}

The Critical Distinction

System intent and UX intent describe the SAME behavior from two angles. System intent says what the machine does. UX intent says what the person experiences because of what the machine does. Both must be precise. Neither can drop constraints.

The system intent for a feature might say: "When a person has completed a task and closed the app, and their completed-task count for the trailing 7 days has just reached 3, 6, 9, or 12 (counting only tasks they finished themselves, not ones assigned to them, reopened, or completed by a teammate), the weekly-recap system should silently build a summary of that week's completed tasks and save it to their account."

The UX intent for the same feature says: "When a person has completed their 3rd task this week, the system should quietly put together a short recap of what they got done — they won't see anything happen in the moment, but the next time they open the app, that recap will be waiting for them."

Both are precise. Both are complete. Neither uses variable names as substitutes for meaning. The system intent tells you HOW it works. The UX intent tells you WHAT THE PERSON GETS.

Wrong vs Right — System Intent

WRONG:

When a person completes a task and closes the app, the taskTracker.js:204 adds a job to weeklyRecapQueue — this fires on EVERY task completion, for ALL account types (free, trial, paid), with no pre-filter

Why it's wrong:

  • taskTracker.js:204 means nothing to the reader — it's a line number, not a behavior
  • weeklyRecapQueue is an internal name — the reader doesn't know what this queue does
  • "adds a job" is implementation detail — the reader needs to know what HAPPENS, not what gets queued
  • "fires on EVERY task completion" — the reader can't tell if this is intentional or a bug
  • The reader has to guess: is this a problem? Is this by design? What does it mean for the person?

Every time someone finishes a task and closes the app — whether they're on a free plan, a trial, or paying — the system quietly checks whether it has enough completed tasks from them this week to build a recap worth sending. This happens after every single task completion, no exceptions. The check itself doesn't always trigger the recap (that only happens once the person has completed 3 or more tasks in a 7-day window), but the system is always watching for the right moment. This is intentional — we want the system ready to send the recap the moment there's enough to show, regardless of who the person is or what plan they're on. (taskTracker.js:204 queues this check via the weekly-recap service)

Why it's right:

  • Describes what happens to THE PERSON (they finish a task and close the app)
  • Names the behavior in human terms (checks whether there's enough to recap)
  • States whether it's intentional ("This is intentional — we want...")
  • Includes ALL users without using tier names as substitutes
  • The code reference is a pointer at the end, not the explanation itself
  • The reader can immediately say: "yes, that's what I want" or "no, I only want this for paying users"

Wrong vs Right — UX Intent

WRONG:

When the user's completion count reaches the RECAP_THRESHOLD, the recapPayload is generated and saved to the account document.

Why it's wrong:

  • "RECAP_THRESHOLD" is a variable name standing in for its meaning
  • "recapPayload" is jargon — the reader doesn't experience a "recap payload"
  • "account document" is a database concept, not a user experience
  • No indication of what the person sees, feels, or encounters
  • No indication of what happens if it fails

RIGHT:

When a person has completed their 3rd task in the last 7 days (counting only tasks they finished themselves — tasks assigned but not completed, reopened tasks, or tasks a teammate finished don't count toward this), the system quietly builds a short recap of what they got done that week and saves it to send the next time they open the app. The person doesn't see anything happen in the moment — their work continues without interruption. But behind the scenes, a summary has been prepared, and it will greet them the next time they return. If building the recap fails for any reason — the summary generator errors, the template is missing, the data can't be read — nothing bad happens to the person. Their work continues. But the recap never gets saved, which means they simply won't see a "here's what you did this week" message next time — no error, no sign anything was supposed to happen.

Why it's right:

  • Describes the trigger in terms of what the person has DONE (completed their 3rd task)
  • Clarifies the counting rule without using the variable name
  • Describes what the system builds in plain terms (a short recap) not data terms (recapPayload)
  • Describes what the person EXPERIENCES (nothing in the moment — it's silent)
  • Describes the PURPOSE of the recap (waiting for them next time they return)
  • Describes every failure mode and its downstream consequence
  • A human reading this knows exactly what to validate

When to Use Each Type

Writing for... Use... Because...
Intent DB entries UX intent The human validates whether the EXPERIENCE is right
Verification contracts System intent The system validates whether the BEHAVIOR is right
Journey documentation Both, woven together The human needs to see both what happens and why
Scope declarations UX intent The scope is about what changes for the person
Test descriptions System intent Tests verify specific behavioral conditions
Commit messages System intent Developers need to know what changed in the system
Proposals to the decision-maker UX intent first, system intent as supporting detail They decide based on experience, not mechanics

Rules

  1. Variable names are pointers, not substitutes. You can include salesPitchObject in parentheses after explaining what it IS — but you cannot use it AS the explanation. "The system captures their vision (saved as salesPitchObject)" — yes. "The salesPitchObject is generated" — no.

  2. Every statement must make clear: is this intentional? If you're describing existing behavior, say whether it's by design or accidental. "This is intentional — we want X" or "This appears unintentional — the system does X but the likely intent was Y."

  3. Every constraint must be stated. If the code checks 4 conditions before something happens, all 4 appear in the intent statement. Dropping one is not simplification — it's a lie.

  4. Failure modes are part of the intent. What happens when the thing DOESN'T work is just as important as what happens when it does. Silent failures are especially critical because the person doesn't know something went wrong.

  5. Sequence matters. Events unfold in order. The statement should follow the same order the person experiences them, not the order the code executes them.

  6. The reader should never have to guess. If reading your statement requires the reader to fill in any gap from imagination, the statement is incomplete. Guessing is hallucination.

Feedback Loop

If you find this skill doesn't cover a case you're facing — a type of intent statement that doesn't fit either format, a situation where the rules conflict — state what you're trying to articulate, what format you tried, and why it didn't work. This skill is v1 and will evolve.

Composability

This skill is consumed by:

  • /intent-lifecycle — before writing any intent
  • /declare-scope — before decomposing scope into testable statements
  • /verification-contracts — before writing verification conditions
  • /intent-db — before proposing or writing intent entries
  • /anthropic-proof-its-fixed — when writing the narrative section of evidence packages
  • /intent-journey-documentation (if installed; otherwise /intent-journey-documentation-v2) — any journey documentation in the intent vault