@forwardimpact/pathway 0.25.22 → 0.25.25

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.
Files changed (40) hide show
  1. package/bin/fit-pathway.js +117 -325
  2. package/package.json +2 -2
  3. package/src/commands/agent-io.js +1 -1
  4. package/src/commands/agent-list.js +164 -0
  5. package/src/commands/agent.js +83 -184
  6. package/src/commands/behaviour.js +22 -10
  7. package/src/commands/build-packs.js +208 -34
  8. package/src/commands/build.js +2 -2
  9. package/src/commands/command-factory.js +39 -14
  10. package/src/commands/discipline.js +24 -10
  11. package/src/commands/driver.js +28 -19
  12. package/src/commands/index.js +0 -1
  13. package/src/commands/interview.js +15 -10
  14. package/src/commands/job.js +110 -62
  15. package/src/commands/level.js +23 -11
  16. package/src/commands/progress.js +12 -7
  17. package/src/commands/questions.js +32 -14
  18. package/src/commands/skill.js +36 -18
  19. package/src/commands/stage.js +37 -27
  20. package/src/commands/tool.js +29 -19
  21. package/src/commands/track.js +23 -10
  22. package/src/formatters/questions/yaml.js +1 -1
  23. package/src/index.html +1 -1
  24. package/src/lib/cli-command.js +33 -33
  25. package/src/lib/cli-output.js +9 -189
  26. package/src/pages/agent-builder-install.js +6 -5
  27. package/src/commands/init.js +0 -64
  28. package/starter/behaviours/systems_thinking.yaml +0 -32
  29. package/starter/capabilities/delivery.yaml +0 -105
  30. package/starter/capabilities/reliability.yaml +0 -72
  31. package/starter/disciplines/software_engineering.yaml +0 -46
  32. package/starter/drivers.yaml +0 -10
  33. package/starter/framework.yaml +0 -49
  34. package/starter/levels.yaml +0 -39
  35. package/starter/questions/behaviours/.gitkeep +0 -0
  36. package/starter/questions/capabilities/.gitkeep +0 -0
  37. package/starter/questions/skills/.gitkeep +0 -0
  38. package/starter/stages.yaml +0 -21
  39. package/starter/tracks/forward_deployed.yaml +0 -33
  40. package/starter/tracks/platform.yaml +0 -33
@@ -1,129 +1,12 @@
1
1
  /**
2
- * CLI Output Formatting Utilities
2
+ * Domain-specific CLI Output Formatters
3
3
  *
4
- * Provides consistent formatting for terminal output including colors,
5
- * tables, headers, and level formatting.
4
+ * Pathway-specific formatting for skill proficiencies, behaviour maturities,
5
+ * modifiers, percentages, and change indicators. Generic formatters (colors,
6
+ * tables, headers, etc.) live in @forwardimpact/libcli.
6
7
  */
7
8
 
8
- // ANSI color codes
9
- export const colors = {
10
- reset: "\x1b[0m",
11
- bold: "\x1b[1m",
12
- dim: "\x1b[2m",
13
- italic: "\x1b[3m",
14
- underline: "\x1b[4m",
15
- red: "\x1b[31m",
16
- green: "\x1b[32m",
17
- yellow: "\x1b[33m",
18
- blue: "\x1b[34m",
19
- magenta: "\x1b[35m",
20
- cyan: "\x1b[36m",
21
- white: "\x1b[37m",
22
- gray: "\x1b[90m",
23
- };
24
-
25
- /**
26
- * Check if stdout supports colors
27
- * @returns {boolean}
28
- */
29
- export function supportsColor() {
30
- if (process.env.NO_COLOR) return false;
31
- if (process.env.FORCE_COLOR) return true;
32
- return process.stdout.isTTY;
33
- }
34
-
35
- /**
36
- * Wrap text with color if supported
37
- * @param {string} text
38
- * @param {string} color
39
- * @returns {string}
40
- */
41
- function colorize(text, color) {
42
- if (!supportsColor()) return text;
43
- return `${color}${text}${colors.reset}`;
44
- }
45
-
46
- /**
47
- * Format a header
48
- * @param {string} text
49
- * @returns {string}
50
- */
51
- export function formatHeader(text) {
52
- return colorize(text, colors.bold + colors.cyan);
53
- }
54
-
55
- /**
56
- * Format a subheader
57
- * @param {string} text
58
- * @returns {string}
59
- */
60
- export function formatSubheader(text) {
61
- return colorize(text, colors.bold);
62
- }
63
-
64
- /**
65
- * Format a list item
66
- * @param {string} label
67
- * @param {string} value
68
- * @param {number} [indent=0]
69
- * @returns {string}
70
- */
71
- export function formatListItem(label, value, indent = 0) {
72
- const padding = " ".repeat(indent);
73
- const bullet = colorize("•", colors.dim);
74
- return `${padding}${bullet} ${label}: ${value}`;
75
- }
76
-
77
- /**
78
- * Format a bullet item (no label)
79
- * @param {string} text
80
- * @param {number} [indent=0]
81
- * @returns {string}
82
- */
83
- export function formatBullet(text, indent = 0) {
84
- const padding = " ".repeat(indent);
85
- const bullet = colorize("•", colors.dim);
86
- return `${padding}${bullet} ${text}`;
87
- }
88
-
89
- /**
90
- * Format a table
91
- * @param {string[]} headers
92
- * @param {Array<Array<string|number>>} rows
93
- * @param {Object} [options]
94
- * @param {boolean} [options.compact=false]
95
- * @returns {string}
96
- */
97
- export function formatTable(headers, rows, options = {}) {
98
- const { compact = false } = options;
99
-
100
- // Calculate column widths
101
- const widths = headers.map((h, i) =>
102
- Math.max(String(h).length, ...rows.map((r) => String(r[i] || "").length)),
103
- );
104
-
105
- const lines = [];
106
-
107
- // Header
108
- const headerLine = headers
109
- .map((h, i) => String(h).padEnd(widths[i]))
110
- .join(" ");
111
- lines.push(colorize(headerLine, colors.bold));
112
-
113
- // Separator
114
- if (!compact) {
115
- lines.push(widths.map((w) => "─".repeat(w)).join("──"));
116
- }
117
-
118
- // Rows
119
- for (const row of rows) {
120
- lines.push(
121
- row.map((cell, i) => String(cell || "").padEnd(widths[i])).join(" "),
122
- );
123
- }
124
-
125
- return lines.join("\n");
126
- }
9
+ import { colorize, colors } from "@forwardimpact/libcli";
127
10
 
128
11
  /**
129
12
  * Format skill proficiency with color
@@ -193,78 +76,15 @@ export function formatPercent(value) {
193
76
  }
194
77
 
195
78
  /**
196
- * Format a change indicator (↑, ↓, →)
79
+ * Format a change indicator
197
80
  * @param {number} change
198
81
  * @returns {string}
199
82
  */
200
83
  export function formatChange(change) {
201
84
  if (change > 0) {
202
- return colorize(`↑${change}`, colors.green);
85
+ return colorize(`\u2191${change}`, colors.green);
203
86
  } else if (change < 0) {
204
- return colorize(`↓${Math.abs(change)}`, colors.red);
87
+ return colorize(`\u2193${Math.abs(change)}`, colors.red);
205
88
  }
206
- return colorize("", colors.dim);
207
- }
208
-
209
- /**
210
- * Format an error message
211
- * @param {string} message
212
- * @returns {string}
213
- */
214
- export function formatError(message) {
215
- return colorize(`Error: ${message}`, colors.red);
216
- }
217
-
218
- /**
219
- * Format a success message
220
- * @param {string} message
221
- * @returns {string}
222
- */
223
- export function formatSuccess(message) {
224
- return colorize(message, colors.green);
225
- }
226
-
227
- /**
228
- * Format a warning message
229
- * @param {string} message
230
- /**
231
- * Format a warning message
232
- * @param {string} message
233
- * @returns {string}
234
- */
235
- export function formatWarning(message) {
236
- return colorize(`Warning: ${message}`, colors.yellow);
237
- }
238
-
239
- /**
240
- * Create a horizontal rule
241
- * @param {number} [width=60]
242
- * @returns {string}
243
- */
244
- export function horizontalRule(width = 60) {
245
- return colorize("─".repeat(width), colors.dim);
246
- }
247
-
248
- /**
249
- * Format a section with title and content
250
- * @param {string} title
251
- * @param {string} content
252
- * @returns {string}
253
- */
254
- export function formatSection(title, content) {
255
- return `${formatHeader(title)}\n\n${content}`;
256
- }
257
-
258
- /**
259
- * Indent all lines of text
260
- * @param {string} text
261
- * @param {number} [spaces=2]
262
- * @returns {string}
263
- */
264
- export function indent(text, spaces = 2) {
265
- const padding = " ".repeat(spaces);
266
- return text
267
- .split("\n")
268
- .map((line) => padding + line)
269
- .join("\n");
89
+ return colorize("\u2192", colors.dim);
270
90
  }
@@ -56,13 +56,14 @@ export function getApmInstallCommand(siteUrl, packName) {
56
56
  }
57
57
 
58
58
  /**
59
- * Build the `npx skills add` command that discovers the published pack
60
- * registry at `<siteUrl>/.well-known/agent-skills/index.json`.
59
+ * Build the `npx skills add` command that discovers the per-pack skill
60
+ * repository at `<siteUrl>/packs/<packName>/.well-known/skills/index.json`.
61
61
  * @param {string} siteUrl
62
+ * @param {string} packName
62
63
  * @returns {string}
63
64
  */
64
- export function getSkillsAddCommand(siteUrl) {
65
- return `npx skills add ${normalizeSiteUrl(siteUrl)}`;
65
+ export function getSkillsAddCommand(siteUrl, packName) {
66
+ return `npx skills add ${normalizeSiteUrl(siteUrl)}/packs/${packName}`;
66
67
  }
67
68
 
68
69
  /**
@@ -80,7 +81,7 @@ export function createInstallSection({ discipline, track, siteUrl }) {
80
81
 
81
82
  const packName = getPackName(discipline, track);
82
83
  const apmCommand = getApmInstallCommand(siteUrl, packName);
83
- const skillsCommand = getSkillsAddCommand(siteUrl);
84
+ const skillsCommand = getSkillsAddCommand(siteUrl, packName);
84
85
 
85
86
  return section(
86
87
  {
@@ -1,64 +0,0 @@
1
- /**
2
- * Init Command
3
- *
4
- * Initializes a new Engineering Pathway project by copying starter data.
5
- */
6
-
7
- import { cp, access } from "fs/promises";
8
- import { join, dirname } from "path";
9
- import { fileURLToPath } from "url";
10
-
11
- const __dirname = dirname(fileURLToPath(import.meta.url));
12
- const starterDir = join(__dirname, "..", "..", "starter");
13
-
14
- /**
15
- * Run the init command
16
- * @param {Object} params - Command parameters
17
- * @param {Object} params.options - Command options
18
- */
19
- export async function runInitCommand({ options }) {
20
- const targetPath = options.path || process.cwd();
21
- const dataDir = join(targetPath, "data", "pathway");
22
-
23
- // Check if data/pathway/ already exists
24
- try {
25
- await access(dataDir);
26
- console.error("Error: ./data/pathway/ already exists.");
27
- console.error("Remove it first or use a different directory.");
28
- process.exit(1);
29
- } catch {
30
- // Directory doesn't exist, proceed
31
- }
32
-
33
- // Verify starter data is available
34
- try {
35
- await access(starterDir);
36
- } catch {
37
- console.error("Error: Starter data not found in package.");
38
- console.error("This may indicate a corrupted package installation.");
39
- process.exit(1);
40
- }
41
-
42
- // Copy starter data
43
- console.log("Creating ./data/pathway/ with starter data...\n");
44
- await cp(starterDir, dataDir, { recursive: true });
45
-
46
- console.log(`✅ Created ./data/pathway/ with starter data.
47
-
48
- Next steps:
49
- 1. Edit data files to match your organization
50
- 2. npx fit-map validate
51
- 3. npx fit-pathway dev
52
-
53
- Data structure:
54
- data/pathway/
55
- ├── framework.yaml # Framework metadata
56
- ├── levels.yaml # Career levels
57
- ├── stages.yaml # Lifecycle stages
58
- ├── drivers.yaml # Business drivers
59
- ├── disciplines/ # Engineering disciplines
60
- ├── capabilities/ # Capability areas with skills
61
- ├── behaviours/ # Behavioural expectations
62
- └── tracks/ # Track specializations
63
- `);
64
- }
@@ -1,32 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/behaviour.schema.json
2
-
3
- name: Think in Systems
4
- human:
5
- description:
6
- The ability to see beyond individual components to understand how the entire
7
- system behaves. Engineers recognize that every service, API, and queue is
8
- part of a larger whole—isolated changes ripple across the system.
9
- maturityDescriptions:
10
- emerging:
11
- Recognizes that systems have interconnected parts; considers immediate
12
- dependencies in code
13
- developing:
14
- Identifies upstream and downstream impacts; uses observability tools to
15
- trace requests across services
16
- practicing:
17
- Maps complex system interactions across technical and business domains;
18
- anticipates cascading effects
19
- role_modeling:
20
- Shapes systems design practices across their function; influences
21
- cross-team architecture decisions
22
- exemplifying:
23
- Defines organizational systems architecture principles; recognized
24
- authority on complex systems
25
-
26
- agent:
27
- title: Consider the whole system
28
- workingStyle: |
29
- For every change:
30
- 1. Identify upstream and downstream impacts
31
- 2. Consider non-functional requirements (performance, security)
32
- 3. Document assumptions and trade-offs
@@ -1,105 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/capability.schema.json
2
-
3
- id: delivery
4
- name: Delivery
5
- emojiIcon: "\U0001F680"
6
- ordinalRank: 1
7
- description: |
8
- Building and shipping solutions that solve real problems.
9
- professionalResponsibilities:
10
- awareness:
11
- You complete assigned tasks within established patterns with guidance
12
- foundational: You deliver small features end-to-end with minimal guidance
13
- working: You own feature delivery from design through deployment
14
- practitioner: You lead technical delivery of complex projects across teams
15
- expert: You drive delivery of the most critical technical initiatives
16
- managementResponsibilities:
17
- awareness: You track team progress and communicate status to stakeholders
18
- foundational:
19
- You coordinate team delivery by managing dependencies and removing blockers
20
- working: You own team delivery outcomes and make resourcing decisions
21
- practitioner: You drive delivery excellence across multiple teams
22
- expert: You shape delivery culture across the business unit
23
- skills:
24
- - id: task_completion
25
- name: Task Completion
26
- human:
27
- description:
28
- Completing work items reliably, from understanding requirements through
29
- implementation to verification.
30
- proficiencyDescriptions:
31
- awareness:
32
- You complete well-defined tasks with guidance, following established
33
- patterns and asking for help when needed.
34
- foundational:
35
- You break down tasks into steps, estimate effort, and deliver
36
- independently on familiar work.
37
- working:
38
- You manage your own workload, handle ambiguous requirements, and
39
- consistently deliver on commitments.
40
- practitioner:
41
- You coordinate task delivery across teams, unblock others, and
42
- establish completion standards for your area.
43
- expert:
44
- You define delivery practices across the organization and drive
45
- completion of the most complex initiatives.
46
- agent:
47
- name: task-completion
48
- description: |
49
- Guide for completing work items reliably from requirements through
50
- verification.
51
- useWhen: |
52
- Implementing features, fixing bugs, or completing any defined work item.
53
- stages:
54
- code:
55
- focus: |
56
- Implement the solution according to requirements. Write clean,
57
- tested code that meets acceptance criteria.
58
- readChecklist:
59
- - Understand the requirements and acceptance criteria
60
- - Review relevant existing code and patterns
61
- confirmChecklist:
62
- - Code compiles and passes tests
63
- - Acceptance criteria are met
64
- - Changes are documented
65
-
66
- - id: planning
67
- name: Planning
68
- human:
69
- description:
70
- Breaking down work into manageable pieces, estimating effort, and
71
- sequencing delivery for maximum impact.
72
- proficiencyDescriptions:
73
- awareness:
74
- You follow project plans created by others and report progress
75
- accurately.
76
- foundational:
77
- You create simple plans for your own work, estimate tasks, and
78
- identify dependencies.
79
- working:
80
- You plan features end-to-end, manage dependencies, and adjust plans
81
- based on new information.
82
- practitioner:
83
- You lead planning for complex projects across teams, manage risk, and
84
- establish planning practices for your area.
85
- expert:
86
- You shape planning strategy across the organization and drive delivery
87
- of the most complex programmes.
88
- agent:
89
- name: planning
90
- description: |
91
- Guide for breaking down work, estimating effort, and sequencing
92
- delivery.
93
- useWhen: |
94
- Planning features, creating implementation plans, or sequencing work.
95
- stages:
96
- code:
97
- focus: |
98
- Follow the implementation plan. Track progress and flag deviations
99
- from the plan early.
100
- readChecklist:
101
- - Review the implementation plan
102
- - Understand task dependencies and ordering
103
- confirmChecklist:
104
- - Plan steps are completed in order
105
- - Deviations from the plan are documented
@@ -1,72 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/capability.schema.json
2
-
3
- id: reliability
4
- name: Reliability
5
- emojiIcon: "\U0001F6E1\uFE0F"
6
- ordinalRank: 2
7
- description: |
8
- Ensuring systems are dependable, observable, and resilient.
9
- professionalResponsibilities:
10
- awareness: You follow operational guidelines and escalate issues appropriately
11
- foundational:
12
- You implement reliability practices in your code and create basic monitoring
13
- working: You design for reliability and lead incident response
14
- practitioner: You establish SLOs across teams and drive reliability culture
15
- expert: You shape reliability strategy across the business unit
16
- managementResponsibilities:
17
- awareness:
18
- You understand reliability requirements and support escalation processes
19
- foundational:
20
- You ensure your team follows reliability practices and facilitate
21
- retrospectives
22
- working:
23
- You own team reliability outcomes and manage incident response rotations
24
- practitioner:
25
- You drive reliability culture across teams and own cross-team reliability
26
- outcomes
27
- expert:
28
- You shape reliability strategy across the business unit and own enterprise
29
- reliability outcomes
30
- skills:
31
- - id: incident_response
32
- name: Incident Response
33
- human:
34
- description:
35
- Responding to production incidents effectively, from detection through
36
- resolution and post-incident review.
37
- proficiencyDescriptions:
38
- awareness:
39
- You follow incident response procedures and escalate issues using
40
- established channels.
41
- foundational:
42
- You participate in incident response, gather diagnostic information,
43
- and contribute to post-incident reviews.
44
- working:
45
- You lead incident response for your services, coordinate resolution,
46
- and conduct blameless post-mortems.
47
- practitioner:
48
- You establish incident response practices across teams, lead complex
49
- incidents, and drive systemic improvements.
50
- expert:
51
- You define incident management strategy across the organization and
52
- lead response to the most critical incidents.
53
- agent:
54
- name: incident-response
55
- description: |
56
- Guide for responding to production incidents from detection through
57
- resolution.
58
- useWhen: |
59
- Handling production issues, investigating failures, or improving
60
- incident response processes.
61
- stages:
62
- code:
63
- focus: |
64
- Implement fixes for identified issues. Ensure changes are tested
65
- and do not introduce regressions.
66
- readChecklist:
67
- - Understand the root cause of the incident
68
- - Review affected systems and dependencies
69
- confirmChecklist:
70
- - Fix addresses the root cause
71
- - Changes are tested
72
- - Monitoring confirms resolution
@@ -1,46 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/discipline.schema.json
2
-
3
- specialization: Software Engineering
4
- roleTitle: Software Engineer
5
- isProfessional: true
6
-
7
- # null = allow trackless (generalist)
8
- validTracks:
9
- - null
10
- - forward_deployed
11
- - platform
12
-
13
- description:
14
- Builds and maintains software systems, focusing on code quality, architecture,
15
- and reliable delivery of business value.
16
-
17
- # Derivation inputs — one skill per tier
18
- coreSkills:
19
- - task_completion
20
- supportingSkills:
21
- - planning
22
- broadSkills:
23
- - incident_response
24
- behaviourModifiers:
25
- systems_thinking: 1
26
-
27
- # Human-specific content
28
- human:
29
- professionalRoleSummary:
30
- As a {roleTitle}, you build and maintain software systems that deliver
31
- business value reliably.
32
- managementRoleSummary:
33
- As a {specialization} manager, you lead teams that build and maintain
34
- software systems delivering business value.
35
-
36
- # Agent-specific content
37
- agent:
38
- identity: |
39
- You are a {roleTitle} agent focused on building reliable software.
40
- priority: |
41
- Write clean, tested code that meets requirements and follows established
42
- patterns.
43
- constraints:
44
- - Follow existing code conventions
45
- - Write tests for new functionality
46
- - Document non-obvious decisions
@@ -1,10 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/drivers.schema.json
2
-
3
- - id: quality
4
- name: Quality
5
- description: Deliver work that meets expectations consistently.
6
- contributingSkills:
7
- - task_completion
8
- - planning
9
- contributingBehaviours:
10
- - systems_thinking
@@ -1,49 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/framework.schema.json
2
-
3
- title: Engineering Pathway
4
- emojiIcon: "\U0001F9ED"
5
- description: |
6
- Define what good engineering looks like for your organization.
7
- Edit these files to match your skills, levels, and expectations.
8
-
9
- entityDefinitions:
10
- driver:
11
- title: Drivers
12
- emojiIcon: "\U0001F3AF"
13
- description: Organizational outcomes that productive teams achieve.
14
- skill:
15
- title: Skills
16
- emojiIcon: "\U0001F4A1"
17
- description: Capabilities required to perform work effectively.
18
- behaviour:
19
- title: Behaviours
20
- emojiIcon: "\U0001F9E0"
21
- description: Mindsets and ways of working.
22
- discipline:
23
- title: Disciplines
24
- emojiIcon: "\U0001F52C"
25
- description: Engineering specializations that define skill profiles.
26
- level:
27
- title: Levels
28
- emojiIcon: "\U0001F4CA"
29
- description: Career levels that define expectations.
30
- track:
31
- title: Tracks
32
- emojiIcon: "\U0001F6E4\uFE0F"
33
- description: Work contexts that modify expectations.
34
- job:
35
- title: Jobs
36
- emojiIcon: "\U0001F4CB"
37
- description: Role specifications combining discipline, track, and level.
38
- agent:
39
- title: Agents
40
- emojiIcon: "\U0001F916"
41
- description: AI agent configurations generated from the framework.
42
- stage:
43
- title: Stages
44
- emojiIcon: "\U0001F504"
45
- description: Phases of the engineering lifecycle.
46
- tool:
47
- title: Tools
48
- emojiIcon: "\U0001F527"
49
- description: Recommended tools referenced by skills.
@@ -1,39 +0,0 @@
1
- # yaml-language-server: $schema=https://www.forwardimpact.team/schema/json/levels.schema.json
2
-
3
- - id: J040
4
- professionalTitle: Level I
5
- managementTitle: Associate
6
- typicalExperienceRange: "0-2 years"
7
- ordinalRank: 1
8
- qualificationSummary:
9
- Entry-level position suitable for recent graduates or those transitioning
10
- into the field ({typicalExperienceRange}).
11
- baseSkillProficiencies:
12
- primary: foundational
13
- secondary: awareness
14
- broad: awareness
15
- baseBehaviourMaturity: emerging
16
- expectations:
17
- impactScope: Individual tasks with guidance
18
- autonomyExpectation: Work with supervision
19
- influenceScope: Contribute to team discussions
20
- complexityHandled: Standard tasks with established patterns
21
-
22
- - id: J060
23
- professionalTitle: Level II
24
- managementTitle: Senior Associate
25
- typicalExperienceRange: "2-5 years"
26
- ordinalRank: 2
27
- qualificationSummary:
28
- Mid-level position with demonstrated ability to complete tasks independently
29
- ({typicalExperienceRange}).
30
- baseSkillProficiencies:
31
- primary: working
32
- secondary: foundational
33
- broad: awareness
34
- baseBehaviourMaturity: developing
35
- expectations:
36
- impactScope: Features and small projects
37
- autonomyExpectation: Work independently on familiar problems
38
- influenceScope: Mentor junior team members
39
- complexityHandled: Moderate complexity with some ambiguity
File without changes
File without changes
File without changes