Block Schema Reference
Block v2 — Universal execution unit for the Process Factory Engine
1. Block v2 JSON Schema (Formal Definition)
The Block v2 is the universal execution unit. Every skill in the pipeline is wrapped in a Block that declares its dependencies, outputs, execution constraints, and lifecycle. The schema below is the complete formal definition.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Block v2",
"description": "Universal execution unit for the Process Factory Engine",
"type": "object",
"required": ["id", "name", "layer", "type", "skill", "trigger", "inputs", "outputs", "execution", "lifecycle"],
"properties": {
"id": {
"type": "string",
"description": "Unique block identifier, typically matches skill name"
},
"name": {
"type": "string",
"description": "Human-readable display name"
},
"layer": {
"type": "string",
"enum": ["L0", "L0.25", "L0.5", "L1", "L2", "L2.5", "L3", "L3.5", "L4"],
"description": "Execution layer in the pipeline"
},
"type": {
"type": "string",
"enum": ["extract", "validate", "build", "orchestrate", "research", "ingest"],
"description": "Block functional category"
},
"skill": {
"type": "string",
"description": "Maps to SKILL.md file in skills directory"
},
"model": {
"type": ["string", "null"],
"enum": ["opus", "sonnet", null],
"description": "Model override, null inherits from run config"
},
"timeout": {
"type": "number",
"default": 300000,
"description": "Execution timeout in milliseconds"
},
"runtime": {
"type": "string",
"enum": ["forge", "claude-cli", "mastery-api", "nowpage"],
"description": "Execution runtime environment"
},
"trigger": {
"type": "object",
"required": ["type"],
"properties": {
"type": { "type": "string", "enum": ["dependency", "cron", "webhook", "event", "manual"] },
"cron": { "type": ["string", "null"] },
"event": { "type": ["string", "null"] },
"webhook": { "type": ["string", "null"] }
}
},
"inputs": {
"type": "object",
"properties": {
"depends": {
"type": "array",
"items": {
"type": "object",
"properties": {
"block": { "type": "string" },
"key": { "type": "string" }
}
}
},
"files": { "type": "array", "items": { "type": "string" } },
"env": { "type": "array", "items": { "type": "string" } },
"config": { "type": "object" }
}
},
"outputs": {
"type": "object",
"properties": {
"artifacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": { "type": "string" },
"path": { "type": "string" },
"format": { "type": "string" }
}
}
},
"metrics": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": { "type": "string" },
"type": { "type": "string" }
}
}
},
"publish": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"domain": { "type": "string" },
"slug": { "type": "string" }
}
}
}
}
},
"execution": {
"type": "object",
"properties": {
"parallel_group": { "type": ["string", "null"] },
"human_gate": {
"type": "string",
"enum": ["before", "after", "none"],
"default": "none"
},
"threshold": {
"type": ["object", "null"],
"properties": {
"metric": { "type": "string" },
"min": { "type": "number" }
}
},
"retryable": { "type": "boolean", "default": true },
"max_retries": { "type": "number", "default": 2 }
}
},
"lifecycle": {
"type": "object",
"required": ["mode"],
"properties": {
"mode": {
"type": "string",
"enum": ["one-shot", "daemon", "on-demand"]
}
}
},
"scope": {
"type": "object",
"properties": {
"gate": { "type": ["number", "null"], "enum": [1, 2, 3, 4, null] },
"run_params": { "type": "object" }
}
},
"lens": {
"type": "object",
"properties": {
"perspective": { "type": ["string", "null"] },
"aggregates": { "type": ["array", "null"], "items": { "type": "string" } },
"feedback_loop": { "type": "boolean", "default": false }
}
},
"record_state": {
"type": "object",
"properties": {
"track_per": { "type": ["string", "null"] },
"states": { "type": "array", "items": { "type": "string" } }
}
},
"state": {
"type": "object",
"description": "Runtime state managed by engine, not set in config",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "ready", "running", "done", "failed", "blocked", "waiting"],
"default": "pending"
},
"started_at": { "type": ["string", "null"], "format": "date-time" },
"ended_at": { "type": ["string", "null"], "format": "date-time" },
"score": { "type": ["number", "null"] },
"error": { "type": ["string", "null"] },
"attempts": { "type": "number", "default": 0 }
}
}
}
}
A block must include: id, name, layer, type, skill, trigger, inputs, outputs, execution, and lifecycle. All other top-level properties are optional and default to null/empty.
The state property is managed entirely by the engine at runtime. Never set it in block config files. The engine initializes all blocks with status: "pending" at run start.
2. Example Blocks
Four complete blocks demonstrating different patterns: root-level research, framework extraction with human gate, parallel extraction, and validation with thresholds.
Example 1: deep-research (L0, research, parallel group)
{
"id": "deep-research",
"name": "Deep Research",
"layer": "L0",
"type": "research",
"skill": "deep-research",
"model": "opus",
"timeout": 600000,
"runtime": "claude-cli",
"trigger": { "type": "dependency" },
"inputs": {
"depends": [],
"files": [],
"env": ["PPLX_API_KEY"],
"config": { "expert_name": "{{expert_name}}" }
},
"outputs": {
"artifacts": [
{ "key": "intel-report", "path": "{{workspace}}/sources/intel-report.md", "format": "markdown" },
{ "key": "raw-sources", "path": "{{workspace}}/sources/raw-sources/", "format": "directory" }
],
"metrics": [{ "key": "source_count", "type": "number" }],
"publish": [{ "domain": "align360.asapai.net", "slug": "{{expert_slug}}-intel" }]
},
"execution": {
"parallel_group": "L0-recon",
"human_gate": "none",
"threshold": null,
"retryable": true,
"max_retries": 2
},
"lifecycle": { "mode": "one-shot" },
"scope": { "gate": null, "run_params": {} },
"lens": { "perspective": null, "aggregates": null, "feedback_loop": false },
"record_state": { "track_per": null, "states": [] }
}
Example 2: expert-framework-creator (L0.25, extract, human gate)
human_gate: "after" so an approver must sign off on the extracted framework before downstream blocks proceed. Uses 3-path convergence (high cost, high quality).{
"id": "expert-framework-creator",
"name": "Expert Framework Creator",
"layer": "L0.25",
"type": "extract",
"skill": "expert-framework-creator",
"model": "opus",
"timeout": 900000,
"runtime": "claude-cli",
"trigger": { "type": "dependency" },
"inputs": {
"depends": [
{ "block": "deep-research", "key": "raw-sources" },
{ "block": "expert-recon", "key": "recon-summary" }
],
"files": ["{{workspace}}/sources/**/*"],
"env": [],
"config": {}
},
"outputs": {
"artifacts": [{ "key": "expert-framework", "path": "{{workspace}}/expert-framework.json", "format": "json" }],
"metrics": [
{ "key": "convergence_score", "type": "number" },
{ "key": "evidence_count", "type": "number" }
],
"publish": null
},
"execution": {
"parallel_group": null,
"human_gate": "after",
"threshold": null,
"retryable": true,
"max_retries": 1
},
"lifecycle": { "mode": "one-shot" },
"scope": { "gate": null, "run_params": {} },
"lens": { "perspective": null, "aggregates": null, "feedback_loop": false },
"record_state": { "track_per": null, "states": [] }
}
Example 3: soul-extractor (L2, extract, parallel group)
null (inherits from factory config). Depends on L0.25 framework output and L0 raw sources.{
"id": "soul-extractor",
"name": "Soul Extractor",
"layer": "L2",
"type": "extract",
"skill": "soul-extractor",
"model": null,
"timeout": 600000,
"runtime": "claude-cli",
"trigger": { "type": "dependency" },
"inputs": {
"depends": [
{ "block": "expert-framework-creator", "key": "expert-framework" },
{ "block": "deep-research", "key": "raw-sources" }
],
"files": ["{{workspace}}/sources/**/*"],
"env": [],
"config": {}
},
"outputs": {
"artifacts": [{ "key": "soul", "path": "{{workspace}}/soul.json", "format": "json" }],
"metrics": [{ "key": "extraction_completeness", "type": "percentage" }],
"publish": null
},
"execution": {
"parallel_group": "L2-extractors",
"human_gate": "none",
"threshold": null,
"retryable": true,
"max_retries": 2
},
"lifecycle": { "mode": "one-shot" },
"scope": { "gate": null, "run_params": {} },
"lens": { "perspective": null, "aggregates": null, "feedback_loop": false },
"record_state": { "track_per": null, "states": [] }
}
Example 4: clone-tester (L3.5, validate, threshold + human gate)
overall_score >= 85) and a human gate after. If the score is below 85, it auto-retries up to 2 times. After passing threshold, it still requires human approval before the pipeline can finalize. This is the quality checkpoint that gates deployment.{
"id": "clone-tester",
"name": "Clone Tester",
"layer": "L3.5",
"type": "validate",
"skill": "clone-tester",
"model": "opus",
"timeout": 1200000,
"runtime": "claude-cli",
"trigger": { "type": "dependency" },
"inputs": {
"depends": [
{ "block": "clone-compiler", "key": "system-prompt" },
{ "block": "clone-compiler", "key": "knowledge-files" },
{ "block": "clone-compiler", "key": "tool-configs" },
{ "block": "expert-framework-creator", "key": "expert-framework" }
],
"files": ["{{workspace}}/artifacts/**/*"],
"env": [],
"config": {}
},
"outputs": {
"artifacts": [
{ "key": "test-results", "path": "{{workspace}}/test-results/test-results.json", "format": "json" },
{ "key": "audit-sheet", "path": "{{workspace}}/test-results/audit-sheet.md", "format": "markdown" },
{ "key": "simulation-log", "path": "{{workspace}}/test-results/simulation-log.json", "format": "json" }
],
"metrics": [
{ "key": "overall_score", "type": "percentage" },
{ "key": "governance_violations", "type": "number" }
],
"publish": [{ "domain": "align360.asapai.net", "slug": "{{expert_slug}}-test-results" }]
},
"execution": {
"parallel_group": null,
"human_gate": "after",
"threshold": { "metric": "overall_score", "min": 85 },
"retryable": true,
"max_retries": 2
},
"lifecycle": { "mode": "one-shot" },
"scope": { "gate": null, "run_params": {} },
"lens": { "perspective": null, "aggregates": null, "feedback_loop": false },
"record_state": { "track_per": null, "states": [] }
}
3. Factory Template JSON Structure
A factory template wraps the 18 blocks with shared configuration, parallel group definitions, human gate assignments, threshold rules, and a module mapping that connects extraction outputs to the 9-module knowledge taxonomy.
{
"factory": {
"id": "clone-factory",
"name": "Clone Factory",
"version": "1.0.0",
"pattern": "dag-batch",
"description": "18-skill recursive expert clone pipeline"
},
"config": {
"expert_name": "{{expert_name}}",
"expert_slug": "{{expert_slug}}",
"workspace": "{{workspace_path}}",
"publish_domain": "{{publish_domain}}",
"model_default": "opus"
},
"blocks": [ // ...18 block definitions (see Section 2 for examples) ],
"parallel_groups": {
"L0-recon": ["deep-research", "expert-recon", "masterybook-sync"],
"L2-extractors": ["soul-extractor", "voice-extractor", "framework-extractor", "resource-extractor", "offer-extractor"],
"L3-builders": ["clone-compiler", "lead-magnet-builder", "onboarding-builder"]
},
"human_gates": [
{ "after_block": "expert-framework-creator", "approvers": ["expert", "product_lead"] },
{ "after_block": "gap-analyzer", "approvers": ["product_lead"] },
{ "after_block": "clone-tester", "approvers": ["expert", "product_lead", "tech_lead"] }
],
"thresholds": [
{ "block": "clone-tester", "metric": "overall_score", "min": 85, "action": "fail" }
],
"module_mapping": {
"M1_thinking_structures": ["expert-framework-creator", "soul-extractor"],
"M2_voice_style": ["voice-extractor"],
"M3_cta_psychology": ["offer-extractor"],
"M4_embedded_ip": ["framework-extractor"],
"M5_modularization": ["framework-extractor"],
"M6_meta_structures": ["framework-extractor"],
"M7_pattern_recognition": ["soul-extractor"],
"M8_prompt_templates": ["clone-compiler"],
"M9_retrieval_patterns": ["clone-compiler"]
}
}
All {{double_brace}} values are resolved at run-time by the orchestrator. The factory template is static; the orchestrator instantiates it with concrete values for each expert run.
4. Readiness Signal Algorithm
The DAG scheduler continuously evaluates block readiness. A block transitions from pending to ready only when all preconditions are met: dependencies complete, outputs available, human gates cleared, and parallel group capacity allows.
evaluateReadiness(block, run_state)
function evaluateReadiness(block, run_state):
// 1. Check if block is already done or running
if block.state.status in ['done', 'running', 'failed']:
return block.state.status
// 2. Check all dependencies
for dep in block.inputs.depends:
dep_block = run_state.blocks[dep.block]
if dep_block.state.status != 'done':
return 'blocked'
if dep_block.outputs[dep.key] is missing:
return 'blocked'
// 3. Check human gate (before type)
if block.execution.human_gate == 'before':
if not run_state.gates[block.id].approved:
return 'waiting'
// 4. Check parallel group capacity
if block.execution.parallel_group:
running_in_group = count(b for b in run_state.blocks
if b.execution.parallel_group == block.execution.parallel_group
and b.state.status == 'running')
if running_in_group >= MAX_PARALLEL:
return 'pending'
// 5. All checks pass
return 'ready'
handleBlockCompletion(block_id, result, run_state)
function handleBlockCompletion(block_id, result, run_state):
block = run_state.blocks[block_id]
// 1. Update block state
block.state.status = result.success ? 'done' : 'failed'
block.state.ended_at = now()
block.state.score = result.score
// 2. Check threshold
if block.execution.threshold:
if result.score < block.execution.threshold.min:
if block.state.attempts < block.execution.max_retries:
block.state.status = 'pending'
block.state.attempts += 1
return { action: 'retry' }
else:
block.state.status = 'failed'
return { action: 'failed', reason: 'threshold_not_met' }
// 3. Check human gate (after type)
if block.execution.human_gate == 'after':
block.state.status = 'waiting'
return { action: 'await_approval', gate: block.id }
// 4. Evaluate downstream blocks
for downstream in findDependents(block_id, run_state):
downstream.state.status = evaluateReadiness(downstream, run_state)
return { action: 'continue' }
The scheduler runs evaluateReadiness on all pending/blocked blocks after every state change. This ensures cascading readiness propagation: when an L0 block completes, L0.25 immediately re-evaluates, and so on down the DAG.
5. State Machine Diagram
Every block has a state.status field managed by the engine. The following diagram shows all valid states and transitions.
| From | To | Condition | |
|---|---|---|---|
| pending | → | ready | All dependencies met, no blocking gate |
| pending | → | blocked | One or more dependencies not done |
| blocked | → | ready | All dependencies resolved |
| blocked | → | pending | Partial dependencies resolved (re-queue) |
| ready | → | running | Scheduler picks up block for execution |
| running | → | done | Execution succeeds, threshold met (or no threshold) |
| running | → | failed | Execution error or timeout |
| done | → | waiting | Block has human_gate: "after" |
| waiting | → | done | Human gate approved |
| waiting | → | pending | Human gate rejected (retry) |
| failed | → | pending | Retryable and attempts < max_retries |
6. Parallel Group Semantics
Parallel groups allow multiple blocks to execute concurrently when their individual dependencies are satisfied. This is the primary mechanism for reducing wall-clock time in the pipeline.
How It Works
- Simultaneous readiness: All blocks in a parallel group become
readyat the same time once their respective dependencies are met. The group name is a coordination label, not a dependency. - Concurrent launch: The scheduler launches all ready blocks in the group simultaneously. Each block executes independently.
- Group completion: The group is considered "complete" when ALL blocks in the group reach
donestatus. Partial completion is tracked for progress display. - Independent failure: If one block in the group fails, the other blocks continue executing. A failed block in a group does not halt sibling blocks, only downstream blocks that depend on the failed block's output.
- Progress tracking: The parallel group name is used for progress display:
"L2-extractors: 3/5 done" - Concurrency limits: Maximum concurrent blocks per group can be configured (default: unlimited). Useful for resource-constrained environments.
Defined Parallel Groups
deep-research + expert-recon + masterybook-sync — All root nodes with zero dependencies. Fire simultaneously at run start.
soul-extractor + voice-extractor + framework-extractor + resource-extractor + offer-extractor — All depend on L0.25 framework. Fire simultaneously after framework is approved. Saves ~60% wall-clock time vs sequential.
clone-compiler + lead-magnet-builder + onboarding-builder — All depend on L2 extraction outputs. Fire simultaneously after gap analysis is approved.
Concurrency Configuration
{
"parallel_groups": {
"L0-recon": {
"blocks": ["deep-research", "expert-recon", "masterybook-sync"],
"max_concurrent": 3 // default: unlimited
},
"L2-extractors": {
"blocks": ["soul-extractor", "voice-extractor", "framework-extractor", "resource-extractor", "offer-extractor"],
"max_concurrent": 3 // limit to 3 to reduce API pressure
}
}
}
7. Human Gate Protocol
Human gates are synchronization points where the pipeline pauses for human review and approval. They ensure that critical outputs are validated before downstream blocks consume them.
Gate Flow
- Block completes execution (status transitions to
done) - If
human_gate == "after": status transitions towaiting - Dashboard surfaces the approval UI with the block's output artifacts
- Designated approver reviews outputs
- Approve: Block status transitions to
done; downstream blocks are re-evaluated for readiness - Reject: Block status transitions to
pending(auto-retry) orfailed(abort), depending on retry budget - Reject with feedback: Feedback is stored in
run_state.gates[block_id].feedbackand passed to the skill on retry - Approver roles are configurable per gate:
expert,product_lead,tech_lead
Gate Configuration in Factory Template
"human_gates": [
{
"after_block": "expert-framework-creator",
"approvers": ["expert", "product_lead"],
"timeout_hours": 48,
"auto_approve_on_timeout": false
},
{
"after_block": "gap-analyzer",
"approvers": ["product_lead"],
"timeout_hours": 24,
"auto_approve_on_timeout": false
},
{
"after_block": "clone-tester",
"approvers": ["expert", "product_lead", "tech_lead"],
"timeout_hours": 72,
"auto_approve_on_timeout": false
}
]
API Endpoints
{
"approver": "will@align360.io",
"role": "product_lead",
"notes": "Framework looks solid. FORGE dimensions validated against source material."
}
{
"approver": "samuel@flc.com",
"role": "expert",
"action": "retry",
"feedback": "Missing the 'Hat Debate' pattern. Re-run with emphasis on Phase 3 deliberation structures."
}
If no approver acts within the configured timeout_hours, the gate does NOT auto-approve (by default). The pipeline stays paused. Set auto_approve_on_timeout: true only for non-critical gates in automated environments.
8. Threshold / Retry Logic
Thresholds enforce minimum quality standards. When a block reports a score metric, the engine compares it against the configured minimum. Below-threshold results trigger automatic retries up to the configured limit.
Threshold Evaluation Flow
- Block completes with a score metric (e.g.,
overall_score: 82) - Engine checks:
score >= threshold.min? - Yes: Proceed to human gate (if configured) or mark
done - No, attempts < max_retries: Status transitions to
pending(auto-retry). Attempt counter increments. - No, attempts >= max_retries: Status transitions to
failed - A failed threshold block prevents all downstream blocks from becoming
ready - Human override: A human gate approver can override a below-threshold failure with justification
Example: clone-tester Threshold Scenario
metric: overall_score | min: 85 | max_retries: 2
| Attempt | Score | Result | Next Status |
|---|---|---|---|
| 1 | 82% | Below threshold | pending (auto-retry) |
| 2 | 84% | Below threshold | pending (auto-retry) |
| 3 | 83% | Below threshold, max retries exhausted | failed |
At this point, a human approver can still override:
// POST /api/a360/factory-run/{run_id}/gate/clone-tester/approve
{
"approver": "jason@athio.ai",
"role": "tech_lead",
"override": true,
"justification": "Alpha quality acceptable at 83%. Known gap is CTA psychology (Module 3). Ship and fix in next iteration."
}
Threshold Configuration in Factory Template
"thresholds": [
{
"block": "clone-tester",
"metric": "overall_score",
"min": 85,
"action": "fail", // "fail" = block downstream, "warn" = log only
"override_allowed": true // can a human override?
}
]
On retry, the engine passes the previous attempt's score and any human feedback to the skill. This allows the skill to adjust its approach. For example, the clone-tester can focus on the weakest dimensions from the prior attempt.