update owliver skill

This commit is contained in:
2026-08-14 17:33:16 +05:30
parent cccada9bd2
commit 4fdfb90326
58 changed files with 8015 additions and 1339 deletions

View File

@@ -85,6 +85,19 @@ const GREETINGS = {
return `Platform is steady across ${plural(f.postings.length, 'position')} and ${plural(f.total, 'application')}.`;
},
/* The form is the page, so the greeting is about what is being specified
rather than about the board — read from what this workspace has posted. */
'admin.createPosition': (f) => {
if (!f.postings.length) {
return 'This is the first position in the workspace — the weights you set here become the house pattern.';
}
/* Every posted role is a benchmark for pay and experience; only the ones
carrying weights can be compared on those, so the two are counted
separately rather than one standing in for the other. */
const weighted = f.postings.filter((p) => p.vetting_criteria).length;
return `Specifying a new role. ${plural(f.postings.length, 'position')} on file to benchmark against${weighted ? `, ${weighted} with vetting weights set` : ''}.`;
},
'admin.positions': (f) => {
if (!f.openPositions.length) return 'No open positions yet — publish a role and I will start tracking it.';
if (f.starvedPositions.length) {
@@ -211,6 +224,7 @@ const TITLES = {
'employer.analytics': () => 'Analytics assistant',
'admin.controlCenter': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.positions': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.createPosition': () => 'Specifying a position',
'admin.candidatesList': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.candidates': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.analytics': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
@@ -231,6 +245,8 @@ const DESCRIPTIONS = {
`Reading ${plural(f.total, 'application')} across ${plural(f.postings.length, 'position')} — health, operations and what needs intervention.`,
'admin.positions': (f) =>
`Reading ${plural(f.total, 'application')} across ${plural(f.postings.length, 'position')} — hiring health, pipeline strength and what needs intervention.`,
'admin.createPosition': (f) =>
`Reading this draft against ${plural(f.postings.length, 'posted position')} — vetting weights, pay, experience and the credentials already in use.`,
'admin.candidatesList': (f) =>
`Reading ${plural(f.total, 'candidate')} across ${plural(f.postings.length, 'position')} — match quality, screening and hiring readiness.`,
'admin.candidates': (f) =>
@@ -281,6 +297,11 @@ const PLACEHOLDERS = {
'Ask Owliver which role to fill first…',
'Ask Owliver about hiring bottlenecks…',
],
'admin.createPosition': () => [
'Ask Owliver about the vetting weights…',
'Ask Owliver what comparable roles ask for…',
'Ask Owliver to explain this form…',
],
'admin.candidatesList': () => [
'Ask Owliver about candidates…',
'Ask Owliver who is interview ready…',
@@ -391,6 +412,15 @@ const PROMPTS = {
{ label: 'Identify operational risks', prompt: 'Identify operational risks and what I should fix first', capability: 'recommendations' },
],
/* Create Position asks about the draft in front of the author. Every one is
answerable from the form and the positions already posted. */
'admin.createPosition': () => [
{ label: 'Explain the vetting weights', prompt: 'Summarize these vetting weights', capability: 'vetting-weights' },
{ label: 'Compare with similar roles', prompt: 'What do comparable roles ask for?', capability: 'position-benchmarks' },
{ label: 'Credentials in use', prompt: 'Which certifications does this workspace require?', capability: 'position-requirements' },
{ label: 'How this form works', prompt: 'Explain how this form works', capability: 'position-spec-steps' },
],
/**
* Positions suggestions are the current workforce situation, phrased as
* questions.
@@ -407,6 +437,40 @@ const PROMPTS = {
'admin.positions': (f, workforce) => {
const out = [];
/**
* Two things about the position in front of the reader come first, because
* both are about what they were *just doing* rather than about the board.
*
* A draft is unfinished work, so finishing it leads. Then the role the page
* has open — the drawer, or the one just published, which the form names in
* the URL on its way here — gets the question its state actually invites:
* a role with no applicants yet is a matching question, not a pipeline one.
*
* Both name the record, so the answer resolves against that position and
* cannot be a stale reading of a different one.
*/
const drafts = (f.postings || []).filter((p) => p.status === 'draft');
if (drafts.length) {
out.push({
label: drafts.length === 1 ? `Continue the ${drafts[0].title} draft` : `${drafts.length} drafts to finish`,
prompt: 'Which positions are still in draft?',
capability: 'position-drafts',
});
}
const current = workforce?.currentPositionId
? (workforce.positions || []).find((p) => p.id === workforce.currentPositionId)
: null;
if (current && current.status !== 'draft') {
out.push({
label: `Find matching candidates for ${current.title}`,
/* The definition's own words, with the role named. It resolves to the
candidate-matching skill and reads that position — so switching the
skill off in Settings takes this answer with it, as it should. */
prompt: `Find matching candidates for ${current.title}`,
});
}
if (workforce?.positions?.length) {
const { positions, context } = workforce;
const ranked = prioritise(positions, context);