@forwardimpact/model 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # @forwardimpact/model
2
2
 
3
- Derivation engine for roles, skills, and AI agent profiles.
3
+ Derivation engine for roles, skills, and agent team profiles.
4
4
 
5
5
  ## Role in the Vision
6
6
 
7
7
  The model package contains the core logic that transforms raw data into
8
8
  actionable role definitions. Whether you're generating a human job description
9
- or an AI agent profile, the same derivation engine ensures consistent
9
+ or a coding agent team profile, the same derivation engine ensures consistent
10
10
  expectations across both.
11
11
 
12
12
  ## What It Does
13
13
 
14
14
  - **Job derivation** — Combine discipline, track, and grade into complete role
15
15
  definitions with skill matrices and behaviour profiles
16
- - **Agent profiles** — Generate AI coding agent configurations from the same
16
+ - **Agent profiles** — Generate coding agent team configurations from the same
17
17
  foundation as human roles
18
18
  - **Interview preparation** — Select appropriate questions based on role
19
19
  requirements
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@forwardimpact/model",
3
- "version": "0.9.0",
4
- "description": "Derivation engine for roles, skills, and AI agent profiles",
3
+ "version": "1.0.0",
4
+ "description": "Derivation engine for roles, skills, and agent team profiles",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
package/src/agent.js CHANGED
@@ -487,7 +487,8 @@ function getChecklistStage(stageId) {
487
487
  * @param {Array} params.derivedBehaviours - Behaviours sorted by maturity
488
488
  * @param {Array} params.agentBehaviours - Agent behaviour definitions
489
489
  * @param {Array} params.skills - All skill definitions (for agent section lookup)
490
- * @param {Array<{skill: Object, capability: Object, items: string[]}>} params.checklist - Raw checklist from deriveChecklist
490
+ * @param {Array<{skill: Object, capability: Object, items: string[]}>} params.readChecklist - Read-then-do checklist from deriveChecklist
491
+ * @param {Array<{skill: Object, capability: Object, items: string[]}>} params.confirmChecklist - Do-then-confirm checklist from deriveChecklist
491
492
  * @param {Array<{id: string, name: string, description: string}>} [params.agentIndex] - List of all available agents
492
493
  * @returns {Object} Structured profile body data
493
494
  */
@@ -501,7 +502,8 @@ function buildStageProfileBodyData({
501
502
  derivedBehaviours,
502
503
  agentBehaviours,
503
504
  skills,
504
- checklist,
505
+ readChecklist,
506
+ confirmChecklist,
505
507
  agentIndex,
506
508
  }) {
507
509
  const name = `${humanDiscipline.specialization || humanDiscipline.name} - ${humanTrack.name}`;
@@ -565,7 +567,8 @@ function buildStageProfileBodyData({
565
567
  skillIndex,
566
568
  roleContext,
567
569
  workingStyles,
568
- confirmChecklist: checklist || [],
570
+ readChecklist: readChecklist || [],
571
+ confirmChecklist: confirmChecklist || [],
569
572
  constraints,
570
573
  agentIndex: filteredAgentIndex,
571
574
  hasAgentIndex: filteredAgentIndex.length > 0,
@@ -628,16 +631,19 @@ export function deriveStageAgent({
628
631
  stages,
629
632
  });
630
633
 
631
- // Derive checklist from focused skills only
634
+ // Derive checklists from focused skills only
632
635
  const checklistStage = getChecklistStage(stage.id);
633
- let checklist = [];
636
+ let readChecklist = [];
637
+ let confirmChecklist = [];
634
638
  if (checklistStage && capabilities) {
635
- checklist = deriveChecklist({
639
+ const checklists = deriveChecklist({
636
640
  stageId: checklistStage,
637
641
  skillMatrix: focusedSkills,
638
642
  skills,
639
643
  capabilities,
640
644
  });
645
+ readChecklist = checklists.readChecklist;
646
+ confirmChecklist = checklists.confirmChecklist;
641
647
  }
642
648
 
643
649
  return {
@@ -652,7 +658,8 @@ export function deriveStageAgent({
652
658
  ...(agentDiscipline.constraints || []),
653
659
  ...(agentTrack.constraints || []),
654
660
  ],
655
- checklist,
661
+ readChecklist,
662
+ confirmChecklist,
656
663
  agentDiscipline,
657
664
  agentTrack,
658
665
  agentBehaviours,
@@ -714,7 +721,7 @@ export function generateStageAgentProfile({
714
721
  // Build description using shared helper
715
722
  const description = buildAgentDescription(discipline, track, stage);
716
723
 
717
- // Build structured profile body data (pass raw checklist for template iteration)
724
+ // Build structured profile body data (pass raw checklists for template iteration)
718
725
  const bodyData = buildStageProfileBodyData({
719
726
  stage,
720
727
  humanDiscipline: discipline,
@@ -725,7 +732,8 @@ export function generateStageAgentProfile({
725
732
  derivedBehaviours: agent.derivedBehaviours,
726
733
  agentBehaviours,
727
734
  skills,
728
- checklist: agent.checklist,
735
+ readChecklist: agent.readChecklist,
736
+ confirmChecklist: agent.confirmChecklist,
729
737
  agentIndex,
730
738
  });
731
739
 
package/src/checklist.js CHANGED
@@ -1,22 +1,30 @@
1
1
  /**
2
2
  * Checklist Derivation
3
3
  *
4
- * Checklists are derived from skills with agent.stages.{stage}.confirmChecklist criteria.
5
- * Each skill defines its own readiness criteria for stage transitions.
4
+ * Checklists are derived from skills with agent.stages.{stage} criteria.
5
+ * Each skill defines its own read-then-do and do-then-confirm items
6
+ * for stage transitions.
6
7
  *
7
- * Checklist = Stage × Skill Matrix × Skill Confirm Checklist
8
+ * Checklist = Stage × Skill Matrix × Skill Checklists
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} ChecklistEntry
13
+ * @property {{id: string, name: string}} skill - Skill info
14
+ * @property {{id: string, name: string, emojiIcon: string}} capability - Capability info
15
+ * @property {string[]} items - Checklist items
8
16
  */
9
17
 
10
18
  /**
11
19
  * Derive checklist items for a specific stage
12
- * Returns skills grouped by capability with their ready criteria
20
+ * Returns read-then-do and do-then-confirm items grouped by skill/capability
13
21
  *
14
22
  * @param {Object} params
15
23
  * @param {string} params.stageId - Current stage (plan, code, review)
16
24
  * @param {Array} params.skillMatrix - Derived skill matrix with skill details
17
25
  * @param {Array} params.skills - All skills (to look up agent.stages)
18
26
  * @param {Array} params.capabilities - All capabilities (for emoji lookup)
19
- * @returns {Array<{skill: Object, capability: Object, items: string[]}>} Checklist items grouped by skill
27
+ * @returns {{readChecklist: ChecklistEntry[], confirmChecklist: ChecklistEntry[]}} Checklists by type
20
28
  */
21
29
  export function deriveChecklist({
22
30
  stageId,
@@ -30,7 +38,8 @@ export function deriveChecklist({
30
38
  // Build capability lookup
31
39
  const capabilityById = new Map(capabilities.map((c) => [c.id, c]));
32
40
 
33
- const result = [];
41
+ const readChecklist = [];
42
+ const confirmChecklist = [];
34
43
 
35
44
  for (const entry of skillMatrix) {
36
45
  const skill = skillById.get(entry.skillId);
@@ -39,11 +48,7 @@ export function deriveChecklist({
39
48
  }
40
49
 
41
50
  const stageData = skill.agent.stages[stageId];
42
- if (
43
- !stageData ||
44
- !stageData.confirmChecklist ||
45
- stageData.confirmChecklist.length === 0
46
- ) {
51
+ if (!stageData) {
47
52
  continue;
48
53
  }
49
54
 
@@ -53,28 +58,38 @@ export function deriveChecklist({
53
58
  continue;
54
59
  }
55
60
 
56
- result.push({
57
- skill: {
58
- id: skill.id,
59
- name: skill.name,
60
- },
61
- capability: {
62
- id: capability.id,
63
- name: capability.name,
64
- emojiIcon: capability.emojiIcon,
65
- },
66
- items: stageData.confirmChecklist,
67
- });
61
+ const skillInfo = { id: skill.id, name: skill.name };
62
+ const capabilityInfo = {
63
+ id: capability.id,
64
+ name: capability.name,
65
+ emojiIcon: capability.emojiIcon,
66
+ };
67
+
68
+ if (stageData.readChecklist && stageData.readChecklist.length > 0) {
69
+ readChecklist.push({
70
+ skill: skillInfo,
71
+ capability: capabilityInfo,
72
+ items: stageData.readChecklist,
73
+ });
74
+ }
75
+
76
+ if (stageData.confirmChecklist && stageData.confirmChecklist.length > 0) {
77
+ confirmChecklist.push({
78
+ skill: skillInfo,
79
+ capability: capabilityInfo,
80
+ items: stageData.confirmChecklist,
81
+ });
82
+ }
68
83
  }
69
84
 
70
- return result;
85
+ return { readChecklist, confirmChecklist };
71
86
  }
72
87
 
73
88
  /**
74
89
  * Format a checklist for display (markdown format)
75
90
  * Groups items by skill with capability emoji
76
91
  *
77
- * @param {Array<{skill: Object, capability: Object, items: string[]}>} checklist - Derived checklist
92
+ * @param {ChecklistEntry[]} checklist - Checklist entries (readChecklist or confirmChecklist)
78
93
  * @returns {string} Markdown-formatted checklist
79
94
  */
80
95
  export function formatChecklistMarkdown(checklist) {