<< All versions

Skill v1.0.2

currentAutomated scan96/100
arnoudkooi/sn-scriptsync/snu-artifacts

+1 new, ~2 modified

──Details
PublishedOctober 31, 2026 at 12:51 AM
Content Hashsha256:e3cca69575ee99f9...
Git SHAc967e04cd9a1
Bump Typepatch
Compare with v1.0.1
──Files
Files (1 file, 14.5 KB)
SKILL.md14.5 KBactive
SKILL.md · 351 lines · 14.5 KB

name: snu-artifacts description: "How sn-scriptsync maps ServiceNow artifacts to files: the instance/scope/table layout, naming conventions per artifact type, creating new artifacts, and the _map.json / structure.json files. Read this when creating, naming, or organizing ServiceNow files." metadata: version: "1.0.2"


<!-- SN-SCRIPTSYNC:SKILL instructionsSchemaVersion=35 -->

SN ScriptSync — Artifacts & File Structure

Conventions for naming, creating, and organizing ServiceNow artifacts as local files.

File Naming Conventions

⚠️ CRITICAL: Do NOT Create Separate Field Files for Configuration

NEVER create separate files for configuration/metadata fields:

  • ❌ MyBusinessRule.collection.js (table name - this is a STRING reference)
  • ❌ MyBusinessRule.when.js (when to run - this is a STRING choice)
  • ❌ MyBusinessRule.active.js (active status - this is a BOOLEAN)
  • ❌ MyUIAction.table.js (table reference - this is a STRING)
  • ❌ MyOperation.http_method.js (HTTP method - this is a STRING)
  • ❌ MyScript.action_insert.js (action flag - this is a BOOLEAN)

These configuration fields belong in the creation payload ONLY, not as separate files.

✅ DO create files for actual script/code/content fields:

  1. Script fields (contain executable code):
  • script → MyBusinessRule.script.js
  • operation_script → MyOperation.operation_script.js
  • client_script → MyWidget.client_script.js
  • server_script → MyWidget.server_script.js
  • processing_script → MyUIPage.processing_script.js
  1. Template/HTML fields (contain markup):
  • template → MyWidget.template.html
  • html → MyUIPage.html
  1. CSS fields (contain styles):
  • css → MyWidget.css.scss
  1. Special files:
  • option_schema.json (widget configuration schema)
  • demo_data.json (widget demo data)
  • link.js (widget link function)

Rule of thumb: If the field contains code, markup, or styles → create a file. If it's a configuration value (string, boolean, number, reference) → include in payload only.

Common Fields Reference Table

Field NameTypeCreate File?Example
scriptCODE✅ YesMyBR.script.js
operation_scriptCODE✅ YesMyOperation.operation_script.js
client_scriptCODE✅ YesMyWidget.client_script.js
server_scriptCODE✅ YesMyWidget.server_script.js
processing_scriptCODE✅ YesMyUIPage.processing_script.js
templateMARKUP✅ YesMyWidget.template.html
htmlMARKUP✅ YesMyUIPage.html
cssSTYLES✅ YesMyWidget.css.scss
linkCODE✅ YesMyWidget.link.js
collectionCONFIG (string)❌ NoIn payload: "collection": "incident"
whenCONFIG (string)❌ NoIn payload: "when": "before"
activeCONFIG (boolean)❌ NoIn payload: "active": "true"
http_methodCONFIG (string)❌ NoIn payload: "http_method": "GET"
tableCONFIG (string)❌ NoIn payload: "table": "incident"
action_insertCONFIG (boolean)❌ NoIn payload: "action_insert": "true"
action_updateCONFIG (boolean)❌ NoIn payload: "action_update": "true"
priorityCONFIG (number)❌ NoIn payload: "priority": "100"
orderCONFIG (number)❌ NoIn payload: "order": "100"
web_service_definitionCONFIG (reference)❌ NoIn payload: "web_service_definition": "abc123..."

Standard Scripts

  • Use the artifact name with .script.js extension
  • Example: HelloWorldUtils.script.js, DummyIncidentBR.script.js

Calculation Fields

  • Use field name with .calculation.js extension
  • Example: Foreign.calculation.js

Client Scripts for UI Actions

  • Use artifact name with .client_script_v2.js extension
  • Example: LargeBold.client_script_v2.js

Service Portal Widgets

  • Widgets are folders containing multiple files
  • File names: template.html, client_script.js, css.scss, script.js, etc.

Creating New Artifacts

Important: Understanding Table Metadata

When creating a new artifact, the extension needs to understand the table structure:

Key Considerations:

  1. Mandatory Reference Fields: Some tables require references to other records (cannot be empty)
  2. Field Mappings: Different tables store scripts in different fields
  3. Required Setup: Some artifacts need parent records to exist first

Example: Scripted REST API (sys_ws_operation)

A sys_ws_operation record requires:

  • Mandatory Reference: web_service_definition field must reference a sys_ws_definition record
  • Script Field: The script content is stored in the operation_script field
  • Parent Record Required: You must first create or have an existing REST API service definition

Workflow for Complex Artifacts:

  1. Extension detects new file
  2. Extension fetches table metadata from ServiceNow
  3. Extension analyzes mandatory fields and references
  4. Extension prompts user: "This requires a web_service_definition reference. Do you want to:
  • Select an existing REST API service?
  • Create a new REST API service?"
  1. User provides required information
  2. Extension creates the record with all required fields
  3. Extension updates _map.json with the new sys_id

Pulling Existing Records (pull_records)

Use `pull_records` to fetch existing records (Script Includes, Business Rules, Widgets, UI Pages, etc.) matching a query or specific sys_id / sys_ids and write their code fields to disk with automatic _map.json registration:

json
{
"command": "pull_records",
"params": {
"table": "sys_script",
"query": "nameSTARTSWITHincident^active=true",
"limit": 20
}
}

This is the recommended way to pull scripts in the Global scope (where "Load Scope" is not practical) or ad-hoc sets of records across any table.

Working with Scoped Applications

⚠️ IMPORTANT: Do NOT create scope folders manually

Before creating files in a new scope folder:

  1. Sync or pull at least one artifact first from ServiceNow for that scope (via pull_records or the SN Utils sync button)
  2. This ensures the scope exists and the folder structure is correct
  3. The extension will create the scope folder automatically during the first sync

Why this matters:

  • Scope names must match exactly with ServiceNow
  • The scope must exist in the instance
  • Incorrect scope names will cause sync failures

Correct Workflow:

  1. Create or identify a scope in ServiceNow (e.g., x_abc_my_app)
  2. Create at least one artifact in that scope in ServiceNow
  3. Pull that artifact using pull_records with {"table": "sys_script_include", "query": "sys_scope.scope=x_abc_my_app"}
  4. The extension creates: <instance>/x_abc_my_app/<table>/
  5. Now you can create new files in that scope folder

Creating Custom Tables

Use the typed `create_table` command — don't drive create_artifact against sys_db_object by hand. ServiceNow auto-creates the physical table plus its base sys_* fields (sys_id, sys_created_on, sys_updated_on, …); you only add your own columns.

Recipe:

  1. `create_table` with name, label, optional scope and extends. With a non-global scope, the name is prefixed for you as <scope>_<name> (e.g. x_acme_myapp_project). The prefixed-vs-unprefixed naming is the usual stumbling block — let the command handle it, or pass an already-prefixed x_... name.
  2. `add_column` for each field. Set display: true on the column you want as the display value (no separate update_record needed), and pass mandatory / default / choices inline so the column is usable in one call.
  3. Seed data rows with rest_request POST /api/now/table/<name> (requires sn-scriptsync.restRequest.enabled). This is the blessed path for plain data rows — create_artifact requires fields.name, which is awkward when the display field isn't name.

Fallback (no typed command available): create the table via create_artifact/rest_request against sys_db_object using the full scoped name (x_<scope>_<name>); the base sys_* fields are created automatically; then add_column for the rest and set the display field.

Large / multi-field payloads (widgets)

When a payload has several large or multiline code fields — e.g. a widget's template / css / script / client_script — do not hand-build the JSON on a shell command line; the escaping is error-prone. Write the request body to a file with JSON.stringify (so newlines and quotes are encoded correctly) and send it with curl -d @body.json, or use the file transport. This applies to any artifact with multiline/large field values.

Verifying a widget preview (component-only screenshot)

To show just the rendered widget without a per-tab screenshot grant, combine activate_tab with the CDP capture_full_page selector:

  1. activate_tab with openIfNotFound: true and waitForLoad: true (open/activate the widget preview).
  2. capture_full_page with selector: ".my-widget" (or the widget's root class) for a clean, component-only screenshot — no per-tab grant required.

(capture_full_page uses the browser debugger — preflight with get_capabilities → cdp.available.)

Step-by-Step: Creating Simple Artifacts

For simple artifacts like Script Includes (no mandatory references):

Step 1: Create the file in the correct location

<your_instance>/global/sys_script_include/MyNewUtils.script.js

Or for a scoped app (after syncing at least one artifact):

<your_instance>/<your_scope>/sys_script_include/MyNewUtils.script.js

Step 2: Write your code

javascript
var MyNewUtils = Class.create();
MyNewUtils.prototype = {
initialize: function() {
},
myFunction: function() {
return 'Hello World';
},
type: 'MyNewUtils'
};

Step 3: Save the file

The sn-scriptsync extension will:

  1. Detect the new file
  2. Fetch table metadata to check for mandatory fields
  3. Create the record in ServiceNow (prompting for required info if needed)
  4. Automatically update _map.json with the new sys_id

⚠️ IMPORTANT: Only create the `.script.js` file

  • Do NOT create separate files like .collection.js, .when.js, .active.js
  • The extension will prompt for required fields (like collection for Business Rules)
  • OR use create_artifact command to include all fields in one payload

Common Table Requirements

TableScript FieldMandatory ReferencesNotes
sys_script_includescriptNoneSimple creation
sys_scriptscriptcollection (table name)Must specify which table
sys_ws_operationoperation_scriptweb_service_definitionNeeds parent REST API
sys_ui_actionscripttable (table name)Must specify which table
sys_script_clientscripttable (table name)Must specify which table
sp_widgetMultiple filesNoneWidget folder structure
rm_storyN/ANoneSee rm_story specific guidance below

rm_story (Story) Table Specifics

Key Fields:

  • name - Required by create_artifact (can be same as short_description)
  • short_description - The story title/summary
  • description - Detailed description (plain text)
  • acceptance_criteria - HTML field - use HTML formatting, not markdown
  • state - Story state (see values below)
  • priority - Priority level (1-4)

State Values:

StateValueDescription
Draft-6Initial state, not ready for work
Ready1Ready for development
Work in Progress2Currently being worked on
Ready for Testing-7Development complete, ready for QA
Testing-8Currently being tested
Complete3Story is done
Cancelled4Story was cancelled

⚠️ IMPORTANT: acceptance_criteria is an HTML field!

Use HTML tags for formatting, NOT markdown:

html
<!-- ✅ CORRECT - HTML formatting -->
<b>Acceptance Criteria:</b>
<ul>
<li>Widget displays correctly</li>
<li>Score tracking works</li>
<li>No console errors</li>
</ul>
<b>Definition of Done:</b>
<ul>
<li>Code reviewed</li>
<li>Unit tests pass</li>
</ul>
markdown
<!-- ❌ INCORRECT - Markdown won't render -->
**Acceptance Criteria:**
-Widget displays correctly
-Score tracking works

Example: Creating a Story

json
{
"command": "create_artifact",
"params": {
"table": "rm_story",
"scope": "global",
"fields": {
"name": "Implement User Dashboard Widget",
"short_description": "Implement User Dashboard Widget",
"description": "Create a Service Portal widget that displays user statistics and recent activity.",
"acceptance_criteria": "<b>Acceptance Criteria:</b><ul><li>Widget shows user stats</li><li>Responsive design</li></ul><b>Definition of Done:</b><ul><li>Code reviewed</li><li>Tested in dev</li></ul>",
"state": "1",
"priority": "2"
}
}
}

Updating Story State:

json
{
"command": "update_record",
"params": {
"table": "rm_story",
"sys_id": "abc123...",
"field": "state",
"content": "-7"
}
}

Note: State values are strings (e.g., "-7" not -7)

Handling Mandatory References

When the extension detects a mandatory reference field:

The extension should:

  1. Query ServiceNow for available reference options
  2. Present choices to the user
  3. Allow creation of a new reference record if needed
  4. Validate the reference exists before creating the artifact

The extension should NOT:

  • Set reference fields to empty strings
  • Create records without required references
  • Assume default values for mandatory fields

Fetching Table Metadata

Before creating a new record, the extension should:

  1. Query the ServiceNow API to get table dictionary information:

`` GET /api/now/table/sys_dictionary?sysparm_query=name=<table_name>^ORDERBYelement ``

  1. Analyze mandatory fields: Check for fields where mandatory=true
  1. Identify reference fields: Check reference field for reference table names
  1. Map script fields: Different tables use different field names:
  • Most tables: script
  • REST API Operations: operation_script
  • UI Pages: Multiple fields (html, client_script, processing_script)
  1. Consult ServiceNow documentation if needed for complex tables:
  • ServiceNow Docs: https://docs.servicenow.com/
  • Table API documentation
  • Field specifications and requirements
← v1.0.1All versions