fraim-hub 2.0.288 → 2.0.289
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/dist/src/ai-hub/server.js +4 -8
- package/dist/src/config/ai-manager-hiring.js +6 -2
- package/dist/src/config/persona-capability-bundles.js +1 -1
- package/dist/src/config/persona-hiring.js +26 -26
- package/package.json +2 -2
- package/public/ai-hub/script.js +46 -10
- package/public/first-run/script.js +10 -1
- package/public/portfolio/aida.html +13 -13
- package/public/portfolio/ashley.html +2 -2
- package/public/portfolio/auditya.html +2 -2
- package/public/portfolio/banke.html +2 -2
- package/public/portfolio/beza.html +2 -2
- package/public/portfolio/careena.html +2 -2
- package/public/portfolio/casey.html +2 -2
- package/public/portfolio/celia.html +2 -2
- package/public/portfolio/deidre.html +2 -2
- package/public/portfolio/hari.html +2 -2
- package/public/portfolio/index.html +5 -5
- package/public/portfolio/maestro.html +2 -2
- package/public/portfolio/mandy.html +2 -2
- package/public/portfolio/mona.html +2 -2
- package/public/portfolio/pam.html +2 -2
- package/public/portfolio/procella.html +2 -2
- package/public/portfolio/qasm.html +2 -2
- package/public/portfolio/ricardo.html +2 -2
- package/public/portfolio/sade.html +2 -2
- package/public/portfolio/sam.html +2 -2
- package/public/portfolio/sechar.html +2 -2
- package/public/portfolio/sreya.html +2 -2
- package/public/portfolio/swen.html +4 -4
|
@@ -6332,14 +6332,10 @@ class AiHubServer {
|
|
|
6332
6332
|
messages: persistedConversation ? persistedMessagesForRun(persistedConversation) : [],
|
|
6333
6333
|
events: resumeEvents,
|
|
6334
6334
|
eventLogRefs: persistedConversation?.eventLogRefs || [],
|
|
6335
|
-
//
|
|
6336
|
-
//
|
|
6337
|
-
//
|
|
6338
|
-
//
|
|
6339
|
-
// carry the persisted run projection forward regardless of the
|
|
6340
|
-
// conversation's prior status. If the resumed session genuinely has
|
|
6341
|
-
// nothing left to do, it simply reaches the same completed state
|
|
6342
|
-
// again on its own the next time seekMentoring reports its phase.
|
|
6335
|
+
// A manager can issue new instructions after a job was marked done.
|
|
6336
|
+
// That correction stays in the same conversation/job identity and keeps
|
|
6337
|
+
// its phase history so the tracker can show the job moving back to an
|
|
6338
|
+
// earlier phase instead of pretending this is unrelated fresh work.
|
|
6343
6339
|
currentPhase: persistedRun?.currentPhase || null,
|
|
6344
6340
|
phaseHistory: persistedRun?.phaseHistory || [],
|
|
6345
6341
|
phaseVisits: persistedRun?.phaseVisits || [],
|
|
@@ -64,13 +64,17 @@ function buildSearchQuery(roleKey) {
|
|
|
64
64
|
const profile = getHumanManagerProfile(roleKey);
|
|
65
65
|
return `${profile.keywords.join(' OR ')} AND ${AI_MANAGER_QUERY_TERMS}`;
|
|
66
66
|
}
|
|
67
|
+
function indefiniteArticle(phrase) {
|
|
68
|
+
return /^[aeiou]/i.test(phrase.trim()) ? 'an' : 'a';
|
|
69
|
+
}
|
|
67
70
|
function buildJobDescription(roleKey) {
|
|
68
71
|
const profile = getHumanManagerProfile(roleKey);
|
|
69
72
|
const role = persona_hiring_1.PERSONA_HIRE_CATALOG[roleKey]?.role ?? 'AI Employee';
|
|
73
|
+
const article = indefiniteArticle(role);
|
|
70
74
|
return [
|
|
71
|
-
`${profile.humanTitle} — manager for
|
|
75
|
+
`${profile.humanTitle} — manager for ${article} ${role}`,
|
|
72
76
|
'',
|
|
73
|
-
`You will manage
|
|
77
|
+
`You will manage ${article} ${role} (an autonomous AI agent) and the humans around it, owning the outcomes it ships.`,
|
|
74
78
|
'',
|
|
75
79
|
"What you'll do:",
|
|
76
80
|
`- Write crisp specifications and acceptance criteria the ${role} can execute against.`,
|
|
@@ -278,7 +278,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
278
278
|
],
|
|
279
279
|
protectedAliases: ['ai-engineering', 'agent-engineering', 'ai-agents'],
|
|
280
280
|
defaultHireMode: 'job',
|
|
281
|
-
lockCopy: 'Hire
|
|
281
|
+
lockCopy: 'Hire AIDa to unlock AI agent design, MCP enablement, eval authoring, and agent evaluation work for this request.'
|
|
282
282
|
}
|
|
283
283
|
};
|
|
284
284
|
const PROTECTED_JOB_TO_PERSONA = new Map();
|
|
@@ -20,8 +20,8 @@ exports.getPersonaHireAmountCents = getPersonaHireAmountCents;
|
|
|
20
20
|
*/
|
|
21
21
|
exports.PERSONA_HIRE_CATALOG = {
|
|
22
22
|
aida: {
|
|
23
|
-
displayName: '
|
|
24
|
-
role: 'AI
|
|
23
|
+
displayName: 'AIDa',
|
|
24
|
+
role: 'AI Developer',
|
|
25
25
|
emoji: '\u{1F9E0}',
|
|
26
26
|
gradient: 'linear-gradient(135deg, #4f46e5 0%, #06b6d4 50%, #10b981 100%)',
|
|
27
27
|
blurb: 'Designs production AI agents, connects them to tools and data, and proves their behavior with evals before deployment.',
|
|
@@ -30,7 +30,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
30
30
|
},
|
|
31
31
|
swen: {
|
|
32
32
|
displayName: 'SWEn',
|
|
33
|
-
role: '
|
|
33
|
+
role: 'Software Engineer',
|
|
34
34
|
emoji: '💻',
|
|
35
35
|
gradient: 'linear-gradient(135deg, #2563eb 0%, #06b6d4 100%)',
|
|
36
36
|
blurb: 'Implements features, refactors code, and drives PR iteration to merge, reviewing design and code as a senior would.',
|
|
@@ -39,7 +39,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
39
39
|
},
|
|
40
40
|
qasm: {
|
|
41
41
|
displayName: 'QAsm',
|
|
42
|
-
role: '
|
|
42
|
+
role: 'QA Engineer',
|
|
43
43
|
emoji: '🛡️',
|
|
44
44
|
gradient: 'linear-gradient(135deg, #10b981 0%, #14b8a6 100%)',
|
|
45
45
|
blurb: 'Runs tests, assesses code and test quality, polishes UI, and drives bug bashes with evidence.',
|
|
@@ -48,7 +48,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
48
48
|
},
|
|
49
49
|
sekhar: {
|
|
50
50
|
displayName: 'SEChar',
|
|
51
|
-
role: '
|
|
51
|
+
role: 'Security Engineer',
|
|
52
52
|
emoji: '🔒',
|
|
53
53
|
gradient: 'linear-gradient(135deg, #ef4444 0%, #f43f5e 100%)',
|
|
54
54
|
blurb: 'Sets up AI-native security baselines, runs the findings command center, reviews changes for risk, and drives remediation to closure.',
|
|
@@ -57,7 +57,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
57
57
|
},
|
|
58
58
|
sreya: {
|
|
59
59
|
displayName: 'SREya',
|
|
60
|
-
role: '
|
|
60
|
+
role: 'Site Reliability Engineer',
|
|
61
61
|
emoji: '☁️',
|
|
62
62
|
gradient: 'linear-gradient(135deg, #2563eb 0%, #10b981 100%)',
|
|
63
63
|
blurb: 'Manages deployments, monitors uptime, optimizes cloud cost, and keeps infrastructure resilient and observable.',
|
|
@@ -66,7 +66,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
66
66
|
},
|
|
67
67
|
sade: {
|
|
68
68
|
displayName: 'SADE',
|
|
69
|
-
role: '
|
|
69
|
+
role: 'Salesforce Developer',
|
|
70
70
|
emoji: '☁️',
|
|
71
71
|
gradient: 'linear-gradient(135deg, #0284c7 0%, #0369a1 100%)',
|
|
72
72
|
blurb: 'Deploys Salesforce configuration from ServiceNow tickets, builds reports and dashboards, creates Flows from business requirements, audits org health, and manages users and data at scale.',
|
|
@@ -75,7 +75,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
75
75
|
},
|
|
76
76
|
pam: {
|
|
77
77
|
displayName: 'PaM',
|
|
78
|
-
role: '
|
|
78
|
+
role: 'Product Manager',
|
|
79
79
|
emoji: '📋',
|
|
80
80
|
gradient: 'linear-gradient(135deg, #8b5cf6 0%, #d946ef 100%)',
|
|
81
81
|
blurb: 'Owns specs, PRDs, technical design, issue prep, and the path from idea to shippable artifact.',
|
|
@@ -84,7 +84,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
84
84
|
},
|
|
85
85
|
huxley: {
|
|
86
86
|
displayName: 'hUXley',
|
|
87
|
-
role: '
|
|
87
|
+
role: 'UX / Brand Designer',
|
|
88
88
|
emoji: '🎨',
|
|
89
89
|
gradient: 'linear-gradient(135deg, #ec4899 0%, #f472b6 100%)',
|
|
90
90
|
blurb: 'Builds design systems, prototypes polished user-facing surfaces, and carries brand decisions into shipped product experiences.',
|
|
@@ -93,7 +93,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
93
93
|
},
|
|
94
94
|
gautam: {
|
|
95
95
|
displayName: 'GauTaM',
|
|
96
|
-
role: '
|
|
96
|
+
role: 'GTM & Marketing Manager',
|
|
97
97
|
emoji: '📣',
|
|
98
98
|
gradient: 'linear-gradient(135deg, #f97316 0%, #f59e0b 100%)',
|
|
99
99
|
blurb: 'Defines marketing strategy, ships content, runs launches, and owns the brand voice in market.',
|
|
@@ -102,7 +102,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
102
102
|
},
|
|
103
103
|
sam: {
|
|
104
104
|
displayName: 'SAM',
|
|
105
|
-
role: '
|
|
105
|
+
role: 'Sales Account Manager',
|
|
106
106
|
emoji: '📈',
|
|
107
107
|
gradient: 'linear-gradient(135deg, #059669 0%, #0d9488 100%)',
|
|
108
108
|
blurb: 'Surfaces stalled deals, computes pipeline health, and drafts account-specific re-engagement proposals for your top at-risk opportunities.',
|
|
@@ -111,7 +111,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
111
111
|
},
|
|
112
112
|
casey: {
|
|
113
113
|
displayName: 'CaSey',
|
|
114
|
-
role: '
|
|
114
|
+
role: 'Customer Success + Support',
|
|
115
115
|
emoji: '💬',
|
|
116
116
|
gradient: 'linear-gradient(135deg, #db2777 0%, #9333ea 100%)',
|
|
117
117
|
blurb: 'Scores account churn risk and expansion potential, generates prioritized action plans for CSMs, triages support cases, and routes L1 cases through automated resolution.',
|
|
@@ -120,7 +120,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
120
120
|
},
|
|
121
121
|
mona: {
|
|
122
122
|
displayName: 'MONa',
|
|
123
|
-
role: '
|
|
123
|
+
role: 'Finance Manager',
|
|
124
124
|
emoji: '💰',
|
|
125
125
|
gradient: 'linear-gradient(135deg, #10b981 0%, #f59e0b 100%)',
|
|
126
126
|
blurb: 'Models revenue, tracks unit economics, builds financial forecasts, and owns the metrics that drive growth decisions.',
|
|
@@ -129,7 +129,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
129
129
|
},
|
|
130
130
|
hari: {
|
|
131
131
|
displayName: 'HaRi',
|
|
132
|
-
role: '
|
|
132
|
+
role: 'HR Manager',
|
|
133
133
|
emoji: '👥',
|
|
134
134
|
gradient: 'linear-gradient(135deg, #0d9488 0%, #059669 100%)',
|
|
135
135
|
blurb: 'Manages onboarding, performance reviews, benefits analysis, payroll coordination, and HR business-partner advisory.',
|
|
@@ -138,7 +138,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
138
138
|
},
|
|
139
139
|
ricardo: {
|
|
140
140
|
displayName: 'RECardo',
|
|
141
|
-
role: '
|
|
141
|
+
role: 'Recruiter',
|
|
142
142
|
emoji: '🤝',
|
|
143
143
|
gradient: 'linear-gradient(135deg, #6366f1 0%, #ec4899 100%)',
|
|
144
144
|
blurb: 'Sources candidates, writes job descriptions, screens pipelines, and manages the hiring loop end-to-end.',
|
|
@@ -147,7 +147,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
147
147
|
},
|
|
148
148
|
cela: {
|
|
149
149
|
displayName: 'CELiA',
|
|
150
|
-
role: '
|
|
150
|
+
role: 'Legal Counsel',
|
|
151
151
|
emoji: '⚖️',
|
|
152
152
|
gradient: 'linear-gradient(135deg, #475569 0%, #6366f1 100%)',
|
|
153
153
|
blurb: 'Drafts and reviews contracts, NDAs, patents, trademarks, and the SaaS legal stack.',
|
|
@@ -156,7 +156,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
156
156
|
},
|
|
157
157
|
procella: {
|
|
158
158
|
displayName: 'PROCella',
|
|
159
|
-
role: '
|
|
159
|
+
role: 'Procurement Manager',
|
|
160
160
|
emoji: '📦',
|
|
161
161
|
gradient: 'linear-gradient(135deg, #0f766e 0%, #7c3aed 100%)',
|
|
162
162
|
blurb: 'Frames procurement strategy, sources suppliers, runs RFx packages, evaluates responses, and keeps purchases acceptance-gated.',
|
|
@@ -165,7 +165,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
165
165
|
},
|
|
166
166
|
banke: {
|
|
167
167
|
displayName: 'BANKe',
|
|
168
|
-
role: '
|
|
168
|
+
role: 'Banking KYC Employee',
|
|
169
169
|
emoji: '\u{1F3E6}',
|
|
170
170
|
gradient: 'linear-gradient(135deg, #0f766e 0%, #2563eb 100%)',
|
|
171
171
|
blurb: 'Runs banking KYC cases with consent-aware evidence capture, decision receipts, and stable audit handoff artifacts.',
|
|
@@ -174,7 +174,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
174
174
|
},
|
|
175
175
|
auditya: {
|
|
176
176
|
displayName: 'AUDITya',
|
|
177
|
-
role: '
|
|
177
|
+
role: 'Banking Auditor',
|
|
178
178
|
emoji: '\u{1F50E}',
|
|
179
179
|
gradient: 'linear-gradient(135deg, #7c3aed 0%, #0f172a 100%)',
|
|
180
180
|
blurb: 'Audits AI banking work by tracing decisions back to evidence, receipts, exceptions, and reusable audit reports.',
|
|
@@ -183,7 +183,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
183
183
|
},
|
|
184
184
|
deidre: {
|
|
185
185
|
displayName: 'DEIdre',
|
|
186
|
-
role: '
|
|
186
|
+
role: 'Inclusion Leader',
|
|
187
187
|
emoji: '🌍',
|
|
188
188
|
gradient: 'linear-gradient(135deg, #9333ea 0%, #d946ef 100%)',
|
|
189
189
|
blurb: 'Audits equity gaps, designs bias-aware AI governance, builds ERG toolkits, and creates inclusion-fluency programs.',
|
|
@@ -192,7 +192,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
192
192
|
},
|
|
193
193
|
careena: {
|
|
194
194
|
displayName: 'CAREEna',
|
|
195
|
-
role: '
|
|
195
|
+
role: 'Career Coach',
|
|
196
196
|
emoji: '🎓',
|
|
197
197
|
gradient: 'linear-gradient(135deg, #0ea5e9 0%, #6366f1 100%)',
|
|
198
198
|
blurb: 'Runs the candidate-side search loop: role sourcing, application execution, networking, interview prep, and close-stage offer strategy.',
|
|
@@ -201,7 +201,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
201
201
|
},
|
|
202
202
|
ashley: {
|
|
203
203
|
displayName: 'AshLey',
|
|
204
|
-
role: '
|
|
204
|
+
role: 'Executive Assistant',
|
|
205
205
|
emoji: '📅',
|
|
206
206
|
gradient: 'linear-gradient(135deg, #f59e0b 0%, #fbbf24 100%)',
|
|
207
207
|
blurb: 'Owns executive coordination, weekly operating reviews, and portfolio reporting across the workforce.',
|
|
@@ -210,7 +210,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
210
210
|
},
|
|
211
211
|
mandy: {
|
|
212
212
|
displayName: 'MANdy',
|
|
213
|
-
role: '
|
|
213
|
+
role: 'Manager',
|
|
214
214
|
emoji: '🎯',
|
|
215
215
|
gradient: 'linear-gradient(135deg, #7c3aed 0%, #4338ca 100%)',
|
|
216
216
|
blurb: 'Plans the job sequence, runs sub-agents in parallel, coaches them through verification loops, and hands back a synthesized DRAFT for your approval.',
|
|
@@ -219,7 +219,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
219
219
|
},
|
|
220
220
|
beza: {
|
|
221
221
|
displayName: 'BeZa',
|
|
222
|
-
role: '
|
|
222
|
+
role: 'Business Strategist',
|
|
223
223
|
emoji: '🧭',
|
|
224
224
|
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
|
225
225
|
blurb: 'Turns ideas into structured business plans, validates founder-market fit, and pressure-tests strategy.',
|
|
@@ -228,7 +228,7 @@ exports.PERSONA_HIRE_CATALOG = {
|
|
|
228
228
|
},
|
|
229
229
|
maestro: {
|
|
230
230
|
displayName: 'MAESTRO',
|
|
231
|
-
role: 'Full-Brained
|
|
231
|
+
role: 'Full-Brained Employee',
|
|
232
232
|
emoji: '★',
|
|
233
233
|
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%)',
|
|
234
234
|
blurb: 'One AI employee who can take a job from any function and ship it back with evidence. You set the direction. You sign off on what ships. Maestro does the work.',
|
|
@@ -260,7 +260,7 @@ exports.PERSONA_AVATAR_CATALOG = {
|
|
|
260
260
|
procella: { seed: 'PROCELLA-procurement', bg: 'ccfbf1', style: 'notionists' },
|
|
261
261
|
banke: { seed: 'BANKe-banking-kyc', bg: 'ccfbf1', style: 'notionists' },
|
|
262
262
|
auditya: { seed: 'AUDITya-banking-audit', bg: 'e9d5ff', style: 'notionists' },
|
|
263
|
-
aida: { seed: '
|
|
263
|
+
aida: { seed: 'AIDa-ai-developer', bg: 'c7d2fe', style: 'notionists' },
|
|
264
264
|
};
|
|
265
265
|
function buildPersonaAvatarUrl(personaKey) {
|
|
266
266
|
const avatar = exports.PERSONA_AVATAR_CATALOG[personaKey];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-hub",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.289",
|
|
4
4
|
"description": "FRAIM Hub local companion package.",
|
|
5
5
|
"author": "Sid Mathur <sid.mathur@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/mathursrus/FRAIM#readme",
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
"electron-updater": "^6.8.9",
|
|
211
211
|
"express": "^5.2.1",
|
|
212
212
|
"extract-zip": "^2.0.1",
|
|
213
|
-
"fraim": "2.0.
|
|
213
|
+
"fraim": "2.0.289",
|
|
214
214
|
"mongodb": "^7.0.0",
|
|
215
215
|
"node-cron": "4.2.1",
|
|
216
216
|
"node-edge-tts": "^1.2.10",
|
package/public/ai-hub/script.js
CHANGED
|
@@ -23,7 +23,7 @@ const PAGE_SCOPED_JOBS = new Set(['organization-onboarding', 'manager-agreements
|
|
|
23
23
|
// invokedArea left runs started from the "wrong" tab unreachable from either rail.
|
|
24
24
|
// Issue #702: personas whose home is the MANAGER tab because their work is inherently
|
|
25
25
|
// cross-project and manager-facing (not project work). Per the spec (R1b), Ashley — the
|
|
26
|
-
//
|
|
26
|
+
// Executive Assistant is Manager-scoped. Every other hired persona works inside
|
|
27
27
|
// projects and belongs on the Projects tab only, NOT the Manager rail. Add a key here
|
|
28
28
|
// to surface a new manager-scoped persona.
|
|
29
29
|
const MANAGER_PERSONA_KEYS = new Set(['ashley']);
|
|
@@ -1156,7 +1156,6 @@ const SERVER_OWNED_CONV_FIELDS = ['messages', 'events', 'artifacts', 'run', 'del
|
|
|
1156
1156
|
// any inbound value. That is what preserves issue #913: a marker arriving over
|
|
1157
1157
|
// the wire is never trusted, only one this client set after a real fetch.
|
|
1158
1158
|
const CLIENT_ONLY_CONV_FIELDS = ['_bodyLoaded', '_bodyFetched', '_stopping'];
|
|
1159
|
-
const FULL_BODY_CONV_FIELDS = ['messages', 'events', 'artifacts', 'run', 'handoffSummary'];
|
|
1160
1159
|
function slimConversationForPersist(conv) {
|
|
1161
1160
|
if (!conv || typeof conv !== 'object') return conv;
|
|
1162
1161
|
const slim = { ...conv };
|
|
@@ -1175,7 +1174,13 @@ function conversationHasBody(conv) {
|
|
|
1175
1174
|
// instead of looping. Issue #913 stays satisfied because `_bodyFetched` is
|
|
1176
1175
|
// client-only and stripped from every inbound header.
|
|
1177
1176
|
if (conv._bodyFetched === true) return true;
|
|
1178
|
-
|
|
1177
|
+
// Issue #1416: `messages` is the only field that proves the transcript was actually
|
|
1178
|
+
// fetched. `events`/`artifacts`/`run`/`handoffSummary` can each arrive independently
|
|
1179
|
+
// via a lightweight status update (e.g. conversationDispatchAgentId()'s restart-recovery
|
|
1180
|
+
// notice sets `events` alone) without the message transcript ever having been fetched.
|
|
1181
|
+
// Treating any one of them as sufficient permanently short-circuited hydration for
|
|
1182
|
+
// Manager/Company conversations that picked up one of those fields first.
|
|
1183
|
+
return Object.prototype.hasOwnProperty.call(conv, 'messages');
|
|
1179
1184
|
}
|
|
1180
1185
|
|
|
1181
1186
|
function cleanConversationHeader(header) {
|
|
@@ -1821,7 +1826,7 @@ function coachEmployeeLabel(conv) {
|
|
|
1821
1826
|
const emp = getEmployeeStatus(agentName);
|
|
1822
1827
|
if (emp) return emp.label;
|
|
1823
1828
|
}
|
|
1824
|
-
return
|
|
1829
|
+
return NO_FRAIM_EMPLOYEE_LABEL;
|
|
1825
1830
|
}
|
|
1826
1831
|
|
|
1827
1832
|
// R3: resolve the logged-in manager's first name for dynamic panel kickers.
|
|
@@ -2936,6 +2941,7 @@ function conversationHasFraimEmployee(conv) {
|
|
|
2936
2941
|
}
|
|
2937
2942
|
|
|
2938
2943
|
function getEmployeeStatus(employeeId) {
|
|
2944
|
+
if (!employeeId) return null;
|
|
2939
2945
|
const baseId = baseHostIdForAgent(employeeId);
|
|
2940
2946
|
return (state.bootstrap?.employees || []).find((employee) => employee.id === baseId) || null;
|
|
2941
2947
|
}
|
|
@@ -13135,16 +13141,40 @@ function tfBuildManagerRunItem(conv) {
|
|
|
13135
13141
|
return btn;
|
|
13136
13142
|
}
|
|
13137
13143
|
|
|
13144
|
+
// #1416: capture each employee group's open/closed state from the area rail (Manager or
|
|
13145
|
+
// Company) before it is rebuilt, mirroring renderRail()'s preservedEmployeeGroupOpen() for
|
|
13146
|
+
// the Projects rail. Without this, tfRenderManager()/tfRenderCompany()'s ~1-1.5s poll-driven
|
|
13147
|
+
// rebuild wiped the DOM and re-created every group, so a manually collapsed group snapped
|
|
13148
|
+
// back open on the next tick and there was no way to tell a no-run group from one the user
|
|
13149
|
+
// deliberately expanded.
|
|
13150
|
+
function captureAreaEmployeeGroupOpenState(rail) {
|
|
13151
|
+
const openState = new Map();
|
|
13152
|
+
if (!rail) return openState;
|
|
13153
|
+
rail.querySelectorAll('details.conv-employee-group[data-employee-key]').forEach((details) => {
|
|
13154
|
+
const key = details.dataset ? details.dataset.employeeKey : '';
|
|
13155
|
+
if (key) openState.set(key, details.open);
|
|
13156
|
+
});
|
|
13157
|
+
return openState;
|
|
13158
|
+
}
|
|
13159
|
+
|
|
13138
13160
|
// #702: render a hired persona as an employee group on the Manager rail — the SAME
|
|
13139
13161
|
// visual as the Projects rail employee groups (avatar + name + role + count + "+" that
|
|
13140
13162
|
// opens the job palette), with the persona's MANAGER-invoked runs listed under it.
|
|
13141
13163
|
// Keeps a persona looking like an employee, consistent across tabs.
|
|
13142
|
-
function tfRenderAreaPersonaGroup(rail, persona, area) {
|
|
13164
|
+
function tfRenderAreaPersonaGroup(rail, persona, area, employeeGroupOpenState) {
|
|
13143
13165
|
const sample = { personaKey: persona.key };
|
|
13144
13166
|
const runs = tfAreaScopedConversations(area).filter((c) => c.personaKey === persona.key);
|
|
13145
13167
|
const details = document.createElement('details');
|
|
13146
13168
|
details.className = 'conv-employee-group';
|
|
13147
|
-
details.
|
|
13169
|
+
details.dataset.employeeKey = persona.key;
|
|
13170
|
+
// #1416: preserve the user's toggle across the poll-driven rebuild. A group with no
|
|
13171
|
+
// prior state (first render) defaults open only if it has an active run — e.g. the
|
|
13172
|
+
// owning employee's currently-running job — same "has an active run, or you manually
|
|
13173
|
+
// expanded it" contract the issue calls out for the Projects rail; otherwise collapsed.
|
|
13174
|
+
const defaultOpen = runs.some((c) => conversationUiState(c) !== 'complete');
|
|
13175
|
+
details.open = employeeGroupOpenState && employeeGroupOpenState.has(persona.key)
|
|
13176
|
+
? employeeGroupOpenState.get(persona.key)
|
|
13177
|
+
: defaultOpen;
|
|
13148
13178
|
const summary = document.createElement('summary');
|
|
13149
13179
|
summary.className = 'conv-employee-tab';
|
|
13150
13180
|
const avatar = buildConversationEmployeeAvatar(sample, 'conv-employee-avatar');
|
|
@@ -13187,7 +13217,7 @@ function tfRenderAreaPersonaGroup(rail, persona, area) {
|
|
|
13187
13217
|
// is the area's own top-level job run (manager-agreements / org onboarding) or any other
|
|
13188
13218
|
// run with no persona group to live under; it gets its own rail entry unless a group
|
|
13189
13219
|
// below will already list it.
|
|
13190
|
-
function tfRenderAreaEmployeeRail(rail, area, ownerlessConv) {
|
|
13220
|
+
function tfRenderAreaEmployeeRail(rail, area, ownerlessConv, employeeGroupOpenState) {
|
|
13191
13221
|
const areaPersonas = tfAreaRailPersonas(area);
|
|
13192
13222
|
// A group only actually lists conversations tfAreaScopedConversations(area) returns
|
|
13193
13223
|
// (i.e. correctly scope/invokedArea-tagged). A legacy conv that predates that tagging
|
|
@@ -13204,7 +13234,7 @@ function tfRenderAreaEmployeeRail(rail, area, ownerlessConv) {
|
|
|
13204
13234
|
rail.appendChild(head);
|
|
13205
13235
|
any = true;
|
|
13206
13236
|
}
|
|
13207
|
-
tfRenderAreaPersonaGroup(rail, persona, area);
|
|
13237
|
+
tfRenderAreaPersonaGroup(rail, persona, area, employeeGroupOpenState);
|
|
13208
13238
|
}
|
|
13209
13239
|
if (any) {
|
|
13210
13240
|
const pNote = document.createElement('div'); pNote.className = 'area-rail-note';
|
|
@@ -13259,6 +13289,9 @@ function tfRenderCompany() {
|
|
|
13259
13289
|
if (!state.brandEditorDraftActive && typeof tfRenderBrandEditor === 'function') tfRenderBrandEditor();
|
|
13260
13290
|
const rail = document.getElementById('company-rail');
|
|
13261
13291
|
if (rail) {
|
|
13292
|
+
// #1416: capture the current open/closed state before wiping the rail so the
|
|
13293
|
+
// ~1.5s poll-driven rebuild below doesn't snap a manually collapsed group back open.
|
|
13294
|
+
const employeeGroupOpenState = captureAreaEmployeeGroupOpenState(rail);
|
|
13262
13295
|
rail.innerHTML = '';
|
|
13263
13296
|
const orgConv = tfActiveOrgConv();
|
|
13264
13297
|
const orgConvActive = !!orgConv;
|
|
@@ -13277,7 +13310,7 @@ function tfRenderCompany() {
|
|
|
13277
13310
|
// #1398: FRAIMworker (and any hired employee with a company-scoped run, e.g. Aida)
|
|
13278
13311
|
// get the same employee-group presentation as the Manager rail — not just an orphan
|
|
13279
13312
|
// entry for the single "most active" org conv.
|
|
13280
|
-
tfRenderAreaEmployeeRail(rail, 'company', orgConv);
|
|
13313
|
+
tfRenderAreaEmployeeRail(rail, 'company', orgConv, employeeGroupOpenState);
|
|
13281
13314
|
tfReopenPendingRunDelete(rail);
|
|
13282
13315
|
}
|
|
13283
13316
|
const profile = document.getElementById('company-profile');
|
|
@@ -13424,6 +13457,9 @@ function tfRenderManager() {
|
|
|
13424
13457
|
// #521 R6: manager-level job (manager-agreements) lives ONLY in this left rail.
|
|
13425
13458
|
const rail = document.getElementById('manager-rail');
|
|
13426
13459
|
if (rail) {
|
|
13460
|
+
// #1416: capture the current open/closed state before wiping the rail so the
|
|
13461
|
+
// ~1s poll-driven rebuild below doesn't snap a manually collapsed group back open.
|
|
13462
|
+
const employeeGroupOpenState = captureAreaEmployeeGroupOpenState(rail);
|
|
13427
13463
|
rail.innerHTML = '';
|
|
13428
13464
|
const mgrConv = tfActiveMgrConv();
|
|
13429
13465
|
const mgrConvActive = !!mgrConv;
|
|
@@ -13440,7 +13476,7 @@ function tfRenderManager() {
|
|
|
13440
13476
|
// Aida's manager-scoped runs) — the same avatar + name + runs + "+" presentation as the
|
|
13441
13477
|
// Projects rail. `mgrConv` (the area's own top-level run, e.g. manager-agreements) gets
|
|
13442
13478
|
// its own rail entry unless a group above already lists it.
|
|
13443
|
-
tfRenderAreaEmployeeRail(rail, 'manager', mgrConv);
|
|
13479
|
+
tfRenderAreaEmployeeRail(rail, 'manager', mgrConv, employeeGroupOpenState);
|
|
13444
13480
|
// #824: the manager rail also attaches run-delete controls; re-attach an open
|
|
13445
13481
|
// confirm this innerHTML='' rebuild would otherwise drop.
|
|
13446
13482
|
tfReopenPendingRunDelete(rail);
|
|
@@ -717,7 +717,16 @@
|
|
|
717
717
|
}
|
|
718
718
|
};
|
|
719
719
|
submit.addEventListener('click', onSubmit);
|
|
720
|
-
input.addEventListener('keydown', (e) => {
|
|
720
|
+
input.addEventListener('keydown', (e) => {
|
|
721
|
+
if (e.key === 'Enter') {
|
|
722
|
+
onSubmit();
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
if (e.key === 'Tab' && !e.shiftKey) {
|
|
726
|
+
e.preventDefault();
|
|
727
|
+
submit.focus();
|
|
728
|
+
}
|
|
729
|
+
});
|
|
721
730
|
card.appendChild(submit);
|
|
722
731
|
|
|
723
732
|
CHECKLIST_EL.appendChild(card);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>
|
|
6
|
+
<title>AIDa · AI Developer · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -99,15 +99,15 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
99
99
|
|
|
100
100
|
<section class="hero">
|
|
101
101
|
<div class="avatar-ring">
|
|
102
|
-
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=
|
|
102
|
+
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=AIDa-ai-developer&backgroundColor=c7d2fe&radius=50" width="96" height="96" alt="AIDa avatar" style="border-radius:50%;">
|
|
103
103
|
</div>
|
|
104
104
|
<div class="role-chip">AI ENGINEERING</div>
|
|
105
|
-
<h1>Meet <span>
|
|
106
|
-
<p>Agents that work. Evals that prove it.
|
|
105
|
+
<h1>Meet <span>AIDa</span></h1>
|
|
106
|
+
<p>Agents that work. Evals that prove it. AIDa can design production AI agents, connect them to tools and data, and validate their behavior end to end.</p>
|
|
107
107
|
</section>
|
|
108
108
|
|
|
109
109
|
<div class="section-label">
|
|
110
|
-
<h2>What
|
|
110
|
+
<h2>What AIDa Can Build</h2>
|
|
111
111
|
<div class="section-divider"></div>
|
|
112
112
|
</div>
|
|
113
113
|
|
|
@@ -128,10 +128,10 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
128
128
|
<div class="narrative">
|
|
129
129
|
<div class="narrative-step">
|
|
130
130
|
<div class="step-label">The Ask</div>
|
|
131
|
-
<div class="step-text">A team can describe a use case and a target platform.
|
|
131
|
+
<div class="step-text">A team can describe a use case and a target platform. AIDa can scope the agent design, instructions, tool/knowledge configuration, and deployment package.</div>
|
|
132
132
|
</div>
|
|
133
133
|
<div class="narrative-step">
|
|
134
|
-
<div class="step-label">What
|
|
134
|
+
<div class="step-label">What AIDa Can Build</div>
|
|
135
135
|
<div class="step-text">An agent definition, platform-specific deployment package, tool permissions evidence, and a validation walkthrough against the intended use case.</div>
|
|
136
136
|
</div>
|
|
137
137
|
<div class="narrative-step">
|
|
@@ -165,10 +165,10 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
165
165
|
<div class="narrative">
|
|
166
166
|
<div class="narrative-step">
|
|
167
167
|
<div class="step-label">The Ask</div>
|
|
168
|
-
<div class="step-text">A team can supply a dataset, success criteria, and the agent or model under test.
|
|
168
|
+
<div class="step-text">A team can supply a dataset, success criteria, and the agent or model under test. AIDa can structure evaluation cases covering task completion, tool use, hallucination, and safety.</div>
|
|
169
169
|
</div>
|
|
170
170
|
<div class="narrative-step">
|
|
171
|
-
<div class="step-label">What
|
|
171
|
+
<div class="step-label">What AIDa Can Build</div>
|
|
172
172
|
<div class="step-text">A runner-compatible eval suite with dataset provenance, metric definitions, approval-evidenced thresholds, and an executed baseline result.</div>
|
|
173
173
|
</div>
|
|
174
174
|
<div class="narrative-step">
|
|
@@ -194,10 +194,10 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
194
194
|
<div class="narrative">
|
|
195
195
|
<div class="narrative-step">
|
|
196
196
|
<div class="step-label">The Ask</div>
|
|
197
|
-
<div class="step-text">A team can name the target web product and the capabilities to expose.
|
|
197
|
+
<div class="step-text">A team can name the target web product and the capabilities to expose. AIDa can handle transport, authentication, least-privilege tool selection, and client connection instructions.</div>
|
|
198
198
|
</div>
|
|
199
199
|
<div class="narrative-step">
|
|
200
|
-
<div class="step-label">What
|
|
200
|
+
<div class="step-label">What AIDa Can Build</div>
|
|
201
201
|
<div class="step-text">A functioning MCP server for the target product, with authentication wired, a tool manifest, and verified connection instructions for AI clients including Claude, Cursor, and GitHub Copilot.</div>
|
|
202
202
|
</div>
|
|
203
203
|
<div class="narrative-step">
|
|
@@ -223,10 +223,10 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
223
223
|
<div class="narrative">
|
|
224
224
|
<div class="narrative-step">
|
|
225
225
|
<div class="step-label">The Ask</div>
|
|
226
|
-
<div class="step-text">A team can supply a baseline agent and evaluation dataset.
|
|
226
|
+
<div class="step-text">A team can supply a baseline agent and evaluation dataset. AIDa can run the evaluation using the platform's supported interface or the repository's existing eval harness.</div>
|
|
227
227
|
</div>
|
|
228
228
|
<div class="narrative-step">
|
|
229
|
-
<div class="step-label">What
|
|
229
|
+
<div class="step-label">What AIDa Can Build</div>
|
|
230
230
|
<div class="step-text">A scored evaluation artifact linking each result to its evaluator, dataset version, run timestamp, and trace evidence location.</div>
|
|
231
231
|
</div>
|
|
232
232
|
<div class="narrative-step">
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>AshLey ·
|
|
6
|
+
<title>AshLey · Executive Assistant · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -233,7 +233,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
233
233
|
<div class="avatar-ring">
|
|
234
234
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=Ashley-assistant&backgroundColor=fde68a&radius=50" width="96" height="96" alt="Ashley-assistant avatar" style="border-radius:50%;">
|
|
235
235
|
</div>
|
|
236
|
-
<div class="role-chip">
|
|
236
|
+
<div class="role-chip">Executive Assistant</div>
|
|
237
237
|
<h1>Your calendar cleared.<br>Your decisions <span>ready</span>.</h1>
|
|
238
238
|
<p>Your calendar cleared. Your decisions ready. Your meetings worth attending.</p>
|
|
239
239
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>AUDITya -
|
|
6
|
+
<title>AUDITya - Banking Auditor - FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
|
@@ -50,7 +50,7 @@ th { color:var(--accent); font-size:11px; text-transform:uppercase; letter-spaci
|
|
|
50
50
|
</header>
|
|
51
51
|
<section class="hero">
|
|
52
52
|
<div class="avatar"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=AUDITya-banking-audit&backgroundColor=e9d5ff&radius=50" width="96" height="96" alt="AUDITya banking auditor avatar" style="border-radius:50%;"></div>
|
|
53
|
-
<div class="chip">
|
|
53
|
+
<div class="chip">Banking Auditor</div>
|
|
54
54
|
<h1>AUDITya reviews AI banking work with <span>evidence discipline</span>.</h1>
|
|
55
55
|
<p>AUDITya audits a completed KYC run, checks whether the decision is supported by evidence, records exceptions, and produces a report that can be revisited in a future review.</p>
|
|
56
56
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>BANKe -
|
|
6
|
+
<title>BANKe - Banking KYC Employee - FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
|
@@ -50,7 +50,7 @@ th { color:var(--accent); font-size:11px; text-transform:uppercase; letter-spaci
|
|
|
50
50
|
</header>
|
|
51
51
|
<section class="hero">
|
|
52
52
|
<div class="avatar"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=BANKe-banking-kyc&backgroundColor=ccfbf1&radius=50" width="96" height="96" alt="BANKe banking KYC avatar" style="border-radius:50%;"></div>
|
|
53
|
-
<div class="chip">
|
|
53
|
+
<div class="chip">Banking KYC Employee</div>
|
|
54
54
|
<h1>BANKe turns KYC work into <span>auditable evidence</span>.</h1>
|
|
55
55
|
<p>BANKe reviews consent-backed banking cases, records source evidence, makes a bounded KYC decision, and leaves receipts that a separate auditor can inspect later.</p>
|
|
56
56
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>BeZa ·
|
|
6
|
+
<title>BeZa · Business Strategist · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -324,7 +324,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
324
324
|
<div class="avatar-ring">
|
|
325
325
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=BEZA-strategist&backgroundColor=c7d2fe&radius=50" width="96" height="96" alt="BEZA-strategist avatar" style="border-radius:50%;">
|
|
326
326
|
</div>
|
|
327
|
-
<div class="role-chip">
|
|
327
|
+
<div class="role-chip">Business Strategist</div>
|
|
328
328
|
<h1>Validates the idea. Prices the product.<br>Builds the <span>plan</span>. Ships the deck.</h1>
|
|
329
329
|
<p>BeZa pressure-tests early ideas in 24 hours, turns gut-feel pricing into a data-backed structure, and writes the business plan your first investor meeting actually needs — without the 40-page consulting deliverable.</p>
|
|
330
330
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>CAREEna |
|
|
6
|
+
<title>CAREEna | Career Coach | FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
|
@@ -349,7 +349,7 @@ body {
|
|
|
349
349
|
<section class="hero">
|
|
350
350
|
<div class="hero-grid">
|
|
351
351
|
<div class="hero-panel">
|
|
352
|
-
<div class="hero-chip">
|
|
352
|
+
<div class="hero-chip">Career Coach</div>
|
|
353
353
|
<h1>Land the role with stronger applications, sharper interviews, and better timing.</h1>
|
|
354
354
|
<p>CAREEna helps candidates turn a loose job search into a disciplined campaign: better-targeted openings, tighter application packages, stronger networking moves, and interview prep grounded in the actual company and role.</p>
|
|
355
355
|
<div class="hero-metrics">
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>CaSey ·
|
|
6
|
+
<title>CaSey · Customer Success + Support · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -254,7 +254,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
254
254
|
<div class="avatar-ring">
|
|
255
255
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=CASEY-cx&backgroundColor=a5f3fc&radius=50" width="96" height="96" alt="CASEY-cx avatar" style="border-radius:50%;">
|
|
256
256
|
</div>
|
|
257
|
-
<div class="role-chip">
|
|
257
|
+
<div class="role-chip">Customer Success + Support</div>
|
|
258
258
|
<h1>Customers stay.<br><span>Issues close.</span> Health scores rise.</h1>
|
|
259
259
|
<p>CaSey monitors account health signals, triages support queues, and runs survey campaigns that customers actually respond to — so churn stays low and your team stays focused.</p>
|
|
260
260
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>CELiA ·
|
|
6
|
+
<title>CELiA · Legal Counsel · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -233,7 +233,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
233
233
|
<div class="avatar-ring">
|
|
234
234
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=CELA-legal&backgroundColor=cbd5e1&radius=50" width="96" height="96" alt="CELA-legal avatar" style="border-radius:50%;">
|
|
235
235
|
</div>
|
|
236
|
-
<div class="role-chip">
|
|
236
|
+
<div class="role-chip">Legal Counsel</div>
|
|
237
237
|
<h1>Contracts reviewed.<br><span>IP protected.</span> Compliance filed.</h1>
|
|
238
238
|
<p>CELiA reviews contracts for hidden risk, drafts multi-party NDAs, and files provisional patents — so your legal work gets done before the deadline, not after.</p>
|
|
239
239
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>DEIdre ·
|
|
6
|
+
<title>DEIdre · Inclusion Leader · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -256,7 +256,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
256
256
|
<div class="avatar-ring">
|
|
257
257
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=DEIDRE-inclusion-leader&backgroundColor=e9d5ff&radius=50" width="96" height="96" alt="DEIDRE-inclusion-leader avatar" style="border-radius:50%;">
|
|
258
258
|
</div>
|
|
259
|
-
<div class="role-chip">
|
|
259
|
+
<div class="role-chip">Inclusion Leader</div>
|
|
260
260
|
<h1>Data-driven inclusion.<br><span>Policies that work.</span> Teams that stay.</h1>
|
|
261
261
|
<p>DEIdre finds the process gaps nobody measured, builds onboarding toolkits that cut early attrition, and audits hiring algorithms for disparate impact — before they become an equity and inclusion issue.</p>
|
|
262
262
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>HaRi ·
|
|
6
|
+
<title>HaRi · HR Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -195,7 +195,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
195
195
|
<div class="avatar-ring">
|
|
196
196
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=HARI-hr&backgroundColor=ccfbf1&radius=50" width="96" height="96" alt="HARI-hr avatar" style="border-radius:50%;">
|
|
197
197
|
</div>
|
|
198
|
-
<div class="role-chip">
|
|
198
|
+
<div class="role-chip">HR Manager</div>
|
|
199
199
|
<h1>Onboards fast. Reviews fairly.<br>Keeps the <span>team whole</span>.</h1>
|
|
200
200
|
<p>HaRi handles the full HR lifecycle: structured onboarding that actually sticks, performance reviews that develop people, and benefits analysis that saves real money.</p>
|
|
201
201
|
</section>
|
|
@@ -129,13 +129,13 @@ body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg); c
|
|
|
129
129
|
</div>
|
|
130
130
|
<div class="employee-grid">
|
|
131
131
|
|
|
132
|
-
<!--
|
|
132
|
+
<!-- AIDa -->
|
|
133
133
|
<div class="emp-card" style="cursor:pointer;">
|
|
134
134
|
<div class="emp-card-top">
|
|
135
|
-
<div class="emp-avatar" style="background:linear-gradient(135deg,#4f46e5,#06b6d4,#10b981);"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=
|
|
135
|
+
<div class="emp-avatar" style="background:linear-gradient(135deg,#4f46e5,#06b6d4,#10b981);"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=AIDa-ai-developer&backgroundColor=c7d2fe&radius=50" width="56" height="56" alt="aida" style="border-radius:50%;"></div>
|
|
136
136
|
<div class="emp-info">
|
|
137
|
-
<div class="emp-role" style="color:#4f46e5;">AI
|
|
138
|
-
<div class="emp-name">
|
|
137
|
+
<div class="emp-role" style="color:#4f46e5;">AI Developer</div>
|
|
138
|
+
<div class="emp-name">AIDa</div>
|
|
139
139
|
<div class="emp-tagline">Agents that work. Evals that prove it.</div>
|
|
140
140
|
</div>
|
|
141
141
|
</div>
|
|
@@ -640,7 +640,7 @@ body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg); c
|
|
|
640
640
|
<div class="emp-card-top">
|
|
641
641
|
<div class="emp-avatar" style="background:linear-gradient(135deg,#10b981,#0ea5e9,#6366f1);"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=MAESTRO-founder-mode&backgroundColor=fde68a&radius=50" width="56" height="56" alt="maestro" style="border-radius:50%;"></div>
|
|
642
642
|
<div class="emp-info">
|
|
643
|
-
<div class="emp-role" style="color:#10b981;">Full-Brained
|
|
643
|
+
<div class="emp-role" style="color:#10b981;">Full-Brained Employee</div>
|
|
644
644
|
<div class="emp-name">MAESTRO</div>
|
|
645
645
|
<div class="emp-tagline">Every FRAIM skill. Every FRAIM job. One hire.</div>
|
|
646
646
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>MAESTRO · Full-Brained
|
|
6
|
+
<title>MAESTRO · Full-Brained Employee · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -176,7 +176,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
176
176
|
<div class="avatar-ring">
|
|
177
177
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=MAESTRO-founder-mode&backgroundColor=fde68a&radius=50" width="96" height="96" alt="MAESTRO-founder-mode avatar" style="border-radius:50%;">
|
|
178
178
|
</div>
|
|
179
|
-
<div class="role-chip">Full-Brained
|
|
179
|
+
<div class="role-chip">Full-Brained Employee</div>
|
|
180
180
|
<h1>Every FRAIM skill.<br>Every FRAIM job. <span>One hire.</span></h1>
|
|
181
181
|
<p>Every FRAIM skill. Every FRAIM job. One hire.</p>
|
|
182
182
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>MANdy ·
|
|
6
|
+
<title>MANdy · Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -204,7 +204,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
204
204
|
<div class="avatar-ring">
|
|
205
205
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=MANDY-manager&backgroundColor=ede9fe&radius=50" width="96" height="96" alt="MANDY-manager avatar" style="border-radius:50%;">
|
|
206
206
|
</div>
|
|
207
|
-
<div class="role-chip">
|
|
207
|
+
<div class="role-chip">Manager</div>
|
|
208
208
|
<h1>Orchestrates the team.<br>Delivers the <span>result</span>.</h1>
|
|
209
209
|
<p>Orchestrates the team. Delivers the result. Asks for nothing in return.</p>
|
|
210
210
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>MONa ·
|
|
6
|
+
<title>MONa · Finance Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -279,7 +279,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
279
279
|
<div class="avatar-ring">
|
|
280
280
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=MONA-finance-manager&backgroundColor=d1fae5&radius=50" width="96" height="96" alt="MONa finance manager avatar" style="border-radius:50%;">
|
|
281
281
|
</div>
|
|
282
|
-
<div class="role-chip">
|
|
282
|
+
<div class="role-chip">Finance Manager</div>
|
|
283
283
|
<h1>Financial clarity. Fast.<br>Models that <span>drive decisions</span>.</h1>
|
|
284
284
|
<p>MONa builds three-statement models without a consultant, runs FP&A forecasts with driver-based scenarios, and delivers monthly close commentary that helps your board understand what actually happened and why.</p>
|
|
285
285
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>PaM ·
|
|
6
|
+
<title>PaM · Product Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
|
@@ -443,7 +443,7 @@ body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--tex
|
|
|
443
443
|
<div class="avatar-ring">
|
|
444
444
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=PAM-product&backgroundColor=ddd6fe&radius=50" width="96" height="96" alt="PAM-product avatar" style="border-radius:50%;">
|
|
445
445
|
</div>
|
|
446
|
-
<div class="role-chip">
|
|
446
|
+
<div class="role-chip">Product Manager</div>
|
|
447
447
|
<h1>Specs that ship,<br>not <span>slide decks</span></h1>
|
|
448
448
|
<p>PaM turns vague ideas into traceable requirements, phased roadmaps, and acceptance criteria that engineers can execute on — without ambiguity, without meetings.</p>
|
|
449
449
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>PROCella ·
|
|
6
|
+
<title>PROCella · Procurement Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -69,7 +69,7 @@ code,.mono { font-family:'JetBrains Mono',monospace; }
|
|
|
69
69
|
</header>
|
|
70
70
|
<section class="hero">
|
|
71
71
|
<div class="avatar-ring"><img src="https://api.dicebear.com/9.x/notionists/svg?seed=PROCELLA-procurement&backgroundColor=ccfbf1&radius=50" width="96" height="96" alt="PROCella procurement manager avatar"></div>
|
|
72
|
-
<div class="role-chip">
|
|
72
|
+
<div class="role-chip">Procurement Manager</div>
|
|
73
73
|
<h1>PROCella makes supplier decisions <span>defensible</span>.</h1>
|
|
74
74
|
<p>PROCella frames procurement strategy, builds qualified supplier options, turns RFx packages into comparable responses, and protects the buyer's leverage through approval and acceptance gates.</p>
|
|
75
75
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>QAsm ·
|
|
6
|
+
<title>QAsm · QA Engineer · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -254,7 +254,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
254
254
|
<div class="avatar-ring">
|
|
255
255
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=QASM-quality&backgroundColor=a7f3d0&radius=50" width="96" height="96" alt="QASM-quality avatar" style="border-radius:50%;">
|
|
256
256
|
</div>
|
|
257
|
-
<div class="role-chip">
|
|
257
|
+
<div class="role-chip">QA Engineer</div>
|
|
258
258
|
<h1>If it can break,<br>I <span>find it</span></h1>
|
|
259
259
|
<p>If I find it, it gets fixed before you ship.</p>
|
|
260
260
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>RECardo ·
|
|
6
|
+
<title>RECardo · Recruiter · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -180,7 +180,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
180
180
|
<div class="avatar-ring">
|
|
181
181
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=RICARDO-recruiter&backgroundColor=ede9fe&radius=50" width="96" height="96" alt="RICARDO-recruiter avatar" style="border-radius:50%;">
|
|
182
182
|
</div>
|
|
183
|
-
<div class="role-chip">
|
|
183
|
+
<div class="role-chip">Recruiter</div>
|
|
184
184
|
<h1>Sourced, screened, scheduled.<br>You just do the <span>interviews</span>.</h1>
|
|
185
185
|
<p>RECardo runs full-cycle recruiting: sourcing candidates who actually fit, writing job posts engineers read, and coordinating interview loops without the calendar chaos.</p>
|
|
186
186
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SADE ·
|
|
6
|
+
<title>SADE · Salesforce Developer · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -230,7 +230,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
230
230
|
<div class="avatar-ring">
|
|
231
231
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=SADE-salesforce&backgroundColor=bae6fd&radius=50" width="96" height="96" alt="SADE-salesforce avatar" style="border-radius:50%;">
|
|
232
232
|
</div>
|
|
233
|
-
<div class="role-chip">
|
|
233
|
+
<div class="role-chip">Salesforce Developer</div>
|
|
234
234
|
<h1>Clean orgs.<br><span>Automations</span> that actually run.</h1>
|
|
235
235
|
<p>Reports that tell the truth.</p>
|
|
236
236
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SAM ·
|
|
6
|
+
<title>SAM · Sales Account Manager · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -283,7 +283,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
283
283
|
<div class="avatar-ring">
|
|
284
284
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=SAM-sales-account&backgroundColor=d1fae5&radius=50" width="96" height="96" alt="SAM-sales-account avatar" style="border-radius:50%;">
|
|
285
285
|
</div>
|
|
286
|
-
<div class="role-chip">
|
|
286
|
+
<div class="role-chip">Sales Account Manager</div>
|
|
287
287
|
<h1>More pipeline. More signal.<br>More <span>deals closed</span>.</h1>
|
|
288
288
|
<p>SAM finds qualified prospects without a database subscription, spots at-risk accounts before they churn, and delivers pipeline reviews that free your VP of Sales from 90 minutes of spreadsheet work every Friday.</p>
|
|
289
289
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SEChar |
|
|
6
|
+
<title>SEChar | Security Engineer | FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
|
@@ -334,7 +334,7 @@ h1 {
|
|
|
334
334
|
<section class="hero">
|
|
335
335
|
<div class="hero-grid">
|
|
336
336
|
<div class="panel">
|
|
337
|
-
<div class="chip">
|
|
337
|
+
<div class="chip">Security Engineer</div>
|
|
338
338
|
<h1>Setup the baseline. Run the queue. Clear the risk.</h1>
|
|
339
339
|
<p>SEChar sets the launch baseline, keeps the findings queue coherent, and still handles the diff-scoped reviews and remediation calls teams expect from an applied security partner.</p>
|
|
340
340
|
<div class="hero-metrics">
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SREya ·
|
|
6
|
+
<title>SREya · Site Reliability Engineer · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -276,7 +276,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
276
276
|
<div class="avatar-ring">
|
|
277
277
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=SREYA-site-reliability&backgroundColor=dbeafe&radius=50" width="96" height="96" alt="SREya site reliability engineer avatar" style="border-radius:50%;">
|
|
278
278
|
</div>
|
|
279
|
-
<div class="role-chip">
|
|
279
|
+
<div class="role-chip">Site Reliability Engineer</div>
|
|
280
280
|
<h1>SLOs that reflect user pain.<br>Incidents <span>resolved, not survived</span>.</h1>
|
|
281
281
|
<p>SREya designs error budgets before you need them, runs structured incident command that cuts MTTR in half, and delivers quarterly reliability reviews that give your on-call team a roadmap instead of a burnout spiral.</p>
|
|
282
282
|
</section>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SWEn ·
|
|
6
|
+
<title>SWEn · Software Engineer · FRAIM Portfolio</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
@@ -254,7 +254,7 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
254
254
|
<div class="avatar-ring">
|
|
255
255
|
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=SWEN-engineer&backgroundColor=bfdbfe&radius=50" width="96" height="96" alt="SWEN-engineer avatar" style="border-radius:50%;">
|
|
256
256
|
</div>
|
|
257
|
-
<div class="role-chip">
|
|
257
|
+
<div class="role-chip">Software Engineer</div>
|
|
258
258
|
<h1>Ships clean code,<br>not <span>promises</span></h1>
|
|
259
259
|
<p>SWEn delivers production-ready implementations: type-safe APIs, test coverage, real artifacts in the codebase — not prototype code masquerading as ship-ready work.</p>
|
|
260
260
|
</section>
|
|
@@ -314,13 +314,13 @@ code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
|
314
314
|
<span class="t-kw">export const</span> <span class="t-val">PERSONA_HIRE_CATALOG</span> <span class="t-op">=</span> {
|
|
315
315
|
huxley<span class="t-op">:</span> {
|
|
316
316
|
displayName<span class="t-op">:</span> <span class="t-str">'hUXley'</span>,
|
|
317
|
-
role<span class="t-op">:</span> <span class="t-str">'
|
|
317
|
+
role<span class="t-op">:</span> <span class="t-str">'UX / Brand Designer'</span>,
|
|
318
318
|
jobPriceCents<span class="t-op">:</span> <span class="t-num">14900</span>,
|
|
319
319
|
fulltimePriceCents<span class="t-op">:</span> <span class="t-num">54900</span>,
|
|
320
320
|
},
|
|
321
321
|
pam<span class="t-op">:</span> {
|
|
322
322
|
displayName<span class="t-op">:</span> <span class="t-str">'PaM'</span>,
|
|
323
|
-
role<span class="t-op">:</span> <span class="t-str">'
|
|
323
|
+
role<span class="t-op">:</span> <span class="t-str">'Product Manager'</span>,
|
|
324
324
|
jobPriceCents<span class="t-op">:</span> <span class="t-num">7900</span>,
|
|
325
325
|
fulltimePriceCents<span class="t-op">:</span> <span class="t-num">49900</span>,
|
|
326
326
|
},
|