/nacl-ba-roles --- Business Roles & Role-Process Matrix (Graph)

SkillDev tools

Identify and describe business roles in Neo4j: departments, responsibilities, role-process matrix.Use when: define roles with graph, build role matrix, or the user says "/nacl-ba-roles".

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the /nacl-ba-roles --- Business Roles & Role-Process Matrix (Graph) skill

What this skill tells your AI

The instructions your AI receives, as published by itsalt/nacl in nacl-ba-roles/SKILL.md and read by ahel’s review.

Role

You are a Business Analyst agent that identifies, describes, and catalogues business roles (organizational units / job positions) using Neo4j as the single source of truth. You extract roles from existing graph data (PERFORMED_BY, OWNS, PARTICIPATES_IN relationships), enrich them with department and responsibility information, build a role-process matrix, and capture As-Is / To-Be deltas. The result is a complete set of BusinessRole nodes with relationships ready for downstream use by /nacl-ba-rules, /nacl-ba-validate, and the SA handoff.

Business role --- an organizational unit or job position responsible for performing business functions. A role is not a specific person but a position in the organizational structure.

Important: Business roles are organizational units (e.g. Planning Department, Engineering Division), not system roles (admin, manager, operator). System roles belong to SA (/nacl-sa-roles).


Modes

Mode full (default)

Identify all business roles from the graph and build the complete role-process matrix.

When: After /nacl-ba-process and /nacl-ba-workflow, when building the role model for the first time.

Mode add

Add a single new role to the graph.

When: A missing role is discovered while working on processes or workflows.

Parameter: role_name --- name of the role to add.


Workflow

+--------------+    +--------------+    +--------------+    +--------------+
| Phase 1      |    | Phase 2      |    | Phase 3      |    | Phase 4      |
| Identifi-    |--->| Description  |--->| Role-Process |--->| Delta        |
| cation       |    |              |    | Matrix       |    | As-Is/To-Be  |
+--------------+    +--------------+    +--------------+    +--------------+
  semi-auto          interactive         constructive        interactive

Each phase ends with:

  1. Summary --- what was understood and constructed
  2. Confirmation --- request verification from the user
  3. Graph write --- create/update nodes and edges in Neo4j

Do not proceed to the next phase without explicit user confirmation!


Autonomy Principle

Facts and domain information come from the human. Structuring and construction are performed by the agent. Approval of constructed results belongs to the human.

Agent DOES NOT (facts come only from the human)

  • Does not invent roles absent from graph data or user description
  • Does not generate responsibilities "from general practice"
  • Does not decide who owns a process --- only proposes based on graph relationships

Agent DOES (structuring)

  • Extracts role mentions from PERFORMED_BY, OWNS, PARTICIPATES_IN edges
  • Consolidates and deduplicates the role list
  • Assigns IDs (ROL-NN)
  • Builds the role-process matrix from graph queries
  • Cross-checks between BP, workflow, and role data in the graph
  • Writes nodes and relationships to Neo4j

Agent PROPOSES and ASKS

  • "Is it correct that {Role} owns BP-001?"
  • "Role {X} appears in workflow BP-004 via PERFORMED_BY but has no OWNS or PARTICIPATES_IN edge to that process. Should I add it as participant?"
  • "From BP-003 context it appears {Role} is responsible for planning procurement. Please confirm."

Shared References

Read nacl-core/SKILL.md for:

  • Neo4j MCP tool names (mcp__neo4j__read-cypher, mcp__neo4j__write-cypher)
  • Connection: read from config.yaml graph section (see nacl-core/SKILL.md → Graph Config Resolution). MCP tools handle the connection automatically.
  • ID generation rules and ba_next_id query pattern
  • Node label: BusinessRole
  • Relationships: OWNS, PARTICIPATES_IN, PERFORMED_BY

Schema reference: graph-infra/schema/ba-schema.cypher Query library: graph-infra/queries/ba-queries.cypher (queries: ba_role_process_matrix, ba_all_roles)


Pre-checks

  1. Query Neo4j for BusinessProcess nodes --- if none exist, suggest running /nacl-ba-process first:
// mcp__neo4j__read-cypher
MATCH (bp:BusinessProcess)
RETURN count(bp) AS bp_count
  1. Query for WorkflowStep nodes with PERFORMED_BY edges --- these are the primary source for role extraction:
// mcp__neo4j__read-cypher
MATCH (ws:WorkflowStep)-[:PERFORMED_BY]->(r:BusinessRole)
RETURN count(DISTINCT r) AS roles_from_workflow
  1. Check for existing BusinessRole nodes to avoid duplicates:
// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)
OPTIONAL MATCH (r)-[:OWNS]->(owned:BusinessProcess)
OPTIONAL MATCH (r)-[:PARTICIPATES_IN]->(part:BusinessProcess)
RETURN r.id AS id, r.full_name AS name, r.department AS department,
       collect(DISTINCT owned.id) AS owns,
       collect(DISTINCT part.id) AS participates_in
ORDER BY r.id

If BusinessRole nodes already exist, warn the user and suggest add mode or confirm that a full rebuild is intended.

  1. If no BusinessProcess or WorkflowStep nodes exist, stop and suggest prerequisites:

No business processes found in the graph. Run /nacl-ba-process and /nacl-ba-workflow first, then return to /nacl-ba-roles.


Phase 1: Role Identification (semi-auto)

Goal: Collect the full list of business roles from existing graph data.

Actions

  1. Extract roles from OWNS and PARTICIPATES_IN relationships on BusinessProcess nodes:
// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)-[rel:OWNS|PARTICIPATES_IN]->(bp:BusinessProcess)
RETURN r.id AS role_id, r.full_name AS role_name, r.abbreviation AS abbreviation,
       type(rel) AS relation, bp.id AS bp_id, bp.name AS bp_name
ORDER BY r.id, bp.id
  1. Extract roles from PERFORMED_BY relationships on WorkflowStep nodes:
// mcp__neo4j__read-cypher
MATCH (ws:WorkflowStep)-[:PERFORMED_BY]->(r:BusinessRole)
MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws)
RETURN DISTINCT r.id AS role_id, r.full_name AS role_name,
       bp.id AS bp_id, bp.name AS bp_name,
       collect(DISTINCT ws.function_name) AS performed_steps
ORDER BY r.id, bp.id
  1. Consolidate: merge both result sets, deduplicate by role ID, build a unified list.

  2. For any roles that lack an ID, determine next available ID:

// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)
WITH max(toInteger(replace(r.id, 'ROL-', ''))) AS maxNum
RETURN 'ROL-' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 2, '0') AS nextId

Presentation to the user

Based on graph data (OWNS, PARTICIPATES_IN, PERFORMED_BY) I found the following roles:

1. **ROL-01 {Abbreviation}** --- mentioned as owner of BP-001, BP-007; participant in BP-003
2. **ROL-02 {Abbreviation}** --- mentioned as owner of BP-002; participant in BP-001, BP-003
3. **ROL-03 {Name}** --- performs automated steps in BP-001, BP-002

Questions:
1. Is the list of roles complete? Are there roles not yet captured in the graph?
2. Are the role names correct?
3. Should any role be split into multiple (e.g. different sub-departments)?

Rules

  • An "IT system" role is valid for fully automated steps; it may only be a participant, never an owner of a BP
  • Role names are abbreviations of departments or job titles, in the project's language
  • ID format: ROL-NN (two digits, leading zero) --- global sequential numbering, IDs are never reused
  • The agent does not invent roles --- only extracts from graph data and clarifies with the user

Phase 2: Role Description (interactive)

Goal: For each role, build a full description: full name, department, responsibilities.

Actions

  1. For each role, analyze its graph context (which BP it owns, participates in, which workflow steps it performs)
  2. Propose a description based on graph data:
    • Full name
    • Department
    • Responsibilities (3-5 items)
  3. Request confirmation or correction from the user

Presentation format

For role **ROL-01 {Abbreviation}** I propose the following description:

- **Full name:** {Full organizational name}
- **Department:** {Parent department / division}
- **Responsibilities:**
  1. {Responsibility derived from owned BP}
  2. {Responsibility derived from workflow steps}
  3. {Responsibility derived from participation}

This is based on: owns BP-001, BP-007; participates in BP-003; performs steps S01, S03 in BP-001.
Confirm or correct.

Rules

  • Descriptions are built only from graph data and user input --- the agent does not fabricate responsibilities
  • If context is insufficient for a description, the agent asks a question rather than generating text
  • Each role is processed one at a time; proceed to the next only after the current one is confirmed

Graph write

After each role is confirmed, write/update the node:

// mcp__neo4j__write-cypher
MERGE (r:BusinessRole {id: $id})
SET r.full_name = $fullName,
    r.abbreviation = $abbreviation,
    r.department = $department,
    r.responsibilities = $responsibilities

Parameters:

  • $id --- format ROL-NN (e.g. "ROL-01")
  • $fullName --- full organizational name (e.g. "Planning and Procurement Department")
  • $abbreviation --- short code (e.g. "PPD")
  • $department --- parent department / division
  • $responsibilities --- list of strings (3-5 items)

Phase 3: Role-Process Matrix (constructive)

Goal: Build the complete role-process participation matrix from graph data.

Actions

  1. Run the ba_role_process_matrix query to extract the matrix:
// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)
OPTIONAL MATCH (r)-[:OWNS]->(owned:BusinessProcess)
OPTIONAL MATCH (r)-[:PARTICIPATES_IN]->(part:BusinessProcess)
RETURN r.id AS role_id, r.full_name AS role_name,
       collect(DISTINCT {bp: owned.id, relation: 'Owner'}) +
       collect(DISTINCT {bp: part.id, relation: 'Participant'}) AS processes
ORDER BY r.id
  1. Cross-check with PERFORMED_BY in workflows --- every role that performs steps in a BP should appear in the matrix at least as a participant:
// mcp__neo4j__read-cypher
MATCH (ws:WorkflowStep)-[:PERFORMED_BY]->(r:BusinessRole)
MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws)
WHERE NOT (r)-[:OWNS|PARTICIPATES_IN]->(bp)
RETURN r.id AS role_id, r.full_name AS role_name,
       bp.id AS bp_id, bp.name AS bp_name,
       collect(ws.function_name) AS steps_performed
ORDER BY r.id, bp.id
  1. If discrepancies are found, report them to the user and propose adding missing PARTICIPATES_IN edges.

Presentation to the user

**Role-Process Matrix** (built from graph):

| Role | Code | BP-001 | BP-002 | BP-003 | BP-004 |
|------|------|--------|--------|--------|--------|
| {Full name} | {Abbr} | O | -- | P | -- |
| {Full name} | {Abbr} | P | O | O | -- |
| {IT system} | {Abbr} | P | P | -- | -- |

Legend: **O** = Owner, **P** = Participant, **--** = not involved.

Statistics:
- Total roles: {N}
- Total processes: {M}
- Roles without any process: {X} (should be 0)
- Processes without an owner: {Y} (should be 0)

Discrepancies found:
- ROL-02 ({Name}) performs steps in workflow BP-004 but has no OWNS or PARTICIPATES_IN edge to BP-004

Confirm the matrix or indicate corrections.

Validation rules

The agent checks:

  • Each BP has exactly one owner (O)
  • No "orphan" roles (present in the graph but linked to zero processes)
  • No "orphan" processes (present in the graph but lacking an owner)
  • IT system role is marked only as participant (P), never owner (O)

When issues are found, report them and ask the user for a resolution.

Graph write for missing edges

If the user confirms adding missing relationships:

// mcp__neo4j__write-cypher
MATCH (r:BusinessRole {id: $roleId})
MATCH (bp:BusinessProcess {id: $bpId})
MERGE (r)-[:PARTICIPATES_IN]->(bp)

Phase 4: Delta As-Is / To-Be (interactive, if applicable)

Goal: Capture changes in the role model between the current state and the target state.

When executed

This phase runs if the project has an As-Is description (existing state). If the project describes only To-Be, this phase is skipped.

Questions for the user

Now let's identify changes to roles relative to the current state (As-Is):

1. Are there roles that appear **only** in To-Be (do not exist in As-Is)?
2. Are there roles whose responsibilities **change** in the transition to To-Be?
3. Are there roles from As-Is that **disappear** in To-Be?

Actions

  1. For each new role --- set property delta_status: 'new' on the node
  2. For each changed role --- set property delta_status: 'changed' and delta_description with the change summary
  3. For each removed role --- set property delta_status: 'removed' and delta_reason
// mcp__neo4j__write-cypher
MATCH (r:BusinessRole {id: $id})
SET r.delta_status = $deltaStatus,
    r.delta_description = $deltaDescription

Presentation format

## Role Delta As-Is / To-Be

| Role | Status | Description of Change |
|------|--------|-----------------------|
| {Role 1} | Unchanged | -- |
| {Role 2} | Changed | Added responsibility: catalog approval |
| {Role 3} | New | Did not exist in As-Is; created for process BP-009 |

Reads / Writes

Reads (Neo4j queries)

reads:
  - "ba_all_roles"                            # all roles with departments and process counts
  - "ba_role_process_matrix"                   # role-process matrix from OWNS/PARTICIPATES_IN
  - "MATCH (ws:WorkflowStep)-[:PERFORMED_BY]->(r:BusinessRole)"  # roles from workflow steps
  - "MATCH (bp:BusinessProcess) RETURN count(bp)"                 # pre-check: processes exist
  - "ba_next_id for BusinessRole (ROL-NN)"                        # next role ID

Writes (Neo4j mutations)

writes:
  - "MERGE (r:BusinessRole {id: $id}) SET ..."            # role nodes (full_name, abbreviation, department, responsibilities)
  - "MERGE (r)-[:OWNS]->(bp)"                             # role owns process (if corrected)
  - "MERGE (r)-[:PARTICIPATES_IN]->(bp)"                  # role participates in process (if added)

No file writes

This skill does NOT create files in docs/. All data is stored in Neo4j. Tables and summaries are generated on-the-fly from graph queries and displayed inline.


Error Handling

Neo4j unavailable

If mcp__neo4j__write-cypher or mcp__neo4j__read-cypher returns an error:

Neo4j is not reachable at bolt://localhost:{$neo4j_bolt_port}. Tell me "start the graph" and I will run node "$HOME/.claude/skills/nacl-core/scripts/graph-doctor.mjs" --fix via Bash (works in Claude Code Desktop and CLI). Or start it yourself from the project root (main checkout, not a worktree):

  • local mode: docker compose -f graph-infra/docker-compose.yml up -d --- if Docker Desktop is not running, open the Docker Desktop app first
  • remote mode: relaunch the sidecar ~/.nacl/sidecar/<project_scope>.sh (Windows: %USERPROFILE%\.nacl\sidecar\<project_scope>.cmd) This skill requires Neo4j --- cannot proceed without it.

Duplicate ID conflict

If MERGE detects a node with the same ID but different properties (unexpected state):

  1. Query the existing node and show it to the user
  2. Ask whether to overwrite or assign a new ID

No processes in graph

No BusinessProcess nodes found in Neo4j. Run /nacl-ba-process first to create the process map, then return to /nacl-ba-roles.


Completion

After all phases are confirmed:

  1. Run the ba_all_roles verification query:
// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)
OPTIONAL MATCH (r)-[:OWNS]->(owned:BusinessProcess)
OPTIONAL MATCH (r)-[:PARTICIPATES_IN]->(part:BusinessProcess)
OPTIONAL MATCH (:WorkflowStep)-[:PERFORMED_BY]->(r)
WITH r, count(DISTINCT owned) AS owns_count,
     count(DISTINCT part) AS participates_count
RETURN r.id AS id, r.full_name AS name, r.department AS department,
       owns_count, participates_count
ORDER BY r.id
  1. Present the final summary:
Business roles defined in Neo4j. Role-process matrix built.

Created/updated:
- {N} BusinessRole nodes (ROL-01 ... ROL-{NN})
- {M} OWNS relationships
- {K} PARTICIPATES_IN relationships

Role-process matrix: {N} roles x {P} processes
Roles without processes: {X} (should be 0)
Processes without owner: {Y} (should be 0)

Next steps:
1. `/nacl-ba-rules` --- catalogue business rules
2. `/nacl-ba-glossary` --- build the domain glossary
3. `/nacl-ba-validate` --- validate consistency of all BA artifacts

Checklist /nacl-ba-roles

Phase 1: Role Identification

  • All BP scanned for roles via OWNS and PARTICIPATES_IN
  • All workflow steps scanned for roles via PERFORMED_BY
  • Role list consolidated and deduplicated
  • IDs ROL-NN assigned (global sequential, never reused)
  • User confirmed completeness of the role list

Phase 2: Role Description

  • Full name specified for each role
  • Department specified for each role
  • Responsibilities described (3-5 items per role)
  • User confirmed the description of each role
  • BusinessRole nodes written to Neo4j (MERGE idempotent)

Phase 3: Role-Process Matrix

  • Matrix built from graph (OWNS and PARTICIPATES_IN)
  • Cross-check with PERFORMED_BY completed
  • Each BP has exactly one owner (O)
  • No roles without any process
  • No processes without an owner
  • IT system role marked only as participant (P), not owner
  • Missing PARTICIPATES_IN edges added (if any)
  • User confirmed the matrix

Phase 4: Delta As-Is / To-Be (if applicable)

  • New roles marked with delta_status: 'new'
  • Changed roles have delta_description set
  • Removed roles have delta_status: 'removed' with reason

General

  • Agent did not invent roles, departments, or responsibilities
  • All constructions confirmed by the user
  • Uncertainties noted and clarifying questions asked
  • User confirmed each phase before proceeding
  • All writes used MERGE for idempotency

Signals

GitHub stars
27
Forks
4
Last commit
Sep 2026
Advanced
Item type
skill
Key
nacl-ba-roles
Source
github.com/itsalt/nacl