job-application-agent 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ # Usage analytics
2
+
3
+ Job Application Agent includes default-enabled, opt-out usage analytics. The purpose is to learn which discovery sources, job types, applicant-tracking systems, and application steps are useful or unreliable.
4
+
5
+ The first eligible command displays a disclosure. New installations may send that command's events after the disclosure. Existing installations receive a one-command grace period before events begin.
6
+
7
+ ## Controls
8
+
9
+ ```text
10
+ node scripts/job-application.mjs telemetry status
11
+ node scripts/job-application.mjs telemetry disable
12
+ node scripts/job-application.mjs telemetry enable
13
+ node scripts/job-application.mjs telemetry reset
14
+ node scripts/job-application.mjs telemetry preview --stdin
15
+ node scripts/job-application.mjs telemetry record --stdin
16
+ ```
17
+
18
+ - `disable` stops future collection while preserving the anonymous installation ID.
19
+ - `enable` resumes collection with the same anonymous installation ID.
20
+ - `reset` disables collection and removes the anonymous ID and relay token. Enabling later creates a new identity.
21
+ - `preview` validates and shows an event without transmitting it.
22
+ - `record` rejects undocumented events and properties; browser workflows use it for started, step, pause, skip, and round events. Confirmed submissions are emitted by `ledger add` and must not be recorded twice.
23
+ - `status`, `disable`, `reset`, and `preview` never transmit an event. After `enable`, collection resumes on the next eligible workflow command.
24
+ - Previously collected events remain until the analytics retention period expires. Disabling or resetting does not issue a historical-deletion request.
25
+
26
+ Telemetry is best effort. It has no offline queue, uses a short network timeout, and never changes the result of a job-application command.
27
+
28
+ ## Identity boundary
29
+
30
+ Analytics never includes the candidate's name, email, phone, exact address, profile URLs, candidate location, work authorization, personal compensation or compensation floor, target profile or thresholds, resume or attachments, must-have evidence or coverage details, rejection reasons, prompts, responses, job descriptions, form questions, drafted answers, notes, passwords, MFA, CAPTCHA, legal or demographic answers, browser data, IP address, request headers, user agent, or raw error messages.
31
+
32
+ Structured job context may include company, role title, canonical destination domain, a SHA-256 hash of the job URL after removing query parameters and fragments, ATS, source channel, job country, work mode, employment type, seniority, role family, published salary band, fit score, match/gap categories, workflow stages, field categories, pause reasons, submission result, outcome, bounded interview quality, and bounded interview failure point.
33
+
34
+ Company and title values are bounded and rejected when they resemble an email, phone number, URL, LinkedIn profile, or GitHub profile.
35
+
36
+ ## Event schema
37
+
38
+ | Event | Structured properties |
39
+ |---|---|
40
+ | `installation_started` | OS family, Node major version, submission mode |
41
+ | `command_completed` | Command category, result, duration bucket |
42
+ | `job_discovered` | Company, title, job hash/domain, ATS/source, job country, work mode, seniority, employment type, role family, published salary band |
43
+ | `job_assessed` | Company, title, job hash/domain, ATS, fit score, eligibility, decision, match/gap tags |
44
+ | `application_started` | Job hash, ATS, approval mode, required-field count, resume/cover-letter/referral requirements |
45
+ | `application_step` | Job hash, ATS, stage, field category, retry count, duration bucket |
46
+ | `application_paused` | Job hash, ATS, stage, bounded reason |
47
+ | `application_skipped` | Job hash, bounded reason, fit score, eligibility |
48
+ | `application_submitted` | Company, title, job hash/domain, ATS, duration, fields filled, short-answer count, resume-upload Boolean, approval mode |
49
+ | `round_completed` | Requested/submitted/assessed/skipped/paused/error counts, duration bucket |
50
+ | `outcome_recorded` | Company, title, job hash/domain, ATS, outcome, days since submission, optional bounded interview quality/failure point |
51
+ | `review_generated` | Canonical unique-submission and outcome counts, review-due Boolean |
52
+ | `skill_error` | Stable error code, workflow stage, ATS/job hash when available, recoverable Boolean |
53
+
54
+ Only documented enums, bounded numbers, Booleans, bounded company/title/country strings, and documented tag arrays are accepted. Client and relay both reject unknown properties. Payloads are limited to 4 KB.
55
+
56
+ ## Processing and retention
57
+
58
+ - A Cloudflare Worker validates events, signs anonymous installation tokens, and forwards accepted payloads.
59
+ - PostHog US Cloud stores personless events with `$process_person_profile: false`.
60
+ - Every event disables GeoIP enrichment with `$geoip_disable: true`, and the PostHog project discards incoming IP data.
61
+ - The project does not call PostHog identify, alias, group, person-property, autocapture, or session-replay features.
62
+ - Anonymous installation IDs remain stable until reset.
63
+ - The product retention policy is 24 months and dashboards are private. Dashboard queries exclude data older than 24 months.
64
+ - PostHog US Cloud must be configured with a 24-month raw-event TTL before production telemetry is considered fully retention-compliant. The current free project does not expose a self-service raw-event TTL, so the owner must enable that control through an eligible PostHog plan or arrange time-bounded deletion with PostHog. This limitation does not weaken any collection-time identity boundary.
65
+ - The Worker does not forward client IPs or request headers, and Worker observability is disabled.
@@ -0,0 +1,12 @@
1
+ # Application answer guidance
2
+
3
+ Use this structure for motivation and fit answers:
4
+
5
+ 1. State one company-specific motivation tied to the product, customers, technical problem, or mission visible in a reliable company source.
6
+ 2. Give two concrete, resume-backed achievements that demonstrate the most important requirements. Prefer outcomes and shipped work over tool lists.
7
+ 3. If a material gap exists, add one honest bridge: name the adjacent evidence, state what is not yet demonstrated, and explain the credible learning path without implying experience the candidate does not have.
8
+
9
+ Keep the answer direct and human. Aim for roughly 100–150 words unless the form requires another length. Adapt the evidence to the question; do not paste a keyword-dense summary.
10
+
11
+ Never invent experience, scale, security ownership, technologies, employment terms, motivation, or company knowledge. Do not claim GraphQL, Temporal, Rust, P2P, networking, security, or other experience unless it is explicit in the canonical resume or candidate-provided evidence.
12
+
@@ -0,0 +1,156 @@
1
+ # Data schemas
2
+
3
+ ## Profile input
4
+
5
+ Send one JSON object to `profile set --stdin`. Send an object containing only intentional overrides to `profile migrate --stdin`; migration preserves existing identity fields, maps legacy `salaryPreference` to `targetCompensation`, adds current defaults, validates the complete result, and writes it atomically.
6
+
7
+ ```json
8
+ {
9
+ "name": "Candidate Name",
10
+ "email": "candidate@example.com",
11
+ "phone": "+91 90000 00000",
12
+ "location": "Bengaluru, India",
13
+ "workAuthorization": "Exact countries or arrangements",
14
+ "linkedin": "https://linkedin.com/in/example",
15
+ "github": "https://github.com/example",
16
+ "portfolio": "https://example.com",
17
+ "availability": "30 days",
18
+ "currentCompensation": "Optional exact value and currency",
19
+ "targetCompensation": "Optional legacy-compatible free text",
20
+ "compensationFloor": { "amount": 9000000, "currency": "INR", "period": "year" },
21
+ "roleFamilies": ["product-engineering", "full-stack", "ai-ml"],
22
+ "seniority": ["senior", "staff"],
23
+ "skills": ["TypeScript", "Python", "React", "Node.js", "PostgreSQL", "MCP", "AI agents"],
24
+ "targetLocations": ["India", "Remote", "Worldwide"],
25
+ "excludedLocations": [],
26
+ "workModes": ["remote"],
27
+ "industries": ["AI", "developer tools"],
28
+ "excludedCompanies": [],
29
+ "submissionMode": "routine-auto",
30
+ "yearsExperience": 10,
31
+ "autoSubmitMinScore": 80,
32
+ "manualReviewMinScore": 70,
33
+ "minMustHaveCoverage": 70
34
+ }
35
+ ```
36
+
37
+ Required fields are `name`, `email`, `phone`, `location`, `workAuthorization`, `roleFamilies`, `seniority`, `targetLocations`, `workModes`, `submissionMode`, `yearsExperience`, `autoSubmitMinScore`, `manualReviewMinScore`, and `minMustHaveCoverage`.
38
+
39
+ `compensationFloor` is optional and must use a three-letter currency code and `period: "year"`. Compare a job salary only when its basis and currency are directly comparable.
40
+
41
+ ## Job assessment input
42
+
43
+ Treat `mustHaves[].evidence` as private resume analysis. It is used locally and is not included in telemetry.
44
+
45
+ ```json
46
+ {
47
+ "title": "Senior Product Engineer",
48
+ "company": "Example",
49
+ "description": "Posting text",
50
+ "source": "greenhouse",
51
+ "url": "https://job-boards.greenhouse.io/example/jobs/123",
52
+ "postingStatus": "active",
53
+ "eligibility": "eligible",
54
+ "roleFamily": "product-engineering",
55
+ "seniority": "senior",
56
+ "experienceMin": 7,
57
+ "experienceMax": 12,
58
+ "workMode": "remote",
59
+ "remote": true,
60
+ "locations": ["Remote", "India"],
61
+ "salaryMaximum": 12000000,
62
+ "salaryCurrency": "INR",
63
+ "mustHaves": [
64
+ { "requirement": "TypeScript", "status": "met", "evidence": "Resume-backed example" },
65
+ { "requirement": "Distributed systems", "status": "partial", "evidence": "Related platform work, not exact claim" },
66
+ { "requirement": "GraphQL", "status": "missing" }
67
+ ]
68
+ }
69
+ ```
70
+
71
+ Allowed sources: `linkedin`, `greenhouse`, `lever`, `ashby`, `workable`, `comeet`, `workday`, `rippling`, `smartrecruiters`, `google-form`, `company`, `email`, and `other`.
72
+
73
+ Allowed posting statuses: `active`, `closed`, `unclear`. Allowed eligibility: `eligible`, `unclear`, `ineligible`. Allowed seniority: `junior`, `mid`, `senior`, `staff`, `principal`, `lead`, `manager`, `director`, `founding`, `unspecified`. Allowed work modes: `remote`, `hybrid`, `onsite`, `unspecified`. Must-have statuses: `met`, `partial`, `missing`, `unclear`.
74
+
75
+ Assessment output retains `review`, `ask`, `skip`, and `exclude`, and adds `autoEligible`, `mustHaveCoverage`, and structured `gates`. `review` does not itself authorize submission.
76
+
77
+ ## Duplicate check input
78
+
79
+ Include as many identifiers as are known.
80
+
81
+ ```json
82
+ {
83
+ "id": "example-senior-product-engineer-2026-01-15",
84
+ "company": "Example",
85
+ "role": "Senior Product Engineer",
86
+ "url": "https://jobs.example.com/roles/123?utm_source=board",
87
+ "employerJobId": "greenhouse:123"
88
+ }
89
+ ```
90
+
91
+ The check removes fragments and non-job query parameters while retaining recognized job or requisition identifiers. Matching ledger ID, canonical URL, or same-company employer job ID is a hard duplicate. Same company and role without a shared job ID is a possible duplicate.
92
+
93
+ ## Confirmed submission input
94
+
95
+ Add only after visible success confirmation.
96
+
97
+ ```json
98
+ {
99
+ "id": "example-senior-product-engineer-2026-01-15",
100
+ "company": "Example",
101
+ "role": "Senior Product Engineer",
102
+ "url": "https://jobs.example.com/roles/123",
103
+ "employerJobId": "greenhouse:123",
104
+ "source": "company",
105
+ "score": 84,
106
+ "status": "submitted",
107
+ "submittedAt": "2026-01-15T10:00:00.000Z",
108
+ "approval": "STANDING AUTHORIZATION",
109
+ "duplicateOverride": "NEW REQUISITION CONFIRMED",
110
+ "answers": { "Resume": "Canonical resume.pdf" },
111
+ "telemetry": {
112
+ "durationBucket": "5-15m",
113
+ "fieldsFilled": 14,
114
+ "shortAnswerCount": 2,
115
+ "resumeUploaded": true
116
+ }
117
+ }
118
+ ```
119
+
120
+ Use `duplicateOverride` only for a verified distinct requisition after a possible-duplicate warning. It and `telemetry` are transient and are not written to the application ledger. Use approval `APPROVE SUBMIT` for per-application approval or `STANDING AUTHORIZATION` when the current request authorizes routine batch submission.
121
+
122
+ ## Outcome input
123
+
124
+ ```json
125
+ {
126
+ "id": "example-senior-product-engineer-2026-01-15",
127
+ "status": "rejected",
128
+ "occurredAt": "2026-01-20T09:00:00.000Z",
129
+ "note": "Optional private note",
130
+ "interviewQuality": "weak",
131
+ "failurePoint": "constraints",
132
+ "reasons": [
133
+ { "category": "eligibility", "evidence": "explicit" }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ Allowed outcomes: `interview`, `rejected`, `offer`, `withdrawn`.
139
+
140
+ Optional interview quality values: `promising`, `viable`, `weak`, `dead`. Optional failure points: `role-scope`, `company-problem`, `constraints`, `interviewer`, `process`, `unknown`. A failure point requires an interview quality. Free-form notes remain private and are never included in telemetry.
141
+
142
+ Allowed reason categories: `eligibility`, `closed-stale`, `level-compensation`, `must-have-gap`, `generic-resume-screen`, `interview-stage`, `unknown`. Evidence is `explicit` or `inferred`. An identical event is idempotent. Adding reasons or interview-quality fields to an earlier identical occurrence appends one local enrichment row but suppresses duplicate outcome telemetry.
143
+
144
+ ## Review acknowledgement input
145
+
146
+ Generate `ledger review` first. Acknowledge only after the candidate has reviewed it.
147
+
148
+ ```json
149
+ {
150
+ "reviewedAt": "2026-01-21T09:00:00.000Z"
151
+ }
152
+ ```
153
+
154
+ The acknowledgement stores the current canonical unique-submission and mature-application counts in append-only `reviews.ndjson`.
155
+
156
+ `ledger review` also returns `interviewLearningSegments`. Each row combines the canonical application's source and ten-point fit-score band with the latest recorded interview quality and failure point, plus a count. This supports evidence-based targeting reviews without exposing private notes or automatically changing score weights.