fraim 2.0.109 β†’ 2.0.114

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 CHANGED
@@ -1,5 +1,5 @@
1
- # πŸš€ FRAIM: Framework for Rigor-based AI Management
2
- **"FRAIM is a step towards the future of how we work."** - Transforming ideas into production code by converting you into an AI manager orchestrating multiple agents with enterprise-grade discipline.
1
+ # πŸš€ FRAIM β€” AI Workforce Infrastructure
2
+ **"Brilliant AI isn't how industries get built. Organizations are."** β€” FRAIM transforms every layer of the AI-powered company at once: **AI agents** become an accountable, improving workforce; **their operators** become capable AI managers who hold the line on quality, delegation, and evidence; and **executives** gain clear optics on AI proficiency across the entire organization.
3
3
 
4
4
 
5
5
  πŸš€ **The Problem with AI Coding Today**
@@ -36,7 +36,7 @@ R - Retrospectives: Continuous learning from experience
36
36
 
37
37
  πŸ€– **Works with any AI agent** (Cursor, Claude, Windsurf) - no vendor lock-in.
38
38
 
39
- **The bottom line:** FRAIM isn't just about using AIβ€”it's about managing AI teams with the same discipline you'd apply to human developers.
39
+ **The bottom line:** FRAIM isn't just about using AI β€” it transforms every layer of your AI-powered company: agents become an accountable workforce, operators become capable AI managers, and executives gain clear optics on AI proficiency across the whole org.
40
40
 
41
41
 
42
42
 
@@ -448,9 +448,9 @@ gh issue edit 123 --remove-label "phase:impl" --add-label "phase:tests"
448
448
 
449
449
  ## 🎯 **The Bottom Line**
450
450
 
451
- **FRAIM isn't just about using AIβ€”it's about managing AI teams with the same discipline you'd apply to human teams.**
451
+ **FRAIM isn't just about using AI β€” it transforms every layer of your AI-powered company: agents become an accountable workforce, operators become capable AI managers, and executives gain clear optics on AI proficiency across the whole org.**
452
452
 
453
- Stop fighting with AI agents. Start orchestrating them.
453
+ Stop fighting with AI agents. Start building your AI organization.
454
454
 
455
455
  **This is the future of how we work.**
456
456
 
@@ -637,10 +637,10 @@ const runSetup = async (options) => {
637
637
  console.log(chalk_1.default.green('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
638
638
  console.log(chalk_1.default.green(' FRAIM is ready!'));
639
639
  console.log(chalk_1.default.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
640
- console.log(chalk_1.default.white('\n FRAIM is an AI management layer that turns you into'));
641
- console.log(chalk_1.default.white(' a manager of AI agents. Run multiple agents through'));
642
- console.log(chalk_1.default.white(' structured jobs, get manager-style coaching, and build'));
643
- console.log(chalk_1.default.white(' a learning loop where agents improve over time.'));
640
+ console.log(chalk_1.default.white('\n FRAIM is AI Workforce Infrastructure. It transforms every'));
641
+ console.log(chalk_1.default.white(' layer of your AI-powered work at once: AI agents become an'));
642
+ console.log(chalk_1.default.white(' accountable workforce, you become a capable AI manager, and'));
643
+ console.log(chalk_1.default.white(' your leadership gains clear optics on AI proficiency.'));
644
644
  console.log(chalk_1.default.gray('\n 60+ jobs across engineering, marketing, fundraising,'));
645
645
  console.log(chalk_1.default.gray(' legal, product, hiring, customer development, and more.'));
646
646
  // Show which IDEs were configured and how to use FRAIM in each
@@ -20,7 +20,8 @@
20
20
  * seekMentoring handler (e.g., when the local AIMentor errors).
21
21
  */
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.REQUIRED_QUALITY_FIELDS = exports.QUALITY_PRODUCING_JOBS = void 0;
23
+ exports.REQUIRED_QUALITY_FIELDS = exports.ALL_STAGE_CATEGORIES = exports.STAGE_DISPLAY_NAMES = exports.STAGE_CATEGORY_MAP = exports.QUALITY_PRODUCING_JOBS = void 0;
24
+ exports.getRequiredFieldsForJob = getRequiredFieldsForJob;
24
25
  exports.validateQualityEvidence = validateQualityEvidence;
25
26
  exports.buildQualityRejectionMessage = buildQualityRejectionMessage;
26
27
  /**
@@ -28,15 +29,64 @@ exports.buildQualityRejectionMessage = buildQualityRejectionMessage;
28
29
  * via `evidence.quality` on their final seekMentoring completion.
29
30
  */
30
31
  exports.QUALITY_PRODUCING_JOBS = [
32
+ // Customer Development
31
33
  'process-interview-notes',
32
- 'triage-customer-needs'
34
+ 'triage-customer-needs',
35
+ // Business Strategy
36
+ 'business-plan-creation',
37
+ 'pricing-strategy-definition',
38
+ 'founder-market-fit-analysis',
39
+ 'review-business-strategy',
40
+ // Product Quality
41
+ 'code-quality-assessment',
42
+ // Test Quality
43
+ 'test-standards-evaluation',
44
+ 'test-coverage-evaluation',
45
+ 'review-test-quality',
33
46
  ];
34
47
  /**
35
- * Required numeric fields inside `evidence.quality` for QUALITY_PRODUCING_JOBS.
36
- * The schema is intentionally lenient beyond these β€” extra fields are
37
- * allowed so per-job assessment can evolve β€” but these five gate completion.
48
+ * Maps job names to their founder journey stage category.
49
+ * Used to auto-populate `stageCategory` on quality score records.
38
50
  */
39
- exports.REQUIRED_QUALITY_FIELDS = [
51
+ exports.STAGE_CATEGORY_MAP = {
52
+ 'process-interview-notes': 'customer-development',
53
+ 'triage-customer-needs': 'customer-development',
54
+ 'business-plan-creation': 'business-strategy',
55
+ 'pricing-strategy-definition': 'business-strategy',
56
+ 'founder-market-fit-analysis': 'business-strategy',
57
+ 'review-business-strategy': 'business-strategy',
58
+ 'code-quality-assessment': 'product-quality',
59
+ 'test-standards-evaluation': 'test-quality',
60
+ 'test-coverage-evaluation': 'test-quality',
61
+ 'review-test-quality': 'test-quality',
62
+ };
63
+ /**
64
+ * Human-readable stage names for dashboard display.
65
+ */
66
+ exports.STAGE_DISPLAY_NAMES = {
67
+ 'customer-development': 'Customer Development',
68
+ 'business-strategy': 'Business Strategy',
69
+ 'product-quality': 'Product Quality',
70
+ 'test-quality': 'Test Quality',
71
+ 'fundraising': 'Fundraising',
72
+ 'go-to-market': 'Go-to-Market',
73
+ };
74
+ /**
75
+ * All known stage categories, in display order for the tile grid.
76
+ */
77
+ exports.ALL_STAGE_CATEGORIES = [
78
+ 'customer-development',
79
+ 'business-strategy',
80
+ 'product-quality',
81
+ 'test-quality',
82
+ 'fundraising',
83
+ 'go-to-market',
84
+ ];
85
+ /**
86
+ * Required fields for customer-development jobs (legacy V1 schema).
87
+ * These jobs require participant and evidence sub-dimensions.
88
+ */
89
+ const CUSTOMER_DEV_REQUIRED_FIELDS = [
40
90
  { path: 'composite', type: 'number' },
41
91
  { path: 'participant.fit', type: 'number' },
42
92
  { path: 'participant.urgency', type: 'number' },
@@ -44,15 +94,38 @@ exports.REQUIRED_QUALITY_FIELDS = [
44
94
  { path: 'evidence.quoteSpecificityAvg', type: 'number' }
45
95
  ];
46
96
  /**
47
- * Validate an `evidence.quality` object against REQUIRED_QUALITY_FIELDS.
48
- * Returns null if valid, or an array of human-readable error strings.
97
+ * Required fields for all other quality-producing jobs.
98
+ * Only composite and coaching are universally required β€” sub-dimensions
99
+ * vary by stage and are validated holistically, not mechanically.
100
+ */
101
+ const UNIVERSAL_REQUIRED_FIELDS = [
102
+ { path: 'composite', type: 'number' },
103
+ ];
104
+ /**
105
+ * Returns the required quality fields for a given job.
106
+ * Customer-development jobs retain the strict V1 schema.
107
+ * All other jobs require only a composite score (principle-based, not prescriptive).
108
+ */
109
+ function getRequiredFieldsForJob(jobName) {
110
+ const stage = exports.STAGE_CATEGORY_MAP[jobName];
111
+ if (stage === 'customer-development') {
112
+ return CUSTOMER_DEV_REQUIRED_FIELDS;
113
+ }
114
+ return UNIVERSAL_REQUIRED_FIELDS;
115
+ }
116
+ /**
117
+ * @deprecated Use getRequiredFieldsForJob() for stage-aware validation.
118
+ * Kept for backward compatibility with existing imports.
119
+ */
120
+ exports.REQUIRED_QUALITY_FIELDS = CUSTOMER_DEV_REQUIRED_FIELDS;
121
+ /**
122
+ * Validate an `evidence.quality` object against the required fields for
123
+ * a given job. If no jobName is provided, falls back to the universal
124
+ * schema (composite only).
49
125
  *
50
- * Design note: when `quality` is entirely missing we still walk every
51
- * required field and emit a per-field error, so the agent sees the
52
- * complete schema in one round rather than being told only that
53
- * `quality` itself is missing.
126
+ * Returns null if valid, or an array of human-readable error strings.
54
127
  */
55
- function validateQualityEvidence(quality) {
128
+ function validateQualityEvidence(quality, jobName) {
56
129
  const errors = [];
57
130
  const isMissing = quality === undefined || quality === null;
58
131
  if (isMissing) {
@@ -64,7 +137,8 @@ function validateQualityEvidence(quality) {
64
137
  const effective = isMissing || typeof quality !== 'object' || Array.isArray(quality)
65
138
  ? undefined
66
139
  : quality;
67
- for (const { path, type } of exports.REQUIRED_QUALITY_FIELDS) {
140
+ const requiredFields = jobName ? getRequiredFieldsForJob(jobName) : UNIVERSAL_REQUIRED_FIELDS;
141
+ for (const { path, type } of requiredFields) {
68
142
  const parts = path.split('.');
69
143
  let cursor = effective;
70
144
  for (const part of parts) {
@@ -91,31 +165,49 @@ function validateQualityEvidence(quality) {
91
165
  */
92
166
  function buildQualityRejectionMessage(jobName, currentPhase, errors) {
93
167
  const errorBullets = errors.map(e => `- ${e}`).join('\n');
168
+ const stage = exports.STAGE_CATEGORY_MAP[jobName];
169
+ const isCustomerDev = stage === 'customer-development';
170
+ const schemaExample = isCustomerDev
171
+ ? [
172
+ '```javascript',
173
+ 'evidence: {',
174
+ ' quality: {',
175
+ ' composite: <number 0-10>,',
176
+ ' participant: { fit: <number 1-10>, urgency: <number 1-10>, authority: <number 1-10> },',
177
+ ' evidence: {',
178
+ ' quoteSpecificityAvg: <number 1-10>',
179
+ ' // other fields are allowed and encouraged but not required',
180
+ ' },',
181
+ ' coaching: "<actionable recommendation>",',
182
+ ' interviewee: "<name>",',
183
+ ' company: "<company>"',
184
+ ' }',
185
+ '}',
186
+ '```'
187
+ ]
188
+ : [
189
+ '```javascript',
190
+ 'evidence: {',
191
+ ' quality: {',
192
+ ' composite: <number 0-10>,',
193
+ ' coaching: "<actionable recommendation>",',
194
+ ' // include per-dimension scores with rationale fields',
195
+ ' // additional fields are encouraged β€” schema is flexible per stage',
196
+ ' }',
197
+ '}',
198
+ '```'
199
+ ];
94
200
  return [
95
201
  `❌ **Job completion rejected** for \`${jobName}\`.`,
96
202
  '',
97
- `This job is required to emit a quality score on its final \`seekMentoring\` call so the result is captured in \`fraim_quality_scores\` for the manager dashboard. The following problems were found in \`evidence.quality\`:`,
203
+ `This job is required to emit a quality score on its final \`seekMentoring\` call so the result is captured in \`fraim_quality_scores\` for the quality dashboard. The following problems were found in \`evidence.quality\`:`,
98
204
  '',
99
205
  errorBullets,
100
206
  '',
101
- 'Required minimum schema:',
207
+ `Required minimum schema for \`${stage ?? 'unknown'}\` stage:`,
102
208
  '',
103
- '```javascript',
104
- 'evidence: {',
105
- ' quality: {',
106
- ' composite: <number 0-10>,',
107
- ' participant: { fit: <number 1-10>, urgency: <number 1-10>, authority: <number 1-10> },',
108
- ' evidence: {',
109
- ' quoteSpecificityAvg: <number 1-10>',
110
- ' // other fields are allowed and encouraged but not required',
111
- ' },',
112
- ' interviewee: "<name>",',
113
- ' company: "<company>",',
114
- ' artifactPath: "docs/customer-development/<slug>-interview.md"',
115
- ' }',
116
- '}',
117
- '```',
209
+ ...schemaExample,
118
210
  '',
119
- `You are still in phase \`${currentPhase}\`. The job is **not** marked complete. Build the \`evidence.quality\` object from your Phase 4 (\`conversation-quality-assessment\`) work and resubmit this final phase.`
211
+ `You are still in phase \`${currentPhase}\`. The job is **not** marked complete. Build the \`evidence.quality\` object from your quality assessment work and resubmit this final phase.`
120
212
  ].join('\n');
121
213
  }
@@ -1681,7 +1681,7 @@ class FraimLocalMCPServer {
1681
1681
  const isFinalCompletion = args.status === 'complete' &&
1682
1682
  (tutoringResponse.nextPhase === null || tutoringResponse.nextPhase === undefined);
1683
1683
  if (isQualityJob && isFinalCompletion) {
1684
- const qualityErrors = (0, quality_evidence_1.validateQualityEvidence)(args.evidence?.quality);
1684
+ const qualityErrors = (0, quality_evidence_1.validateQualityEvidence)(args.evidence?.quality, args.jobName);
1685
1685
  if (qualityErrors) {
1686
1686
  this.log(`❌ Quality enforcement rejected ${args.jobName} completion: ${qualityErrors.join('; ')}`);
1687
1687
  const rejection = (0, quality_evidence_1.buildQualityRejectionMessage)(args.jobName, args.currentPhase, qualityErrors);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.109",
3
+ "version": "2.0.114",
4
4
  "description": "FRAIM CLI - Framework for Rigor-based AI Management (alias for fraim-framework)",
5
5
  "main": "index.js",
6
6
  "bin": {