job-application-agent 3.4.2 → 3.5.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.
- package/README.md +2 -0
- package/job-application-agent/SKILL.md +11 -2
- package/job-application-agent/capabilities.json +2 -1
- package/job-application-agent/references/ACCOUNTING.md +104 -0
- package/job-application-agent/references/CLOUD_STATE.md +2 -0
- package/job-application-agent/references/RUNS.md +6 -0
- package/job-application-agent/references/SCHEMAS.md +4 -0
- package/job-application-agent/scripts/application-accounting.mjs +246 -0
- package/job-application-agent/scripts/cloud-state-client.mjs +57 -7
- package/job-application-agent/scripts/job-application.mjs +126 -24
- package/job-application-agent/scripts/version.mjs +1 -1
- package/job-application-agent/tests/accounting-cli.test.mjs +86 -0
- package/job-application-agent/tests/accounting-cloud-client.test.mjs +183 -0
- package/job-application-agent/tests/accounting-retry-cli.test.mjs +96 -0
- package/job-application-agent/tests/accounting-source-race.test.mjs +109 -0
- package/job-application-agent/tests/application-accounting.test.mjs +315 -0
- package/job-application-agent/tests/job-application.test.mjs +5 -0
- package/job-application-agent/tests/review-cadence.test.mjs +66 -0
- package/job-application-agent/tests/workflow-state.test.mjs +18 -2
- package/package.json +2 -2
|
@@ -71,6 +71,11 @@ function submission(index, roundId, overrides = {}) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
function recordLeads(env, roundId, sourceId, entries, otherCount = 0) {
|
|
75
|
+
for (const app of entries) cli(env, ['round','lead','--stdin'], { roundId, sourceId, applicationId: app.id, url: app.url, employerJobId: app.employerJobId, company: app.company, role: app.role, disposition:'qualified', observedAt:app.submittedAt, evidence:'Synthetic role meets the target requirements.' });
|
|
76
|
+
for (let i=0;i<otherCount;i++) cli(env, ['round','lead','--stdin'], { roundId, sourceId, url:`https://other.fixture.example/${sourceId}/${i}`, company:`Other ${i}`, disposition:'no-relevant-opening', observedAt:'2026-08-01T00:00:00Z', evidence:'No target role on this careers page.' });
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
test('persists a scoped autonomy grant and revokes future routine transmissions', async (t) => {
|
|
75
80
|
const { directory, env } = await fixture(t, 'autonomy');
|
|
76
81
|
|
|
@@ -122,6 +127,7 @@ test('counts only unique confirmed ledger submissions for an explicit round', as
|
|
|
122
127
|
assert.equal(status.completed, false);
|
|
123
128
|
|
|
124
129
|
for (const sourceId of ['linkedin-jobs-feed', 'indeed', 'hacker-news-who-is-hiring']) {
|
|
130
|
+
recordLeads(env, started.roundId, sourceId, sourceId === 'linkedin-jobs-feed' ? Array.from({ length:30 },(_,i)=>submission(i,started.roundId)) : [], sourceId === 'linkedin-jobs-feed' ? 0 : 30);
|
|
125
131
|
cli(env, ['round', 'source', '--stdin'], {
|
|
126
132
|
roundId: started.roundId, sourceId, status: 'searched', reviewedCount: 30, qualifiedCount: sourceId === 'linkedin-jobs-feed' ? 30 : 0,
|
|
127
133
|
evidence: 'Reviewed matching postings against the unchanged target; other leads did not qualify.',
|
|
@@ -142,6 +148,8 @@ test('round completion requires distinct source coverage and explains concentrat
|
|
|
142
148
|
const { roundId } = cli(env, ['round', 'start', '--stdin'], { requestedCount: 2 });
|
|
143
149
|
for (const i of [1, 2]) cli(env, ['ledger', 'add', '--stdin'], submission(i, roundId, { discoverySourceId: 'linkedin-jobs-feed' }));
|
|
144
150
|
assert.match(cliFailure(env, ['round', 'complete', '--stdin'], { roundId }).stderr, /3 distinct discovery sources/i);
|
|
151
|
+
recordLeads(env,roundId,'linkedin-jobs-feed',[submission(1,roundId),submission(2,roundId)],8);
|
|
152
|
+
recordLeads(env,roundId,'indeed',[],10);
|
|
145
153
|
const check = { roundId, sourceId: 'linkedin-jobs-feed', status: 'searched', reviewedCount: 10, qualifiedCount: 2, evidence: 'Reviewed ten relevant postings using the target constraints.' };
|
|
146
154
|
cli(env, ['round', 'source', '--stdin'], check);
|
|
147
155
|
cli(env, ['round', 'source', '--stdin'], check);
|
|
@@ -169,7 +177,10 @@ test('discovery coverage rejects invalid reports and requires attribution withou
|
|
|
169
177
|
for (const bad of [{ sourceId: 'imaginary-board' }, { qualifiedCount: 5 }, { status: 'blocked' }, { applicationIds: ['not-in-round'] }, { evidence: '' }, { privateProfile: 'forbidden' }]) {
|
|
170
178
|
assert.equal(cliFailure(env, ['round', 'source', '--stdin'], { ...check, ...bad }).status, 1);
|
|
171
179
|
}
|
|
172
|
-
for (const sourceId of ['linkedin-jobs-feed', 'indeed', 'hacker-news-who-is-hiring'])
|
|
180
|
+
for (const sourceId of ['linkedin-jobs-feed', 'indeed', 'hacker-news-who-is-hiring']) {
|
|
181
|
+
recordLeads(env,roundId,sourceId,[submission(1,roundId)],3);
|
|
182
|
+
cli(env, ['round', 'source', '--stdin'], { ...check, sourceId });
|
|
183
|
+
}
|
|
173
184
|
assert.match(cliFailure(env, ['round', 'complete', '--stdin'], { roundId }).stderr, /attribution/i);
|
|
174
185
|
cli(env, ['round', 'source', '--stdin'], { ...check, applicationIds: ['round-role-1'] });
|
|
175
186
|
assert.equal(cli(env, ['round', 'status', roundId]).discovery.unattributedCount, 0);
|
|
@@ -180,7 +191,11 @@ test('source diversity is independent of ATS and concentration explanations are
|
|
|
180
191
|
const { env } = await fixture(t, 'balanced-discovery');
|
|
181
192
|
const { roundId } = cli(env, ['round', 'start', '--stdin'], { requestedCount: 5 });
|
|
182
193
|
const ids = ['linkedin-jobs-feed', 'indeed', 'hacker-news-who-is-hiring'];
|
|
183
|
-
for (const sourceId of ids)
|
|
194
|
+
for (const sourceId of ids) {
|
|
195
|
+
const entries=Array.from({length:5},(_,i)=>submission(i+1,roundId)).filter((_,i)=>ids[i%3]===sourceId);
|
|
196
|
+
recordLeads(env,roundId,sourceId,entries,1);
|
|
197
|
+
cli(env, ['round', 'source', '--stdin'], { roundId, sourceId, status: 'searched', evidence: 'Reviewed relevant postings and verified target fit.' });
|
|
198
|
+
}
|
|
184
199
|
for (let i = 1; i <= 5; i++) cli(env, ['ledger', 'add', '--stdin'], submission(i, roundId, { discoverySourceId: ids[(i - 1) % 3], applicationChannel: 'ashby' }));
|
|
185
200
|
const completed = cli(env, ['round', 'complete', '--stdin'], { roundId });
|
|
186
201
|
assert.equal(completed.discovery.maxSourceSharePercent, 40);
|
|
@@ -197,6 +212,7 @@ test('blocked-only attempts and two views of the same network do not satisfy dis
|
|
|
197
212
|
cli(env, ['round', 'source', '--stdin'], { ...check, sourceId: 'indeed' });
|
|
198
213
|
assert.equal(cli(env, ['round', 'status', roundId]).discovery.coverageSatisfied, false);
|
|
199
214
|
const { blocker, ...searched } = check;
|
|
215
|
+
recordLeads(env,roundId,'indeed',[submission(1,roundId)]);
|
|
200
216
|
cli(env, ['round', 'source', '--stdin'], { ...searched, sourceId: 'indeed', status: 'searched', reviewedCount: 1, qualifiedCount: 1 });
|
|
201
217
|
cli(env, ['round', 'source', '--stdin'], { ...check, sourceId: 'indeed' });
|
|
202
218
|
assert.equal(cli(env, ['round', 'status', roundId]).discovery.coverageSatisfied, true);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "job-application-agent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "A privacy-first Agent Skill and CLI for evidence-based job discovery, application completion, and outcome tracking.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"check:native-artifacts": "node scripts/ci/validate-native-artifacts.mjs",
|
|
45
45
|
"privacy-audit": "node --test job-application-agent/tests/privacy-audit.test.mjs",
|
|
46
46
|
"smoke:package": "node scripts/smoke-package.mjs",
|
|
47
|
-
"check": "node --check job-application-agent/scripts/job-application.mjs && node --check job-application-agent/scripts/cloud-state-client.mjs && node --check job-application-agent/scripts/secret-store.mjs && node --check job-application-agent/scripts/source-community-client.mjs && node --check job-application-agent/scripts/source-community-schema.mjs && node --check job-application-agent/scripts/telemetry-client.mjs && node --check job-application-agent/scripts/telemetry-schema.mjs && node --check job-application-agent/scripts/version.mjs && node --check telemetry-worker/src/worker.mjs && node --check telemetry-worker/src/public-stats.mjs && node --check telemetry-worker/public/dashboard.js && node --check installer/src/cli.mjs && node --check installer/src/installer.mjs && node --check installer/src/runner.mjs && node --check installer/src/scheduler.mjs && node --check scripts/ci/classify-paths.mjs && node --check scripts/ci/validate-native-artifacts.mjs && node --check bin/job-application-agent.mjs && node --check state-worker/src/worker.mjs && node --check state-worker/src/backup.mjs && node --check state-worker/src/cli.mjs && node --check state-worker/bin/sync.mjs",
|
|
47
|
+
"check": "node --check job-application-agent/scripts/job-application.mjs && node --check job-application-agent/scripts/cloud-state-client.mjs && node --check job-application-agent/scripts/secret-store.mjs && node --check job-application-agent/scripts/source-community-client.mjs && node --check job-application-agent/scripts/source-community-schema.mjs && node --check job-application-agent/scripts/telemetry-client.mjs && node --check job-application-agent/scripts/telemetry-schema.mjs && node --check job-application-agent/scripts/version.mjs && node --check telemetry-worker/src/worker.mjs && node --check telemetry-worker/src/public-stats.mjs && node --check telemetry-worker/public/dashboard.js && node --check installer/src/cli.mjs && node --check installer/src/installer.mjs && node --check installer/src/runner.mjs && node --check installer/src/scheduler.mjs && node --check scripts/ci/classify-paths.mjs && node --check scripts/ci/validate-native-artifacts.mjs && node --check bin/job-application-agent.mjs && node --check state-worker/src/worker.mjs && node --check state-worker/src/backup.mjs && node --check state-worker/src/cli.mjs && node --check state-worker/bin/sync.mjs && node --check job-application-agent/scripts/application-accounting.mjs",
|
|
48
48
|
"prepack": "npm run check && npm test && npm run privacy-audit"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|