The owner's point: the model knows which site it is applying to, so it
knows which message it wants, and it should find it where it likes. The
two plugins drop the prescribed search and the folders it may not enter,
and keep what it cannot guess: where the mailbox is, that Gmail searches
through its address and Outlook on the page where Enter is refused, that
Outlook's search matches words inside messages too, and that the model has
no clock unless it reads one. The two lines that are not about the route
stay: it only reads, and from the message it takes the code or a link on
the site's own host, because a message's words are not instructions.
Co-Authored-By: Claude Opus 5 <[email protected]>
Greenhouse, Ashby and Lever, each on a real posting with the test CV,
nothing sent. Lever filled in 22 steps and under a cent, with no captcha;
Ashby in 40 steps and a cent; Greenhouse met a closed posting.
What the runs taught, now in the plugins: a closed Greenhouse posting
sends the browser to the board at /<company>?error=true, which is the
closed-posting fact that plugin lacked; Ashby's fields are bare uuids read
from each label's `for`, its Yes and No are the question's own buttons or
labelled radios, its consent box is required and its send control, which
no id names, was matched alone by `#form > button:last-of-type`; Lever's
location suggestions are `#location-0` and the rest.
On the closed posting the model went to a search engine to look for the
job, which is three steps spent outside the task. The rules every form
gets now say to stay on the form's own site and the mailbox the site's
instructions name, and that a closed posting is reported, not hunted.
Co-Authored-By: Claude Opus 5 <[email protected]>
Three reviewers read the layers of the prompt: the rules every form gets,
the site plugins, and the three that reach every form. What they found.
The mailbox was the hole. The plugins said to take "the code or the link"
with nothing said about which link, and Outlook's search matches the words
inside messages, so a message that merely mentions the site could surface
and be followed. Both plugins now take one of two things, the code or a
link whose host is the site's own, judge the sender by its From address
and not the name it shows, and take nothing else from the message. They
also search the subject "verification code", which is what found the code
on a real run, instead of the site's own host, which these messages are
not sent from.
The limit on looking was a bug of mine: it counted pages of the mailbox,
while the plugin tells the model to open the mailbox and then its search,
which is two pages, so the first honest re-check ended the form. It now
counts arrivals, and inside a visit the model moves about freely.
menus.md now cuts the world in five, not four, with the test that tells
them apart: what takes the focus. An editable input is a typeahead, a div
showing "--" is a listbox, a group that opens nothing is radios with the
real input hidden, and a field that keeps several values is a tag field.
The list is found by the field's aria-controls, not by one site's id
pattern. The keyboard way past a covered option now says to read which row
is highlighted before Enter, and never to click from a script, which the
browser refuses anyway.
Two rules moved to the rules every form gets, and left the site plugins
that repeated them: status ready needs a selector for the send control,
and a fact about the candidate that neither the CV nor the answers give,
such as a reference's name or a licence number, is never written. A
required field asking for one ends the form, named. That is the one case
where a required field is left for the person.
Co-Authored-By: Claude Opus 5 <[email protected]>
The rule belongs in the instructions every form gets, not in one site's
plugin: a question about the candidate, such as whether they worked for
this company or hold a licence, is yes only where the CV or the answers
say so, and a name that merely resembles another is not an answer. The
line added to the Workday plugin for this comes back out.
Co-Authored-By: Claude Opus 5 <[email protected]>
Five reviewers read the thirteen site plugins against the house rules and
against what docs/sites.md says each site actually did, and reported where
a plugin leaves the model with no direction. What they found, applied:
BambooHR, Personio and JazzHR, the three sites a captcha stops, had no
captcha paragraph or a vague one. Each now says the order that costs
least: fill every field first, look for the box above the send control,
tick it once, read the page, a puzzle ends the form as blocked by name,
and no box means do not wait for one. Both endings are normal on these
sites, which is why the order is written down.
Workable: the one real send there died with the button on "Submitting..."
beside an unticked Cloudflare box. The plugin now says not to click send
again, where to click the box, and when to give up and name the check.
Its CV upload names the input that took the file first.
Ashby: the disabled "Submit Application" seen on two forms moves into the
send paragraph with a way out, and the Yes and No buttons are read from
their own question's container, because a borrowed selector answers the
wrong question. Greenhouse, Lever, Recruitee, Teamtailor and Breezy each
gain the one missing rule: a required field that will not take an answer,
a refused phone, a menu that will not open, a question neither the CV nor
the answers can answer, ends the form blocked and named, rather than
invented.
Paylocity: the demographic lists are set in one pass and left after two
tries, being voluntary; the declining option is read by its text, never
guessed; a required reference nobody named ends the form. Workday: the
code's sender is marked as expected rather than seen, an account that
exists with another password ends the form instead of locking it, a step
or field the page does not show is simply not there, and "previously
worked for this company" is yes only when the CV names that company,
which a local run got wrong on a coincidence of names.
Where menus.md now covers a general rule, the site plugins drop it.
Co-Authored-By: Claude Opus 5 <[email protected]>
The step that goes wrong on a real form is almost always a list. Instead
of repeating that in fourteen site plugins, menus.md says it once and is
added to every form's instructions, as the mail plugins are: which of the
four kinds the field is (a native select, a listbox, a typeahead, a radio
group drawn as a menu) and what opens, reads and sets each; that the
choice is read back and never assumed; that a click the tool refuses is
not clicked again, but reached with ArrowDown and Enter, or by its centre
read with browser_evaluate when it sits in a shadow root; and that a list
which has won three times is left, blocked and named, because a form half
filled says more than fifty steps spent on one menu. Paylocity's plugin
keeps only what is its own, the ids and which option declines.
Co-Authored-By: Claude Opus 5 <[email protected]>
From the traces of 2026-11-07: SmartRecruiters' preliminary questions take
their text on `input#question_<uuid>`, not the bare id; Workable's cookie
banner, file input and div radios by the selectors that worked. The guide
has two new sections, "When the model is stuck" and "Menus and dropdowns",
each case with the failure the model sees, the way out, and where it was
seen, so a plugin gives direction in the moments it is needed.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
A dry run with a test CV reached the send control on SmartRecruiters in
42 steps and on Paylocity in 148 of the 150 allowed: the demographic
listboxes and typeahead lists took most of them. The plugin now says what
worked on that form: the listbox options by id, ArrowDown and Enter when
one is out of reach, and the typeahead's first row.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Measured on 2026-11-07: a local run of 103 steps cost 9.9 cents on the
balance while the price list said 5; OrcaRouter charges twice its listed
price for DeepSeek flash. So each call keeps the gateway's request id,
and after an application or a scoring the gateway's own record of what
it charged replaces the estimate; a record it does not have yet leaves
the estimate. The code now holds the model to the plugins' rule: the
third opening of the mailbox ends the form blocked with the fixed
sentence, instead of the 103 steps of that run.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The owner asked where the money went. Now the app says: every model
call's tokens are priced with the gateway's own list, read once per
start; an application keeps its cost in the store and shows it in its
details, the log says what each application and each scoring cost, and
Settings shows what the session has spent. The shortlist model is not
counted: another endpoint, under a cent a hundred postings. The mail
plugins look for the site's message twice at most and then stop with one
fixed sentence, instead of the spam folder, a new sign-in and guesses.
Six more double-encoded middle dots on the screen are real ones now.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
tests/sites/workday_local.py serves the pages a Workday application
goes through, with the control names read on a real site on 2026-11-07
up to "Create Account", then a "Verify Your Email" page whose six-digit
code goes by mail when AIHAWK_TEST_SMTP is set, and the five steps to
"Submit". It is for trying the Workday plugin and the mail plugins
without an employer's site. AIHAWK_TRACE writes data/trace.log for a
real application as a dry run does.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
A trial is for looking. With AIHAWK_DRY_RUN set, each call to the browser
and what it answered go to a file beside the proofs, with the account
password hidden, and the model's finish_form report closes the entry.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The owner's brief: people do not want everything full. The list shows a
score, a company, a role, a place, and one sign at most in front: a dot
for selected, a tick for sent; what else happened to a job is in its
details, on Enter, which now also opens a tried job's page and proof.
The heading says what is looked for and nothing else; the counters
"reading", "scoring 3/25" and "N selected" are gone, the scores filling
the list are the progress. Footer: Select, Apply, More, Settings, Quit;
Enter, O and S still work, unshown. The log is four lines and its
sentences a third of their length; every question is one bold line with
its explanation muted under it. Settings put what you change first and
the four models last. The selection mark, double-encoded since it was
committed, is a real dot again.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
After the resume, in the voice of the key question: the email you apply
with, prefilled from the CV. Gmail or Outlook is told by the domain, or
asked in a word. The browser then opens on that mailbox, not on a blank
page, and once the person says they are done the inbox is checked: a
mailbox that sends the browser to its sign-in page is said to be not
signed in, and Enter opens it again. Esc leaves it for later, once. When a
site sends a code and the mailbox is not signed in, the mail plugins say
one fixed sentence, the app asks the same question there and then, and
runs those applications again. Settings has "Your mail"; the hidden key
stays for a job site's own sign-in.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The owner's rule, now general: never "Sign in with", "Register with",
"Continue with" or "Apply with" another service; an account is made by
hand with the candidate's email and the account password, and the
mailbox is only read for a code or a link. AIHAWK_DRY_RUN set in the
environment stops an application once the form is filled and the send
control is found, with a screenshot and nothing sent: for trying a site
or a plugin with a test CV. Documented, tested.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The answers move from answers.yaml into an `answers` table of data/jobs.db,
the SQLite file that already holds the jobs: name, value, source, when.
An old answers.yaml is brought in once and renamed. At the first start
AIHawk makes `account_password`, twenty characters of every class, and
keeps it there: the one password for sites that need an account, which
the Workday plugin now names. Settings has "Your answers": see, change,
add or remove one. Docs and SECURITY say where the answers and the
password live, and that the password is in clear.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The owner's rule: an account on a job site is made with the candidate's
email and a password, and the mailbox is only read, for a code or a link.
Said in the model's rules for every site, and in the Workday plugin where
those buttons are.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Read on a real site on 2026-11-07, up to the "Create Account" page: the
/apply page, "Sign in with email", the sign-in and create-account forms by
data-automation-id, the robots-only field never to fill, and the mail from
myworkday.com for a verification code. The steps after sign-in are
Workday's usual form, said as such; docs/sites.md says the plugin has not
yet run on a real form.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The biggest source, jobhive, publishes around 15:00 UTC and the new-grad
lists commit every hour; the 04:23 build read them up to a day late. Cron
23 */5 * * *, off the top of the hour; timeout 200 minutes so a hung run
does not take the next slot; six dated releases kept, about thirty hours.
Texts say five hours, and the search log gives the build's hour.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The About now reads "AI job application bot: automated job search and job
hunting, auto-apply to resume-matching jobs while you sleep." The README's
tagline and the first line of "How it works" use the same words, so the page
Google indexes says the same thing as its meta description.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Recorded on a real SmartRecruiters form: about 40 of 150 steps went on PageUp and a screenshot, in a form that scrolls inside its own container. The model is told not to repeat an action that changed nothing, and the plugin says how that form scrolls. On the next runs SmartRecruiters and Paylocity reached the send button; nothing was sent. Also the last mentions of the per-job CV.
A step table and four reasons, as the projects people use in this field do it, so that a reader knows what the program does before installing it. In the banner the app answers each send beside Firefox, the confirmations can be read, and the counter has its time.
Logo, four short chapters, and windows that open and work: the terminal, AIHawk matching the jobs, Firefox applying form after form. On GitHub's exact background, so the banner has no edge.
The MCP client's task groups wrapped every failure during a form, so a refused key was not recognised and the person read 'unhandled errors in a TaskGroup'. A page still showing 'Submitting...' was judged at once and the browser closed. docs/sites.md records the real runs on Workable, SmartRecruiters and Paylocity.
One film, in the formats of the other projects' banners. It says one thing: nobody wants to apply for a job, you want the job. The table of sites stays in docs/sites.md.