/nacl:ba-context — System Context Diagram via Neo4j Graph

SkillDev tools

Define system boundaries in Neo4j graph: scope, stakeholders, external entities, data flows., all data stored as graph nodes and edges. Use when: define system scope with graph, system context diagram, or the user says "/nacl:ba-context".

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-context skill

What this skill tells your AI

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

Purpose

Define system boundaries: what is automated, what stays outside, who interacts with the system and what data is exchanged. All facts are persisted as Neo4j nodes and relationships — no markdown files are produced. Mermaid diagrams are generated from graph queries at render time.

The interactive protocol is identical; only the storage backend changes.


Workflow

┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Phase 1     │    │ Phase 2     │    │ Phase 3     │    │ Phase 4     │
│ System      │───▶│ External    │───▶│ Data        │───▶│ Context     │
│ Scope       │    │ Entities    │    │ Flows       │    │ Diagram     │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
   interactive        interactive       constructive        automated

Each phase ends with:

  1. Summary — what was understood / constructed
  2. Confirmation — request verification from the user
  3. Graph write — idempotent MERGE of nodes and relationships into Neo4j

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


Neo4j Tools

ToolPurpose
mcp__neo4j__read-cypherRead-only queries (list, verify, diagram data)
mcp__neo4j__write-cypherCreate / update nodes and relationships (MERGE)

Connection details are in ${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md.


ID Formats

Node LabelFormatExampleCounter
SystemContextSYS-NNNSYS-001Global sequential
StakeholderSTK-NNSTK-01Global sequential
ExternalEntityEXT-NNEXT-01Global sequential
DataFlowDFL-NNNDFL-001Global sequential

To get the next available ID:

// Example: next SystemContext ID
MATCH (n:SystemContext)
WITH max(toInteger(replace(n.id, 'SYS-', ''))) AS maxNum
RETURN 'SYS-' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 3, '0') AS nextId

Pre-flight Check

Mode full

  1. Query existing SystemContext nodes:
    MATCH (sc:SystemContext) RETURN sc.id, sc.name
    
  2. If nodes exist — warn the user about potential overwrite and ask for confirmation
  3. If no nodes — proceed directly

Mode update

  1. Query existing context:
    MATCH (sc:SystemContext)
    OPTIONAL MATCH (sc)-[:HAS_STAKEHOLDER]->(stk:Stakeholder)
    OPTIONAL MATCH (sc)-[:HAS_EXTERNAL_ENTITY]->(ext:ExternalEntity)
    OPTIONAL MATCH (ext)-[flow:HAS_FLOW]->(sc)
    RETURN sc, collect(DISTINCT stk) AS stakeholders,
           collect(DISTINCT ext) AS external_entities,
           collect(DISTINCT {entity: ext.name, direction: flow.direction, data: flow.data_description}) AS data_flows
    
    (This is the named query ba_system_context from graph-infra/queries/ba-queries.cypher.)
  2. If no SystemContext exists — suggest running in full mode
  3. Show the user the current state and ask what needs to change

Phase 1: System Scope (interactive)

Goal: Define automation boundaries — what the system does, for whom, what is excluded.

Questions for the user

**Phase 1: System Scope**

1. What is the system called?
2. What are the automation goals? (what problems should it solve)
3. Who are the stakeholders? (who is interested and why)
4. What areas are automated? (what is in scope)
5. What is NOT in scope? (explicit exclusions)
6. Are there known constraints or assumptions?

Answer by number: 1 — ..., 2 — ..., 3 — ...

Question format

Ask numbered questions. If the user cannot answer — propose reasonable assumptions explicitly marked [assumption].

Actions after receiving answers

  1. Formulate automation goals (2-5 clear points)
  2. List stakeholders (table: who, role, interest)
  3. Describe boundaries (what is in, what is out)
  4. Record constraints and assumptions
  5. Define success criteria

Graph Write — SystemContext node

MERGE (sc:SystemContext {id: $sysId})
SET sc.name        = $systemName,
    sc.goals       = $goals,          // list of strings
    sc.in_scope    = $inScope,        // list of strings
    sc.out_of_scope = $outOfScope,    // list of strings
    sc.constraints = $constraints,    // list of strings
    sc.assumptions = $assumptions,    // list of strings
    sc.success_criteria = $criteria,  // list of strings
    sc.status      = 'draft',
    sc.created     = date(),
    sc.updated     = date()

Graph Write — Stakeholder nodes

For each stakeholder:

MERGE (stk:Stakeholder {id: $stkId})
SET stk.name     = $name,
    stk.role     = $role,
    stk.interest = $interest

WITH stk
MATCH (sc:SystemContext {id: $sysId})
MERGE (sc)-[:HAS_STAKEHOLDER]->(stk)

Transition

Show the user a Phase 1 summary and ask:

Phase 1 summary:
- System: {{system_name}}
- Goals: {{brief list}}
- Scope: {{what is in}}
- Exclusions: {{what is out}}
- Stakeholders: {{count}} recorded

All correct? Proceed to external entities?

After confirmation -> Phase 2


Phase 2: External Entities (interactive)

Goal: Identify who and what interacts with the system — users, external systems, organizations.

Questions for the user

**Phase 2: External Entities**

Who and what interacts with the system?

For each entity provide:
- Name
- Type: User / External System / Organization
- Description: what it does, why it interacts

Examples:
- "Sales Manager" (User) — creates orders, tracks statuses
- "1C:Accounting" (External System) — receives shipment data
- "Suppliers" (Organization) — provide price lists

Actions after receiving answers

For each entity record:

  1. Name — how the business refers to the entity
  2. Type — User / ExternalSystem / Organization
  3. Description — 1-2 sentences about its interaction role

Graph Write — ExternalEntity nodes

For each entity:

MERGE (ext:ExternalEntity {id: $extId})
SET ext.name        = $name,
    ext.type        = $type,       // "User" | "ExternalSystem" | "Organization"
    ext.description = $description

WITH ext
MATCH (sc:SystemContext {id: $sysId})
MERGE (sc)-[:HAS_EXTERNAL_ENTITY]->(ext)

Summary and confirmation

I have recorded the following external entities:

| # | Entity | Type | Description |
|---|--------|------|-------------|
| 1 | {{entity_1}} | {{type}} | {{description}} |
| 2 | {{entity_2}} | {{type}} | {{description}} |

Is the list complete? Anyone missing?

Transition

After confirmation -> Phase 3


Phase 3: Data Flows (constructive)

Goal: Determine what data enters and exits the system for each external entity.

How it works

This is a constructive phase: the agent proposes data flows based on entity descriptions from Phase 2; the user confirms or corrects.

The agent does NOT invent flows from nothing — it structures and names flows based on what the user already described in Phase 1 and Phase 2.

Actions

  1. For each external entity from Phase 2 determine:

    • Incoming flows (IN) — what data the entity sends TO the system
    • Outgoing flows (OUT) — what data the system sends TO the entity
  2. Name flows concretely:

    • Correct: "Purchase orders", "Stock balance report"
    • Incorrect: "Data", "Information"
  3. If the direction is ambiguous for an entity — ask a clarifying question

Proposal to the user

Based on entity descriptions I propose the following data flows:

| # | Entity | Incoming flows (-> system) | Outgoing flows (system ->) |
|---|--------|----------------------------|----------------------------|
| 1 | {{entity_1}} | {{data_in}} | {{data_out}} |
| 2 | {{entity_2}} | {{data_in}} | {{data_out}} |

Questions:
1. Are the flow directions correct?
2. Are there flows I missed?
3. Should any flows be renamed?

Graph Write — DataFlow nodes and relationships

For each confirmed flow:

MERGE (df:DataFlow {id: $dflId})
SET df.name             = $flowName,
    df.direction        = $direction,        // "IN" | "OUT" | "BOTH"
    df.data_description = $dataDescription

WITH df
MATCH (ext:ExternalEntity {id: $extId})
MATCH (sc:SystemContext {id: $sysId})
MERGE (ext)-[:HAS_FLOW {direction: $direction, data_description: $dataDescription}]->(sc)

Transition

After confirmation -> Phase 4


Phase 4: Context Diagram Generation (automated)

Goal: Build a Mermaid context diagram from the graph and present the final result.

Actions

  1. Query the full system context from the graph using ba_system_context:

    MATCH (sc:SystemContext {id: $sysId})
    OPTIONAL MATCH (sc)-[:HAS_STAKEHOLDER]->(stk:Stakeholder)
    OPTIONAL MATCH (sc)-[:HAS_EXTERNAL_ENTITY]->(ext:ExternalEntity)
    OPTIONAL MATCH (ext)-[flow:HAS_FLOW]->(sc)
    RETURN sc,
           collect(DISTINCT stk) AS stakeholders,
           collect(DISTINCT {id: ext.id, name: ext.name, type: ext.type}) AS external_entities,
           collect(DISTINCT {entity: ext.name, direction: flow.direction, data: flow.data_description}) AS data_flows
    
  2. Build a Mermaid flowchart from query results

  3. Show the diagram to the user for final confirmation

Diagram rules

  1. Each external entity = a node in subgraph "External Entities"
  2. The system = one node in a subgraph with the system name
  3. Arrows are always labeled — what is being transferred
  4. Arrow direction = data flow direction
  5. -->|"flow"| for unidirectional flows
  6. <-->|"flow"| for bidirectional flows
  7. Use flowchart LR for horizontal layout
  8. Use styles: extStyle for external entities, sysStyle for the system

Mermaid template (generated from graph, NOT from files)

flowchart LR
    subgraph ext ["External Entities"]
        E1["{{entity_1}}"]
        E2["{{entity_2}}"]
    end

    subgraph sys ["{{system_name}}"]
        S["{{system_short_name}}"]
    end

    E1 -->|"{{flow_in_1}}"| S
    S -->|"{{flow_out_1}}"| E1
    E2 <-->|"{{flow_2}}"| S

    classDef extStyle fill:#fff3cd,stroke:#ffc107
    classDef sysStyle fill:#d4edda,stroke:#28a745
    class E1,E2 extStyle
    class S sysStyle

Final confirmation

Context diagram generated from Neo4j graph.

Graph nodes created:
- SystemContext: {{sysId}} ({{system_name}})
- Stakeholders: {{count}} nodes
- External Entities: {{count}} nodes
- Data Flows: {{count}} nodes

Verification query:
  ba_system_context (graph-infra/queries/ba-queries.cypher)

Diagram correct? Ready to finalize?

Autonomy Principle

The agent does NOT invent

  • Stakeholder and external entity names
  • External entity types (user / system / organization)
  • Specific data carried by flows
  • Areas in or out of scope

The agent CONSTRUCTS

  • Data flow names based on user descriptions
  • Flow directions (IN / OUT) based on entity roles
  • Mermaid diagram from graph query results
  • Cypher MERGE statements from collected facts

The agent PROPOSES and ASKS

  • "Did I understand correctly that the DPO sends data to the system, not the other way around?"
  • "The flow between TeamCenter and the system is bidirectional — correct?"
  • "I named the flow 'Purchase orders' — is that the right label?"

Reads / Writes

agent: nacl-ba-context
trigger: /nacl:ba-context
mode: interactive (dialogue with user)

reads:
  - Neo4j: SystemContext, Stakeholder, ExternalEntity, DataFlow (in update mode)
  - Reference query: ba_system_context (graph-infra/queries/ba-queries.cypher)

writes:
  - Neo4j node: SystemContext  (SYS-NNN)
  - Neo4j node: Stakeholder   (STK-NN)
  - Neo4j node: ExternalEntity (EXT-NN)
  - Neo4j node: DataFlow      (DFL-NNN)
  - Neo4j rel:  (:SystemContext)-[:HAS_STAKEHOLDER]->(:Stakeholder)
  - Neo4j rel:  (:SystemContext)-[:HAS_EXTERNAL_ENTITY]->(:ExternalEntity)
  - Neo4j rel:  (:ExternalEntity)-[:HAS_FLOW]->(:SystemContext)

creates_directories: []   # No file output — graph only

calls_next:
  - nacl-ba-process

parameters:
  scope: full | update  # full = from scratch, update = modify existing context
  lang: ru | en         # output language (default: ru)

Language

Supports --lang=en for English output. See ${CLAUDE_PLUGIN_ROOT}/nacl-core/lang-directive.md. When --lang=en: all generated text, node names, descriptions in English. Default: Russian (ru).


Working with Incomplete Answers

If the user cannot answer all questions:

  1. Record what is known
  2. Propose reasonable assumptions with justification:
    Assumption: The system has one external user role — "Client".
    Justification: Only one end-user type was mentioned in the description.
    
  3. Store assumptions in the SystemContext.assumptions property (string list)
  4. Continue with the assumptions in mind
  5. If there are open questions, record them as a separate property or note in the summary

Completion

After Phase 4:

  1. Run the verification query to confirm graph state:

    MATCH (sc:SystemContext)
    OPTIONAL MATCH (sc)-[:HAS_STAKEHOLDER]->(stk)
    OPTIONAL MATCH (sc)-[:HAS_EXTERNAL_ENTITY]->(ext)
    OPTIONAL MATCH (ext)-[flow:HAS_FLOW]->(sc)
    RETURN sc.id, sc.name,
           count(DISTINCT stk) AS stakeholder_count,
           count(DISTINCT ext) AS entity_count,
           count(DISTINCT flow) AS flow_count
    
  2. Suggest next steps:

    System context defined in Neo4j graph.
    
    Next steps:
    1. /nacl:ba-process — define business processes in the graph
    2. /nacl:ba-full — run full BA cycle in graph mode
    

Schema Reference

Node property documentation from graph-infra/schema/ba-schema.cypher:

SystemContext {
  id: String,           // SYS-NNN
  name: String,
  goals: [String],
  in_scope: [String],
  out_of_scope: [String],
  constraints: [String],
  assumptions: [String],
  success_criteria: [String],
  status: String,       // "draft" | "confirmed"
  created: Date,
  updated: Date
}

Stakeholder {
  id: String,           // STK-NN
  name: String,
  role: String,
  interest: String
}

ExternalEntity {
  id: String,           // EXT-NN
  name: String,
  type: String,         // "User" | "ExternalSystem" | "Organization"
  description: String
}

DataFlow {
  id: String,           // DFL-NNN
  name: String,
  direction: String,    // "IN" | "OUT" | "BOTH"
  data_description: String
}

Relationships:

(:SystemContext)-[:HAS_STAKEHOLDER]->(:Stakeholder)
(:SystemContext)-[:HAS_EXTERNAL_ENTITY]->(:ExternalEntity)
(:ExternalEntity)-[:HAS_FLOW {direction, data_description}]->(:SystemContext)

Checklist /nacl:ba-context

Before completing, verify:

Phase 1: System Scope

  • SystemContext node created in Neo4j (SYS-NNN)
  • System name recorded
  • Automation goals formulated (2-5 points)
  • Stakeholder nodes created with roles and interests
  • Boundaries defined (in_scope and out_of_scope)
  • Constraints and assumptions recorded
  • Success criteria defined

Phase 2: External Entities

  • All external entities recorded as ExternalEntity nodes
  • Each has a type: User / ExternalSystem / Organization
  • Each has a description of its interaction role
  • HAS_EXTERNAL_ENTITY relationships link to SystemContext
  • User confirmed completeness of the list

Phase 3: Data Flows

  • For each entity, incoming flows (IN) are defined
  • For each entity, outgoing flows (OUT) are defined
  • Flows are named concretely (not "data" or "information")
  • DataFlow nodes created with HAS_FLOW relationships
  • User confirmed directions and names

Phase 4: Context Diagram

  • Mermaid flowchart generated from graph query
  • All arrows are labeled
  • All external entities from Phase 2 are present in diagram
  • All flows from Phase 3 are reflected in diagram
  • User approved the final diagram

General

  • User confirmed each phase
  • Assumptions documented in SystemContext.assumptions
  • No facts invented by the agent
  • Verification query returns expected counts

Signals

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