infer-status
Resolve the canonical application status from signals (triage class + current status + days-since-apply / days-since-last-contact + optional portal state) using the taxonomy decision table. Emits {status, next_action, next_action_due_on, rationale}; optionally updates a flat tracker.json. Honours the offer-accept guardrail and the ghosting rule.
- License 许可
- MIT
- 最近更新
- 2026-06-09
- Stars
- ★ 7
- Forks
- 1
01 前言 Front Matter
- name
- infer-status
- description
- Resolve the canonical application status from signals (triage class + current status + days-since-apply / days-since-last-contact + optional portal state) using the taxonomy decision table. Emits {status, next_action, next_action_due_on, rationale}; optionally updates a flat tracker.json. Honours the offer-accept guardrail and the ghosting rule.
- when_to_use
- Use after triage-inbox classifies new emails, before draft-reply chooses an intent template, or any time the user wants to refresh the funnel state for one or many applications.
- allowed-tools
- Read, Write
- user-invocable
- true
03 SKILL.md 正文
infer-status
Map signals → status using the taxonomy decision table — no invention. Hard rules: ../_shared/RULES.md. All enums, the decision table, the ghosting rule, and the offer-accept guardrail live in ../../knowledge/status/taxonomy.md.
Inputs
Per-application signals (JSON; single or array)
{
"job": { "company": "...", "role": "...", "job_id": "..." },
"current_status": "applied | screening | assessment | interview | final-round | offer | accepted | rejected | withdrawn | ghosted",
"triage_class": "rejection | screen | interview-invite | assessment | offer | recruiter-outbound | info | request-info | spam | other | null",
"days_since_apply": "number | null",
"days_since_last_contact":"number | null",
"portal_state": "string | null", // verbatim portal label if scraped, e.g. "Application Rejected"
"as_of": "YYYY-MM-DD"
}
Or --in inbox/triage-<date>.json to read triage records directly; the skill joins triage → applications by (company, role) or job_id and pulls current_status from tracker.json if present.
Flags
--ghost-days N— override the 14-day ghosting threshold.--update tracker.json— write the new status back intotracker.json(only fields that changed).--confirm-accept— the only way to transitionoffer → accepted. Without it, an offer stays atoffer.
Method
-
Read the taxonomy decision table and the ghosting rule.
-
Resolve
triage_classif absent by reading the latestinbox/triage-<date>.jsonfor this job (if present). Otherwise skip the email branch and use only portal + recency signals. -
Apply the decision table.
(triage_class × current_status) → (next_status, suggested_action). Terminal email classes (rejection,offer) trump current status;info/request-info/spamnever change status. -
Override on portal signal if present. Portal labels are ground truth when they exist (e.g.,
portal_state: "Application Rejected"→rejectedregardless of email). Record the override inrationale. -
Apply the ghosting rule. If current_status is non-terminal AND
days_since_last_contact ≥ ghost_days(default 14): status →ghosted; action depends on funnel position (applied/screening →follow-up; interview/final-round/offer →escalate). -
Apply the offer-accept guardrail. Never transition to
acceptedautomatically. Without--confirm-accept, anofferstays atofferwith actionreply-ask. With--confirm-acceptand current_statusoffer, transition toaccepted. -
Compute
next_action_due_onbased on the action:reply-schedule/reply-info/reply-ask→ today + 1 business day.reply-accept(assessment) → respect the email'sdeadlineif any, else +3 days.follow-up→ today + 0 (nudge now).acknowledge/ignore→null.escalate→ today (route torequest-human-inputwith the optional JobClaw agent).
-
Write a rationale. One sentence per non-trivial decision (which table row fired, what triggered the override, what the ghosting rule did).
Output
Per-application result
{
"job": { "company": "...", "role": "...", "job_id": "..." },
"prior_status": "applied",
"status": "screening",
"next_action": "reply-schedule",
"next_action_due_on": "YYYY-MM-DD",
"rationale": "interview-invite × screening → final-round per taxonomy table; deadline 2026-06-02 noted",
"as_of": "YYYY-MM-DD"
}
Single input → object; batch input → array.
Stdout
Tight table: job · prior → next · action · due · rationale (truncated). Flag escalate rows + any status reverting (e.g., interview → ghosted).
Optional tracker update
With --update tracker.json: read JSON {applications: [{job_id, ...}]}; merge new status / next_action / next_action_due_on / last_status_change into the matching record. Don't overwrite fields you didn't compute; preserve user notes.
Anti-patterns
- Inventing a status from a noisy thread; default to
unchanged+acknowledgewhen signals are weak. - Treating
recruiter-outbound(cold inbound, no prior application) asscreening. - Transitioning
offer → acceptedwithout--confirm-accept. - Ignoring the portal signal when present.
- Using more than
--ghost-daysfor the ghosting threshold without recording it inrationale. - Emoji.
Rubric
- [ ] Status ∈ taxonomy enum; action ∈ taxonomy action enum.
- [ ]
rationalecites the table row or the override that fired. - [ ] No
acceptedwithout--confirm-acceptand a prioroffer. - [ ]
ghostedonly set whendays_since_last_contact ≥ ghost_daysAND current_status is non-terminal. - [ ]
next_action_due_onis set whennext_actionis reply-ish;nullwhen not.
Next steps
Status updated. Next: /draft-reply with the suggested intent (or /coach-negotiation if it's an offer).
04 同仓库更多 Skills
write-outreach
Write a short, profile-grounded cold outreach message to a recruiter, hiring manager, or potential referrer — LinkedIn DM or email — with one clear CTA and no flattery.
write-cover-letter
Produce a job-specific, profile-grounded cover letter in markdown — ≤ 350 words, ≤ 1 page, three paragraphs (hook → two quantified proofs → fit close). Reuses keywords from a prior tailor-resume sidecar when present. Writes a JSON sidecar reserved for a future /render-resume --kind cover-letter (rendercv).
triage-inbox
Classify a recruiting email (or a batch) into one of the 10 canonical email classes, extract structured fields (company / role / dates / links / asks / deadline / sentiment), and suggest the next action. Writes inbox/triage-<YYYY-MM-DD>.json — consumed by infer-status and draft-reply.
tailor-resume
Produce a job-specific, ATS-optimized resume from the user's master profile and a target job — reordering, reframing, and surfacing the most relevant real experience and keywords. Enforces a content rubric (bullet shape, length, parallel grammar, metric coverage), then renders a polished PDF by default (via render-resume) and visually QAs it. Never fabricates.
score-fit
Score how well the user's master profile fits a specific job — an ATS-style match percentage with matched/missing keywords, strengths, gaps, and a clear apply-or-skip recommendation. Optionally writes a structured sidecar that tailor-resume consumes.
review-render
Visually QA a rendered resume PDF and auto-fix layout/content defects in a bounded loop: render → screenshot → deterministic gate → vision rubric → apply one fix → re-render, until it passes or hits a pass cap. Catches widows, under-fill, overflow, orphaned headers, and imbalance that text-only logic can't see.