This document describes the implemented features and provides guidance for future development or modifications.
Files: src/layout/projectCreator.ts
Command: soar.createProject - "Create New Soar Project"
Functionality:
- Creates a complete Soar project structure matching VisualSoar's behavior
- Prompts user for directory and agent name
- Generates default datamap with standard Soar attributes
- Creates file scaffolding with proper folder structure
Generated Structure:
AgentName/
├── AgentName.vsa.json # Project file with datamap and layout
├── AgentName.soar # Main load file
└── AgentName/ # Agent folder
├── _firstload.soar # First load file (empty)
├── AgentName_source.soar # Source file with includes
├── initialize-AgentName.soar # Initialization operator
├── all/ # Generic rules folder
│ └── all_source.soar
└── elaborations/ # Elaborations folder
├── _all.soar # State propagation rules
├── top-state.soar # Top-state elaboration
└── elaborations_source.soar
Default Datamap:
- Root state with:
^io,^name,^operator,^type,^superstate,^top-state - Memory systems:
^epmem,^smem,^reward-link - IO structure:
^io.input-link,^io.output-link(empty SOAR_ID) - Initialize operator with proper propose/apply rules
Validation:
- Agent name must start with letter
- Only alphanumeric, hyphens, and underscores allowed
- Directory must exist
- Prevents overwriting existing projects
Files: syntaxes/soar.tmLanguage.json, language-configuration.json
Implementation:
- Complete TextMate grammar covering all Soar language elements
- Keywords:
sp,gp,state,operator,impasse, etc. - Variables:
<identifier>patterns - Attributes:
^attribute-namepatterns - Comments: Single-line
#and block#|...|# - String literals with escape sequences
- Numeric literals (integers and floats)
- RHS functions and operators
Auto-closing Pairs: (), {}, [], <>, "", ||
Code Folding: Production blocks, comments
Files: snippets/soar.json
Available Snippets:
spp: Simple productionspn: Production with negationgpp: Goal productionoperator-prop: Operator proposaloperator-app: Operator applicationoperator-term: Operator terminationelab: Elaboration productionrhs-make: RHS make actionrhs-remove: RHS remove action
Files: src/server/soarLanguageServer.ts, src/client/lspClient.ts
Capabilities:
- Document synchronization
- Diagnostic reporting (validation errors)
- Foundation for future features (hover, completion, etc.)
Key Features:
- Activates on
.soarfile open - Parses Soar productions
- Validates against datamap
- Reports errors with accurate positions
Files: src/server/soarParser.ts, src/server/soarTypes.ts
Parsing Capabilities:
- Production detection (
sp,gp) - Production name extraction
- Variable tracking (
<var>) - Attribute extraction (
^attr) - Function call detection
- Accurate Position Tracking: Properly calculates line/column for multi-line productions
Critical Method: getPositionInBody() - Tracks newlines and characters
*within production body to compute absolute document positions.
Files: src/server/visualSoarProject.ts, src/server/projectLoader.ts
Schema Support:
- VisualSoar 9.6.4 project schema (version 6)
- Full type definitions for datamap and layout
- Bidirectional compatibility
Project Detection:
- Auto-finds
.vsa.json,.vsproj,.soarprojfiles - Loads on workspace open
- Builds indices for fast lookups
Data Structures:
ProjectContext {
projectFile: string;
project: VisualSoarProject;
datamapIndex: Map<string, DMVertex>;
layoutIndex: Map<string, LayoutNode>;
}Files: src/datamap/datamapTreeProvider.ts
Features:
- Hierarchical display of datamap structure
- Shows node names instead of IDs
- Removes
^prefix from attributes - Type-specific icons
- Linked attribute awareness (owner/inbound metadata, link badges, read-only context)
- Descriptions show:
- Attribute counts for SOAR_ID
- Enumeration choices
- Operator names for ^operator attributes
Cycle Detection:
- Tracks ancestor IDs to prevent infinite loops
- Labels cyclic references as "(cycle)"
- Makes cyclic references non-expandable
Multiple Datamap Views:
-
Metadata Cache:
DatamapMetadataCachecomputes owners, inbound counts, and cycle info so the tree, commands, and validators share a single source of truth for linked edges. -
View root datamap by default
-
Switch to substate datamaps via "View Datamap" command
-
Shows which datamap is active (e.g., "move-block (substate)")
-
Return to root via home icon button
Methods:
setDatamapRoot(vertexId): Switch to different datamapgetCurrentRootId(): Get current datamap being viewedloadProject(uri): Load project file
Files: src/datamap/datamapOperations.ts
Operations:
- Input: attribute name, type, optional comment
- For ENUMERATION: comma-separated choices
- Creates vertex and edge
- Generates unique IDs
- Saves to project file
- Rename: Changes edge name
- Edit Comment: Modifies edge comment
- Change Type: Converts vertex type (warning if has children)
- Removes edge from parent
- Recursively deletes orphaned vertices
- Updates project file
Validation:
- Name format checking
- Duplicate detection
- Type-specific validation
- Linked attributes are guarded: edit/delete commands are disabled, and
dedicated actions (
Reveal Link Owner,Remove Linked Attribute) keep shared structures safe.
Files: src/datamap/datamapValidator.ts, src/server/soarParser.ts
Strategy:
- Check if attribute exists anywhere in datamap
- Report error if not found (typo detection)
- Skip negated attributes (testing absence)
- Use full parsed range for diagnostics
Enumeration Value Validation (NEW):
- Parser extracts attribute values from patterns like
^status complete - Validator checks if values match enumeration choices in datamap
- Supports dotted attribute paths (e.g.,
^io.output-link.status complete) - Context-aware validation: Handles cases where the same attribute name appears in different contexts
- Example:
^nameon an operator vs^nameon a state may have different valid enumerations - Validator checks ALL possible enumeration contexts for the attribute
- Only reports error if the value is invalid in ALL contexts
- This prevents false positives when attribute names are reused across different vertex types
- Example:
- Navigation: Follows path through datamap from root for dotted paths
- Reports errors with all valid choices from all contexts
Examples:
# Valid - "complete" is in status enum
(state <s> ^io.output-link.status complete)
# Invalid - "finished" is not in status enum
(state <s> ^io.output-link.status finished) # Error reported
# Valid - "move" is in command enum
(state <s> ^io.output-link.command move)
# Variables are not validated (dynamic values)
(state <s> ^status <my-status>) # No error
Severity: Errors (breaks Soar import)
Integration:
- Auto-validates on file save
- Auto-validates on file open
- Manual validation command available
- Workspace-wide validation available
Output: VS Code Diagnostics displayed at exact attribute location
Files: src/layout/layoutTreeProvider.ts
Features:
- Hierarchical display of project layout
- Type-specific icons (operators, files, folders)
- Click to open files
- Shows item counts for containers
Path Resolution:
- Accumulates folder paths from root to node
- Combines:
workspaceFolder + parentPath + node.file - Correctly handles nested folders and substates
Example Path Building:
Root: folder = "BW-Hierarchical", parentPath = ""
→ children get parentPath = "BW-Hierarchical"
move-block: folder = "move-block", parentPath = "BW-Hierarchical"
→ children get parentPath = "BW-Hierarchical/move-block"
pick-up.soar: file = "pick-up.soar", parentPath = "BW-Hierarchical/move-block"
→ opens: "BW-Hierarchical/move-block/pick-up.soar"
Files: src/layout/layoutOperations.ts
Operations:
- Creates new operator node
- Generates .soar file
- Adds to parent's children
- Updates project file
- Creates HIGH_LEVEL_OPERATOR node
- Creates folder
- Creates datamap vertex for substate
- Links via
dmId - Generates boilerplate file
- Creates FILE or FOLDER node
- Creates physical file/folder
- Adds to project structure
- Updates node name
- Can rename file on disk (optional)
- Removes from parent's children
- Optionally deletes file/folder
- Cleans up datamap vertex if substate
Files: src/layout/projectSync.ts
Features:
- Scans workspace for
.soarfiles - Compares with project structure
- Returns list of untracked files
- Generates report
- Shows selection dialog for orphaned files
- Adds selected files to project
- Updates project file
- Refreshes tree view
- Excludes files in version control
- Excludes common build directories
- Checks if already in project
Registered Commands:
Datamap:
soar.loadDatamap: Load project filesoar.refreshDatamap: Reload datamapsoar.addAttribute: Add attribute to SOAR_IDsoar.addLinkedAttribute: Link an existing SOAR_ID under a new parentsoar.editAttribute: Edit attribute propertiessoar.deleteAttribute: Delete attributesoar.revealLinkedOwner: Jump to the owning vertex for a linked attributesoar.deleteLinkedAttribute: Remove a linked edge without touching the shared vertexsoar.viewDatamap: View substate datamapsoar.viewRootDatamap: Return to root datamap
Layout:
soar.refreshLayout: Reload project structuresoar.addOperator: Add operator nodesoar.addFile: Add file nodesoar.addFolder: Add folder nodesoar.renameNode: Rename nodesoar.deleteNode: Delete node
Validation:
soar.validateAgainstDatamap: Validate current filesoar.validateSelectedProjectAgainstDatamap: Validate all files in the selected project
Sync:
soar.findOrphanedFiles: Find untracked filessoar.syncProjectFiles: Import orphaned files
- Implement
TreeDataProvider<T> - Create custom
TreeItemsubclass - Use event emitter for refresh
- Set
contextValuefor conditional menus
- Register command in
extension.ts - Add to
package.jsoncommands array - Add menu item in
package.jsonmenus section - Use
whenclauses for conditional visibility
Shared state object passed through all components:
{
projectFile: string,
project: VisualSoarProject,
datamapIndex: Map<string, DMVertex>,
layoutIndex: Map<string, LayoutNode>
}- Document saved → event triggered
- Parse document →
SoarDocument - Validate →
ValidationError[] - Create diagnostics →
Diagnostic[] - Set diagnostics collection
- Register in
extension.ts:vscode.commands.registerCommand() - Add to
package.jsoncommands section - Add menu item if needed
- Implement handler function
- Create provider implementing
TreeDataProvider - Create custom
TreeItemclass - Register view in
package.jsonviews section - Create view in
extension.ts:vscode.window.createTreeView()
- Add check in
datamapValidator.ts - Return
ValidationErrorwith range - System automatically creates diagnostic
- Add capability in
soarLanguageServer.ts - Register handler:
connection.on<Feature>() - Return appropriate response type
test/
├── fixtures/ # Test data
│ ├── example.soar # Basic Soar file
│ ├── test-validation.soar # Validation test cases
├── BW-Hierarchical/ # Complex hierarchical project
└── suite/
└── extension.test.ts # Extension tests
npm test- Open
src/test/suite/extension.test.ts - Set breakpoints
- Run "Extension Tests" launch configuration
- Indices: Use
Mapfor O(1) lookups instead of array searches - Lazy Tree Items: Create on-demand, not all at once
- Debounced Validation: Avoid validating on every keystroke
- Caching: Cache parsed documents by version
Edit src/datamap/datamapValidator.ts:
severity: 'error'; // or 'warning', 'info'- Add type to
DMVertexunion invisualSoarProject.ts - Add interface for new type
- Handle in
datamapOperations.tsadd/edit - Add icon in
datamapTreeProvider.ts
- Add type to
LayoutNodeunion - Add interface for new type
- Handle in
layoutOperations.ts - Add icon in
layoutTreeProvider.ts - Add context value for menus
Edit buildDescription() method in tree provider to change how items are labeled.
"soar.trace.server": "verbose"Look for console messages:
"Loaded VisualSoar project: /path/to/project.vsa.json"
Add console.log in soarParser.getPositionInBody() to see position tracking.
Inspect projectContext.datamapIndex.size to verify vertices loaded.
- Hover Information: Show attribute info from datamap on hover
- Go to Definition: Navigate to operator/substate definitions
- Refactoring: Rename attribute across entire project
- Code Actions: Quick fixes for validation errors
- Semantic Tokens: Better syntax highlighting with LSP
- Datamap Graph View: Visual graph editor
- Import from Code: Generate datamap from existing Soar code
- Undo/Redo: For datamap operations
- Drag-and-Drop: Reorganize layout tree