The two tags
You add one tag. Qoffee adds a second, rewrites it as the job moves, and removes both at the end. This page exists because IBM only allows five tags per job, so you should know how many are being spent on your behalf.
What a job carries over its lifetime
| Moment | Tags on the job | Count |
|---|---|---|
| You submit it | qoffee | 1 |
| Qoffee sees it queued | qoffee, qoffee@Q | 2 |
| It starts running | qoffee, qoffee@R | 2 |
| It fails and you are told | qoffee, qoffee@F:1755835200 | 2 |
| Tracking ends | qoffeed | 1 |
Your own tags are read and written back on every update, so nothing you added is lost.
The resolved tag is stripped too if you re-track the job later, because otherwise qoffeed would sit there forever burning a slot you did not know was scarce.
What the second tag means
| Tag | Meaning |
|---|---|
qoffee@I | Initializing, and you have been told. |
qoffee@Q | Queued, and you have been told. |
qoffee@R | Running, and you have been told. |
qoffee@U | A status Qoffee does not recognise, and you have been told. |
qoffee@F:1755835200 | Failed, and you have been told. The number is a Unix timestamp, used only by FAILURE_AUTOCLEAR_HOURS. |
| no second tag | Tracked, never reported. This is also what a job tagged by an older version looks like, which is why old jobs keep working. |
On every run Qoffee compares the job's real status against the letter in that tag. Same, and it stays silent. Different, and it tells you, then rewrites the tag. That comparison is the entire reason you are not pinged every fifteen minutes about the same queued job.
Why the failure code carries a timestamp
ERROR and CANCELLED both collapse to F.
Which of the two it was is re-read from IBM on every run, so it does not need storing.
The timestamp is there only so the autoclear safety net has something to measure from. If the tag was written by an older version and has no timestamp, Qoffee backfills one silently on the next run and does not treat that as news.
Why you cannot rename the tracking tag
TRACKING_TAG is in settings.py but it is below the line marked as not a user setting, and it is the only value there that people ask about.
The reason is arithmetic. A pinned failure is written as <TAG>@F:<10-digit epoch>, which is 13 characters on top of the tag name, and IBM caps a tag at 24.
Anything longer than 11 characters cannot be encoded.
The failure state would then silently fail to persist, and the job would be reported as newly failed on every single run, forever.
Making it configurable would mean handing you a setting whose failure mode is an infinite notification loop with no error message.
Use name: labels to distinguish your jobs instead.
The encoding lives in qoffee/providers/ibm.py and the constants in qoffee/settings.py.
The separator, the prefix and the caps are all in one place.