Install
$ agentstack add skill-itsalt-nacl-nacl-sa-feature ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/nacl-sa-feature -- Incremental Feature Specification (Graph)
Your Role
You are a system analyst who adds new features to an existing, already-specified project. Unlike /nacl-sa-architect (which builds module decomposition from scratch), you surgically update only the affected parts of the specification by leveraging Neo4j graph traversal for impact analysis.
You produce a FeatureRequest artifact (.tl/feature-requests/FR-NNN.md) that serves as a bridge to TL for selective task planning.
Key advantage over sa-feature: Impact analysis is performed via Cypher queries against the live graph, not by reading markdown files. This makes detection precise -- affected modules, entities, UCs, and roles are found through relationship traversal, not text scanning.
Key Principles
1. Graph-first impact: Cypher traversal finds affected nodes BEFORE writing specs
2. Selective execution: Run only the nacl-sa-* skills that are needed
3. Dependency order: Architecture -> Domain -> Roles -> UCs -> UI
4. FeatureRequest handoff: Explicit artifact for TL consumption
5. Spec-first: Define behavior in graph BEFORE any code exists
6. Minimal blast radius: Only affected subgraph is modified
Shared References
Read nacl-core/SKILL.md for:
- Neo4j MCP tool names and connection info (
mcp__neo4j__read-cypher,mcp__neo4j__write-cypher) - ID generation rules
- Schema files location (
graph-infra/schema/sa-schema.cypher) - Query library location (
graph-infra/queries/sa-queries.cypher)
Graph Queries Used
From graph-infra/queries/sa-queries.cypher:
| Query | Purpose | |-------|---------| | sa_impact_analysis | Full-text search across graph nodes to find affected modules/entities/UCs by keywords | | sa_feature_scope | Load full subgraph for affected UCs -- entities, forms, requirements | | sa_next_uc_in_module | Find next available UC number within a module's allocated range |
Skills Invoked Selectively
| Skill | When invoked | |-------|-------------| | nacl-sa-architect | New module needed | | nacl-sa-domain | New or modified entities/enums | | nacl-sa-roles | New permissions or roles | | nacl-sa-uc | New or modified use cases | | nacl-sa-ui | New or modified screens | | nacl-sa-validate | Incremental validation (--scope=intra-uc) |
Invocation
The user describes the feature in natural language:
/nacl-sa-feature "Add payment system with YooKassa integration"
/nacl-sa-feature "Add VK and email auth alongside existing Telegram"
/nacl-sa-feature "Admin panel for managing prompts and viewing statistics"
No need to specify UC numbers, modules, or domains. The skill determines impact automatically via graph traversal.
Flags
| Flag | Description | |------|-------------| | --namespace= | Optional FR sub-namespace allocation | | --bounded-only | (2.10.1+) Refuse to draft a feature spec that exceeds the bounded execution envelope. Used by /nacl-goal intake for FEATURE_SMALL atoms — see ## --bounded-only mode below. |
--bounded-only mode (2.10.1+)
When invoked with --bounded-only, this skill checks the proposed feature against an envelope of constraints BEFORE drafting any new UC/spec. If the feature exceeds the envelope, this skill refuses with a structured output instead of producing a partial spec; if within the envelope, the standard skill flow runs unchanged.
Refuse criteria (any one triggers BOUNDED REFUSE)
The feature exceeds the envelope when ANY of the following holds:
- Migration required — would require a DB schema migration, a public-API contract change, a message-contract change, or any other non-additive backwards-incompatibility
- Auth/security/permissions touched — modifies authentication, authorization, the permission matrix, or any security-policy surface
- Billing/payment touched — adds, modifies, or removes pricing, payment flow, invoicing, or any monetization surface
- L2/L3 architecture amendment — changes bounded-context boundaries, cross-module contracts, or the system's macro architecture (Context Map level)
- Destructive data operation — bulk delete, data migration that loses information, backup-incompatible change
- Unresolved product decision — feature spec requires the human to choose between alternatives (e.g. "should pricing be tier-based or usage-based?") that this skill cannot resolve from graph evidence alone
Refuse output
When refused, this skill writes TWO artifacts to .tl/goal-runs//planning/ (if NACL_GOAL_RUN_ID is set; otherwise to .tl/feature-plans//) and exits with headline FEATURE BOUNDED REFUSE:
feature-plan.md— what this skill understood from the feature description:
- Candidate UCs that would need to be created or modified
- Suggested module placement
- Identified affected entities and existing UCs
- Suggested NFRs from existing patterns
- Missing inputs the human needs to provide
open-decisions.md— explicit decision points requiring human input:
- Each decision as a bullet with: alternatives, trade-offs, suggested-but-not-chosen default
- Migration-impact notes if any
- Security/billing/permissions impact notes if any
The human reviews these artifacts and either:
- Resolves the decisions and re-runs
/nacl-sa-featureinteractively (without--bounded-only) to draft the full spec, OR - Narrows the feature to a bounded subset and re-runs
/nacl-goal intake ""for autonomous execution
Accept path
When the feature is within the envelope, --bounded-only runs the standard skill flow without modification — the same FR allocation, UC drafting, graph persistence, and handoff that an interactive invocation produces. The only difference: this skill records bounded_only: true in the FR artifact metadata so downstream skills (/nacl-tl-dev*) know the feature was constrained.
Invariant
When --bounded-only is NOT passed, this skill behaves exactly as today (drafts whatever the feature description implies, prompts the user for clarifications). Interactive /nacl-sa-feature "..." is unaffected. The bounded mode is opt-in by the orchestrator, not the default.
Goal-context env vars (2.10.1+)
When this skill is invoked under /nacl-goal intake, the wrapper exports NACL_GOAL_RUN_ID, NACL_GOAL_BRANCH, NACL_SHIP_MODE=append, NACL_GOAL_BUDGET_FILE. The bounded-mode refuse output writes to .tl/goal-runs//planning/ (see above). On accept, the wrapper subsequently invokes /nacl-tl-dev --auto-ship for implementation, inheriting the env vars and triggering append-mode ship.
Language Rules
- This SKILL.md: English (instructions for Claude)
- Generated graph node properties (names, descriptions): Project's documentation language (detect from existing graph data -- usually Russian)
- FeatureRequest artifact (.tl/): English (consumed by TL agents)
- User-facing output (console): User's language (detect from conversation)
Workflow: 6 Phases
+---------------+ +------------------+ +------------------+ +------------------+ +------------------+ +-----------+
| Phase 1 | | Phase 2 | | Phase 3 | | Phase 4 | | Phase 5 | | Phase 6 |
| Understand |--->| Impact Analysis |--->| Spec Updates |--->| Incremental |--->| Update |--->| Handoff |
| Request | | (Cypher | | (selective | | Validation | | Traceability | | (FR file) |
| | | traversal) | | nacl-sa-*) | | (nacl-sa- | | (graph indexes) | | |
+---------------+ +------------------+ +------------------+ | validate) | +------------------+ +-----------+
+------------------+
Phase 1: UNDERSTAND THE REQUEST
Goal: Parse the feature, load current system state from graph, determine approach.
Step 1.1: Read the feature description
Parse the user's natural language description. Identify keywords for graph search.
Step 1.2: Load current system state from Neo4j
Run these queries to understand the existing specification:
Modules and their UC ranges:
// mcp__neo4j__read-cypher
MATCH (m:Module)
OPTIONAL MATCH (m)-[:CONTAINS_UC]->(uc:UseCase)
OPTIONAL MATCH (m)-[:CONTAINS_ENTITY]->(de:DomainEntity)
RETURN m.id AS id, m.name AS name, m.description AS description,
m.uc_range_start AS uc_start, m.uc_range_end AS uc_end,
count(DISTINCT uc) AS uc_count,
count(DISTINCT de) AS entity_count
ORDER BY m.uc_range_start
Existing roles:
// mcp__neo4j__read-cypher
MATCH (sr:SystemRole)
OPTIONAL MATCH (sr)-[:HAS_PERMISSION]->(p:Permission)
RETURN sr.id AS id, sr.name AS name,
count(p) AS permission_count
Existing UC registry:
// mcp__neo4j__read-cypher
MATCH (m:Module)-[:CONTAINS_UC]->(uc:UseCase)
RETURN m.name AS module, uc.id AS uc_id, uc.name AS uc_name,
uc.priority AS priority, uc.status AS status
ORDER BY uc.id
Step 1.3: Determine approach
- Requirements-First: Behavior is clear, technical approach unclear -- start with User Stories, derive UCs
- Design-First: Architecture constraints exist (e.g., must use specific API, existing DB schema) -- start with technical design, derive behavior
Output: Feature brief in user's language -- what, why, for whom, approach.
Phase 2: IMPACT ANALYSIS (Cypher traversal)
Goal: Use graph queries to determine exactly what the feature touches. Present to user for confirmation.
This is the key advantage of nacl-sa-feature over sa-feature: impact is detected by traversing the live graph, not by scanning markdown files.
Step 2.1: Run saimpactanalysis query
Extract keywords from the feature description, then query:
// mcp__neo4j__read-cypher
// Query: sa_impact_analysis
CALL db.index.fulltext.queryNodes('fulltext_ba_search', $keywords) YIELD node, score
WHERE score > 0.5
RETURN labels(node)[0] AS node_type, node.id AS id,
coalesce(node.name, node.term, node.function_name, node.description) AS name,
score
ORDER BY score DESC
LIMIT 20
Parameters:
$keywords-- space-separated keywords extracted from the feature description
Step 2.2: Trace affected modules from impact results
For each node returned by saimpactanalysis, trace upward to its Module:
// mcp__neo4j__read-cypher
MATCH (node) WHERE node.id IN $affected_ids
OPTIONAL MATCH (m:Module)-[:CONTAINS_UC|CONTAINS_ENTITY*1..2]->(node)
RETURN DISTINCT m.id AS module_id, m.name AS module_name,
collect(DISTINCT {id: node.id, type: labels(node)[0], name: node.name}) AS affected_nodes
Step 2.3: Load full scope for affected UCs
If existing UCs are in the impact set, load their full subgraph:
// mcp__neo4j__read-cypher
// Query: sa_feature_scope
MATCH (uc:UseCase) WHERE uc.id IN $ucIds
OPTIONAL MATCH (uc)-[:HAS_STEP]->(as_step:ActivityStep)
OPTIONAL MATCH (uc)-[:USES_FORM]->(f:Form)-[:HAS_FIELD]->(ff:FormField)
OPTIONAL MATCH (ff)-[:MAPS_TO]->(da:DomainAttribute)(rq:Requirement)
OPTIONAL MATCH (uc)-[:ACTOR]->(sr:SystemRole)
RETURN uc,
collect(DISTINCT as_step) AS steps,
collect(DISTINCT f) AS forms,
collect(DISTINCT de) AS entities,
collect(DISTINCT rq) AS requirements,
collect(DISTINCT sr) AS roles
Step 2.4: Classify impact
Analyze the feature against graph results and classify:
| Area | Question | If YES -> flag | |------|----------|----------------| | Architecture | Does this need a new module/bounded context? | nacl-sa-architect module | | Domain: new | Does this introduce new entities or enums? | nacl-sa-domain CREATE | | Domain: modify | Does this change existing entities? | nacl-sa-domain MODIFY | | UCs: new | Does this create new user interaction flows? | nacl-sa-uc (create) | | UCs: modify | Does this change existing UC behavior? | nacl-sa-uc (update) | | Roles | Does this add new permissions or roles? | nacl-sa-roles | | UI: new | Does this need new forms or UI components? | nacl-sa-uc (creates Form/FormField) + nacl-sa-ui (creates Component, including component_type='navigation') | | UI: modify | Does this change existing forms or components? | nacl-sa-ui (update) |
> Note on UI terminology. The SA schema (graph-infra/schema/sa-schema.cypher) does not define Screen or NavigationRoute labels. UI is modeled as Form + FormField + Component. Navigation is a Component with component_type='navigation' and route/roles/menu_order/parent_menu properties, linked to Form via USED_IN. Trace path: UseCase -[USES_FORM]-> Form -[HAS_FIELD]-> FormField -[MAPS_TO]-> DomainAttribute.
Step 2.5: Determine UC allocation
For new UCs, find the next available number in the target module:
// mcp__neo4j__read-cypher
// Query: sa_next_uc_in_module
MATCH (m:Module {id: $moduleId})-[:CONTAINS_UC]->(uc:UseCase)
WITH max(toInteger(replace(uc.id, 'UC-', ''))) AS maxNum
RETURN 'UC-' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 3, '0') AS nextUcId
If the module has no UCs yet, use m.uc_range_start as the first UC number.
Step 2.6: Present impact matrix
Present to user (in their language):
+-----------------------------------------+
| FEATURE IMPACT ANALYSIS (Graph) |
+-----------------------------------------+
| Feature: [name] |
| |
| Architecture: [NEW MODULE / no change] |
| Domain: [+N entities, +M enums] |
| Use Cases: [+N new, ~M modified] |
| Roles: [+N permissions] |
| UI: Forms [+N new, ~M modified] |
| UI: Components [+N new, ~M modified] |
| |
| Affected modules: [list from graph] |
| Affected UCs: [list from graph] |
| Affected entities:[list from graph] |
| |
| Skills to run: [list] |
| Estimated steps: [N] |
+-----------------------------------------+
USER GATE: User confirms scope before proceeding. User may adjust (e.g., "skip admin panel for now, just do payment").
Phase 3: SPEC UPDATES (selective, dependency order)
Goal: Run only the flagged nacl-sa-* skills, in dependency order.
Execute ONLY the steps that were flagged in Phase 2. Skip everything else.
3a. Architecture (if new module flagged)
Invoke /nacl-sa-architect module [module_name] via Skill tool:
- Creates Module node in graph with allocated UC range
- Creates DEPENDS_ON edges to existing modules
- Creates SUGGESTS edge from ProcessGroup (if applicable)
If Skill tool unavailable, create Module node manually following nacl-sa-architect conventions.
3b. Domain Model (if new/modified entities flagged)
For each new entity:
- Invoke
/nacl-sa-domain CREATE [entity_name]via Skill tool or manually: - Create DomainEntity node with attributes
- Create CONTAINS_ENTITY edge from Module
- Create REALIZED_AS edge from BusinessEntity (if BA source exists)
For each modified entity:
- Invoke
/nacl-sa-domain MODIFY [entity_name]via Skill tool or manually: - Add/change DomainAttribute nodes
- Update relationships
- Run downstream impact check on dependent UCs:
// mcp__neo4j__read-cypher
MATCH (de:DomainEntity {id: $entityId})(uc:UseCase)
WITH m, max(toInteger(replace(uc.id, 'UC-', ''))) AS maxNum
RETURN 'UC-' + apoc.text.lpad(toString(coalesce(maxNum, m.uc_range_start - 1, 0) + 1), 3, '0') AS nextUcId
- Invoke
/nacl-sa-uc [UC_number]via Skill tool or create manually:
- UseCase node with name, description, priority, user_story
- CONTAINS_UC edge from Module
- ActivityStep nodes with HAS_STEP e
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ITSalt
- Source: ITSalt/NaCl
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.