| name | faber-config |
| description | Load, validate, and resolve FABER configuration and workflows with inheritance support |
| model | claude-opus-4-5 |
FABER Config Skill
Configuration is stored at: .fractary/plugins/faber/config.json
Workflow definitions may be inline or in separate files under .fractary/plugins/faber/workflows/
Workflow Inheritance: Workflows can extend other workflows via the extends field. The resolver
merges parent and child workflows, handling pre_steps, steps, and post_steps according to inheritance rules.
YOU MUST NOT:
- Modify configuration files (read-only operations)
- Make decisions about configuration values
- Cache or store configuration between invocations
load-config
Load the main FABER configuration file.
Script: ../core/scripts/config-loader.sh (for TOML) or direct JSON read
Parameters:
config_path(optional): Path to config file (default:.fractary/plugins/faber/config.json)
Returns:
{
"status": "success",
"config": {
"schema_version": "2.0",
"workflows": [...],
"integrations": {...}
}
}
Execution:
# For JSON config (v2.0)
cat .fractary/plugins/faber/config.json
# For TOML config (legacy)
../core/scripts/config-loader.sh .faber.config.toml
load-workflow
Load a specific workflow definition.
Parameters:
workflow_id: ID of the workflow to load (default: "default")config_path(optional): Path to config file
Returns:
{
"status": "success",
"workflow": {
"id": "default",
"description": "Standard FABER workflow",
"phases": {
"frame": {"enabled": true, "steps": [...]},
"architect": {"enabled": true, "steps": [...]},
"build": {"enabled": true, "steps": [...]},
"evaluate": {"enabled": true, "steps": [...], "max_retries": 3},
"release": {"enabled": true, "steps": [...]}
},
"autonomy": {"level": "guarded", "require_approval_for": ["release"]},
"hooks": {...}
}
}
Execution:
- Load main config
- Find workflow by ID in
workflowsarray - If workflow has
fileproperty, load from that file - Return merged workflow definition
resolve-workflow
Primary Operation - Load and resolve a workflow with full inheritance chain merging.
This is the main operation for getting an executable workflow. It handles:
- Namespace resolution (e.g.,
fractary-faber:default,project:my-workflow) - Inheritance chain parsing via
extendsfield - Merging pre_steps, steps, and post_steps across the inheritance hierarchy
- Applying skip_steps to exclude specific inherited steps
- Validating step ID uniqueness across the merged workflow
Parameters:
workflow_id: ID of the workflow to resolve (e.g.,"fractary-faber:default","my-workflow")config_path(optional): Path to project config file (default:.fractary/plugins/faber/config.json)
Returns:
{
"status": "success",
"workflow": {
"id": "my-workflow",
"description": "My custom workflow extending default",
"inheritance_chain": ["my-workflow", "fractary-faber:default"],
"phases": {
"frame": {
"enabled": true,
"steps": [
{"id": "fetch-or-create-issue", "source": "fractary-faber:default", "position": "pre_step"},
{"id": "switch-or-create-branch", "source": "fractary-faber:default", "position": "pre_step"},
{"id": "custom-frame-step", "source": "my-workflow", "position": "step"}
]
},
...
},
"autonomy": {...},
"skipped_steps": ["merge-pr"]
}
}
Namespace Resolution:
| Namespace | Location | Description |
|---|---|---|
fractary-faber: |
${PLUGIN_ROOT}/plugins/faber/config/workflows/ |
Core FABER workflows |
fractary-faber-cloud: |
${PLUGIN_ROOT}/plugins/faber-cloud/config/workflows/ |
Cloud infrastructure workflows |
project: |
.fractary/plugins/faber/workflows/ |
Project-specific workflows |
| (no namespace) | .fractary/plugins/faber/workflows/ |
Defaults to project: |
Plugin Root Resolution:
- Check environment variable
CLAUDE_PLUGIN_ROOTfirst (set by plugin system) - Fall back to installed location:
~/.claude/plugins/marketplaces/fractary/ - In development: Use the repository root where plugins are being developed
Execution Algorithm:
1. NAMESPACE RESOLUTION
- Parse workflow_id for namespace (split on ":")
- If no namespace, assume "project:"
- Resolve plugin root:
* If CLAUDE_PLUGIN_ROOT env var set → use that
* Else → use ~/.claude/plugins/marketplaces/fractary/
- Map namespace to file path:
* fractary-faber: → ${plugin_root}/plugins/faber/config/workflows/
* fractary-faber-cloud: → ${plugin_root}/plugins/faber-cloud/config/workflows/
* project: → .fractary/plugins/faber/workflows/ (relative to cwd)
- Load workflow JSON from resolved path
2. PARSE INHERITANCE CHAIN
chain = [current_workflow]
visited = set() # Track visited workflows to detect cycles
while current_workflow.extends:
if current_workflow.extends in visited:
ERROR: Circular inheritance detected: {cycle_path}
visited.add(current_workflow.id)
parent = resolve_namespace_and_load(current_workflow.extends)
chain.append(parent)
current_workflow = parent
# chain is now [child, parent, grandparent, ...]
3. MERGE WORKFLOWS
for each phase in [frame, architect, build, evaluate, release]:
merged_steps = []
# Pre-steps: root ancestor first, then down to child
for workflow in reversed(chain):
merged_steps.extend(workflow.phases[phase].pre_steps)
# Main steps: only from the leaf child
merged_steps.extend(chain[0].phases[phase].steps)
# Post-steps: child first, then up to root ancestor
for workflow in chain:
merged_steps.extend(workflow.phases[phase].post_steps)
merged.phases[phase].steps = merged_steps
4. APPLY SKIP_STEPS
skip_ids = chain[0].skip_steps or []
for phase in merged.phases:
merged.phases[phase].steps = [
s for s in merged.phases[phase].steps if s.id not in skip_ids
]
5. VALIDATE
all_step_ids = []
for phase in merged.phases:
for step in merged.phases[phase].steps:
if step.id in all_step_ids:
ERROR: "Duplicate step ID: {step.id}"
all_step_ids.append(step.id)
for skip_id in skip_ids:
if skip_id not in [all step IDs from ancestors]:
WARNING: "skip_steps contains unknown step ID: {skip_id}"
6. RETURN merged workflow with inheritance_chain metadata
Merge Order Visualization:
For a workflow my-workflow extends etl-common extends default:
Build Phase Execution Order:
┌─────────────────────────────────────────────────┐
│ 1. default.build.pre_steps (root first) │
│ 2. etl-common.build.pre_steps │
│ 3. my-workflow.build.pre_steps │
│ 4. my-workflow.build.steps (child only) │
│ 5. my-workflow.build.post_steps │
│ 6. etl-common.build.post_steps │
│ 7. default.build.post_steps (root last) │
└─────────────────────────────────────────────────┘
Error Handling:
WORKFLOW_NOT_FOUND: Workflow file doesn't exist at resolved pathINVALID_NAMESPACE: Unknown namespace prefixCIRCULAR_INHERITANCE: Workflow inheritance creates a cycleDUPLICATE_STEP_ID: Same step ID appears multiple times in merged workflowINVALID_SKIP_STEP: skip_steps references a step that doesn't exist in ancestors
CRITICAL - Use Deterministic Script:
The merge algorithm described above MUST be executed deterministically using the provided script. DO NOT attempt to perform the merge logic manually - this leads to incomplete merges.
Script Execution (MANDATORY for inheritance chains):
# Use this script for ALL resolve-workflow operations with inheritance
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
"${SCRIPT_DIR}/scripts/merge-workflows.sh" "$workflow_id" \
--plugin-root "${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/fractary}" \
--project-root "$(pwd)"
Post-Merge Validation (MANDATORY): After merge, ALWAYS validate the result:
"${SCRIPT_DIR}/scripts/validate-merge.sh" "$merged_workflow_json"
If validation fails with "no steps from any ancestor", the merge was incomplete. This is a FATAL error - do not proceed with workflow execution.
Why Scripts Are Required:
- LLM-based merge is non-deterministic and prone to skipping merge logic
- Issue #327 documented a case where the LLM identified the inheritance chain but did not execute the merge algorithm, resulting in empty phase steps
- The deterministic script guarantees consistent merge behavior
validate-config
Validate configuration against JSON schema.
Script: ../core/scripts/config-validate.sh
Parameters:
config_path: Path to config file to validate
Returns:
{
"status": "success",
"valid": true,
"summary": {
"schema_version": "2.0",
"workflow_count": 1,
"autonomy_level": "guarded"
}
}
Or on failure:
{
"status": "error",
"valid": false,
"errors": [
"Missing required field: integrations.work_plugin",
"Invalid autonomy level: unknown"
]
}
Execution:
../core/scripts/config-validate.sh .fractary/plugins/faber/config.json
get-phases
Extract phase definitions from a workflow.
Parameters:
workflow_id: ID of the workflow (default: "default")config_path(optional): Path to config file
Returns:
{
"status": "success",
"phases": ["frame", "architect", "build", "evaluate", "release"],
"enabled_phases": ["frame", "architect", "build", "evaluate", "release"],
"phase_config": {
"frame": {"enabled": true, "steps": [...]},
"architect": {"enabled": true, "steps": [...]},
...
}
}
Execution:
- Load workflow using
load-workflow - Extract phase names and configurations
- Filter to enabled phases
get-integrations
Get configured plugin integrations.
Parameters:
config_path(optional): Path to config file
Returns:
{
"status": "success",
"integrations": {
"work_plugin": "fractary-work",
"repo_plugin": "fractary-repo",
"spec_plugin": "fractary-spec",
"logs_plugin": "fractary-logs"
}
}
Parse Request
- Extract operation name
- Extract parameters
Execute Operation
- For
load-config: Read and parse JSON config file - For
load-workflow: Load config, find workflow, merge with file if needed - For
validate-config: Run validation script - For
get-phases: Extract phase information - For
get-integrations: Extract integrations section
- For
Return Result
- Always return structured JSON
- Include status field (success/error)
- Include operation-specific data
🎯 STARTING: FABER Config
Operation: load-config
Config Path: .fractary/plugins/faber/config.json
───────────────────────────────────────
[... execution ...]
✅ READY: FABER Config
Schema Version: 2.0
Workflows: 1
───────────────────────────────────────
→ Workflow resolved and ready for execution by faber-manager
Note: Use "READY" instead of "COMPLETED" to indicate this is a handoff to the next step, not termination of the overall workflow. The director skill will continue to invoke faber-manager.