| name | resource-management |
| description | Manage ResourceX resources, register prototypes, and load skills. Use when you need to add, search, distribute, or inspect resources in RoleX, or when you need to register a prototype or load a skill on demand. |
Feature: ResourceX Concepts
ResourceX is the resource system that powers RoleX's content management.
Resources are typed content bundles identified by tag and digest,
stored locally in a CAS (Content-Addressable Storage) or in a remote registry.
Scenario: What is a resource
Given a resource is a directory containing content and metadata
Then it has a resource.json manifest defining name, type, tag, and author
And it contains content files specific to its type (e.g. .feature files, SKILL.md)
And it is identified by a locator string
Scenario: Tag + digest model
Given ResourceX uses a tag + digest model similar to Docker
Then tag is a human-readable label — like "stable" or "0.1.0"
And tag is mutable — the same tag can point to different content over time
And digest is a sha256 content fingerprint — deterministic and immutable
And digest is computed from the archive's file-level hashes
And the format is sha256:<64-char-hex>
And content uniqueness is guaranteed by digest, not by tag
Scenario: Locator formats
Given a locator is how you reference a resource
Then it can be just a name — nuwa (tag defaults to latest)
And it can be a name with digest — name@sha256:abc123...
And it can include a path — path/name:tag (e.g. prompts/hello:stable)
And it can include a registry — registry.example.com/name:tag
And it can be a local directory path — ./path/to/resource or /absolute/path
And when tag is omitted, it defaults to latest
Scenario: Resource types in RoleX
Given RoleX registers resource types with ResourceX
Then "role" type — individual manifests with .feature files (alias: "individual")
And "organization" type — organization manifests with .feature files (alias: "org")
And "skill" type — SKILL.md files loaded via the skill process
Scenario: resource.json structure
Given every resource directory must contain a resource.json
Then the structure is:
"""
{
"name": "my-resource",
"type": "role",
"tag": "0.1.0",
"author": "deepractice",
"description": "What this resource is"
}
"""
And name is the resource identifier
And type determines how the resource is resolved (role, organization, skill)
And tag is a human-readable label, not a semantic version — omit for latest
Scenario: Storage location
Given resources are stored locally at ~/.deepractice/resourcex by default
And the location is configurable via LocalPlatform resourceDir option
And prototype registrations are stored at ~/.deepractice/rolex/prototype.json
Feature: Resource Operations
Manage resources through the use tool with !resource namespace.
Operations cover the full lifecycle: add, push, pull, search, remove.
Scenario: add — import a resource from a local directory
Given you have a resource directory with resource.json
When you call use with !resource.add
Then the resource is archived and stored in local CAS
And it gets a digest computed from its content
And it can then be pushed to a remote registry
And parameters are:
"""
locator: "!resource.add"
args:
path: "/absolute/path/to/resource"
"""
Scenario: push — publish a resource to a remote registry
Given a resource has been added to local CAS
When you call use with !resource.push
Then the resource archive is uploaded to the configured registry
And the registry stores it by name, tag, and digest
And parameters are:
"""
locator: "!resource.push"
args:
locator: "name:tag"
registry: "https://..." # optional
"""
Scenario: pull — download a resource from a remote registry
Given a resource exists in a remote registry
When you call use with !resource.pull
Then the resource is downloaded and cached in local CAS
And subsequent resolves use the local cache
And parameters are:
"""
locator: "!resource.pull"
args:
locator: "name:tag"
"""
Scenario: search — find resources in local CAS
Given you want to find resources stored locally
When you call use with !resource.search
Then matching resources are returned as locator strings
And parameters are:
"""
locator: "!resource.search"
args:
query: "keyword"
"""
Scenario: has — check if a resource exists locally
Given you want to verify a resource is in local CAS
When you call use with !resource.has
Then returns whether the resource exists
And parameters are:
"""
locator: "!resource.has"
args:
locator: "name:tag"
"""
Scenario: remove — delete a resource from local CAS
Given you want to remove a resource from local storage
When you call use with !resource.remove
Then the resource manifest is removed from local CAS
And parameters are:
"""
locator: "!resource.remove"
args:
locator: "name:tag"
"""
Scenario: Typical workflow — add then push
Given you want to publish a resource to a registry
Then the sequence is:
"""
1. locator: "!resource.add"
args: { path: "./my-resource" }
2. locator: "!resource.push"
args: { locator: "my-resource" }
"""
And add imports to local CAS, push uploads to registry
And tag defaults to latest when omitted
Feature: Resource Loading via use
Load resources on demand through the unified use entry point.
The use tool dispatches based on locator format.
Scenario: use — load a ResourceX resource
Given you need to load or execute a resource
When you call use with a regular locator (no ! prefix)
Then the resource is resolved through ResourceX and its content returned
And parameters are:
"""
locator: "hello-prompt" # by registry locator (tag defaults to latest)
locator: "./path/to/resource" # by local path
"""
Scenario: skill — load full skill content by locator
Given a role has a procedure referencing a skill via locator
When you need the detailed instructions beyond the procedure summary
Then call skill with the locator from the procedure's Feature description
And the full SKILL.md content is returned with metadata header
And this is progressive disclosure layer 2 — on-demand knowledge injection
And parameters are:
"""
skill locator: "skill-creator" # tag defaults to latest
skill locator: "/absolute/path/to/skill-directory"
"""
Scenario: Progressive disclosure — three layers
Given RoleX uses progressive disclosure to manage context
Then layer 1 — procedure: metadata loaded at activate time (role knows what skills exist)
And layer 2 — skill: full instructions loaded on demand via skill(locator)
And layer 3 — use: execution of external resources via use(locator)
And each layer adds detail only when needed, keeping context lean
Feature: Prototype Registration
Register a ResourceX source as a role or organization prototype.
Prototypes provide inherited state that merges with an individual's instance state on activation.
Scenario: What is a prototype
Given an individual's state has two origins — prototype and instance
Then prototype state comes from organizational definitions (read-only)
And instance state is created by the individual through execution (mutable)
And on activation, both are merged into a virtual combined state
Scenario: Prototype resource structure for a role
Given a role prototype is a directory with:
"""
/
├── resource.json (type: "role")
├── individual.json (manifest with id, type, children tree)
├── .individual.feature (persona Gherkin)
└── ..feature (identity, background, duty, etc.)
"""
And individual.json defines the tree structure:
"""
{
"id": "nuwa",
"type": "individual",
"alias": ["nvwa"],
"children": {
"identity": {
"type": "identity",
"children": {
"background": { "type": "background" }
}
}
}
}
"""
Scenario: Prototype updates
Given you re-register a prototype with the same id
Then the source is overwritten — latest registration wins
And the next activation will load the updated prototype
Feature: Common Workflows
Typical sequences of operations for resource management.
Scenario: Publish a prototype to registry
Given you have a prototype directory ready
When you want to make it available via registry
Then the sequence is:
"""
1. locator: "!resource.add"
args: { path: "/path/to/roles/nuwa" }
2. locator: "!resource.push"
args: { locator: "nuwa" }
"""
And the prototype is now pullable by anyone with registry access
Scenario: Update and re-push a prototype
Given the prototype content has changed
When you re-add and push with the same tag
Then the registry updates the tag to point to the new digest
"""
1. locator: "!resource.add"
args: { path: "/path/to/roles/nuwa" }
2. locator: "!resource.push"
args: { locator: "nuwa" }
"""
And consumers pulling the same tag get the updated content
Scenario: Test loading a skill
Given you want to verify a skill is accessible
When you call skill with the locator
Then the full SKILL.md content should be returned
And example:
"""
skill locator: "skill-creator"
"""