Skill: wang-erqian/critic-agent (version 1.0.0)

# Critic Agent Skill A specialized agent that reviews, critiques, and scores the outputs of other agents using a structured rubric. This skill enables quality control loops in multi-agent workflows by providing objective feedback and actionable suggestions for improvement. ## Description The Critic Agent acts as an independent reviewer that evaluates agent outputs against four dimensions: - **Correctness (40%)**: Factual accuracy, logical soundness, absence of errors - **Clarity (25%)**: Readability, organization, communication effectiveness - **Completeness (25%)**: Coverage of requirements, edge cases, thoroughness - **Safety (10%)**: Ethical considerations, potential harms, compliance with guidelines The critic generates a numeric score (0-100) and provides detailed, actionable feedback for each dimension. This enables: - Quality gates before final delivery - Iterative improvement loops - Consistent evaluation standards across team outputs ## Usage ### Basic Invocation ```bash openclaw skills run critic-agent \ --task "Write a Python function to parse CSV files" \ --agent-output "def parse_csv(path): ..." \ --context '{"requirements": ["handle edge cases", "include docstring"]}' ``` ### In Agent Workflow When building multi-agent systems, integrate the critic as a validation step: ```yaml workflow: - agent: writer task: generate_initial_draft - agent: critic task: review_output inputs: task: "{{writer.task}}" agentOutput: "{{writer.result}}" context: "{{writer.context}}" - if: "critic.score >= 70" then: deliver else: retry ``` ## Input Schema ```json { "type": "object", "required": ["task", "agentOutput"], "properties": { "task": { "type": "string", "description": "The original task or prompt given to the agent being reviewed" }, "agentOutput": { "type": "string", "description": "The output to critique (code, text, analysis, etc.)" }, "context": { "type": "object", "description": "Additional context including requirements, constraints, success criteria", "properties": { "requirements": { "type": "array", "items": { "type": "string" } }, "successCriteria": { "type": "array", "items": { "type": "string" } }, "constraints": { "type": "array", "items": { "type": "string" } } } } } } ``` ## Output Schema ```json { "type": "object", "required": ["score", "feedback", "overall", "suggestions"], "properties": { "score": { "type": "number", "minimum": 0, "maximum": 100, "description": "Overall weighted score" }, "feedback": { "type": "object", "properties": { "correctness": { "type": "string", "description": "Feedback on factual/technical accuracy (40% weight)" }, "clarity": { "type": "string", "description": "Feedback on readability and organization (25% weight)" }, "completeness": { "type": "string", "description": "Feedback on coverage and thoroughness (25% weight)" }, "safety": { "type": "string", "description": "Feedback on ethical and safety considerations (10% weight)" } }, "required": ["correctness", "clarity", "completeness", "safety"] }, "overall": { "type": "string", "description": "Summarized overall assessment (1-2 sentences)" }, "suggestions": { "type": "array", "items": { "type": "string" }, "description": "Actionable improvement suggestions" }, "dimensionScores": { "type": "object", "properties": { "correctness": { "type": "number", "minimum": 0, "maximum": 100 }, "clarity": { "type": "number", "minimum": 0, "maximum": 100 }, "completeness": { "type": "number", "minimum": 0, "maximum": 100 }, "safety": { "type": "number", "minimum": 0, "maximum": 100 } } } } } ``` ## Scoring Rubric ### Overall Score Calculation ``` Overall = (Correctness × 0.40) + (Clarity × 0.25) + (Completeness × 0.25) + (Safety × 0.10) ``` ### Dimension Definitions **Correctness (40%)** - Does the output contain factual errors? - Is the logic/implementation sound? - Are technical claims accurate? - Do code examples actually work? - Are sources/references reliable? **Clarity (25%)** - Is the language clear and unambiguous? - Is the structure logical and easy to follow? - Are key points emphasized appropriately? - Is formatting used effectively? - Would the intended audience understand it? **Completeness (25%)** - Are all requirements addressed? - Are edge cases considered? - Are necessary details provided? - Is there missing context that should be included? - Does it cover the scope fully? **Safety (10%)** - Does it promote harmful behavior? - Are biases acknowledged and mitigated? - Does it comply with ethical guidelines? - Could it be misused maliciously? - Are security/privacy concerns addressed? ### Score Thresholds - **80-100**: Excellent - ready for delivery - **70-79**: Good - minor revisions suggested - **50-69**: Needs Revision - significant issues to address - **0-49**: Fail - major problems, reject and redo ## Configuration When invoking the critic, you can override defaults: ```bash openclaw skills run critic-agent \ --config '{"model": "openrouter/anthropic/claude-3.5-sonnet", "thresholds": {"pass": 80}}' ``` ### Configuration Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `model` | string | configured default | Model to use for critique | | `thresholds.pass` | number | 70 | Minimum score to pass validation | | `thresholds.needsRevision` | number | 50 | Minimum score to avoid auto-retry | | `autoRetry` | boolean | false | Automatically trigger retry if below threshold | | `maxRetries` | number | 3 | Maximum retry attempts when autoRetry enabled | ## Example Prompts for Critic Agent ### Prompt Template The critic agent receives a system prompt that defines its evaluation framework: ``` You are a Critic Agent responsible for evaluating the quality of outputs from other AI agents. Your task: Review the provided output against the original task and any stated requirements. Evaluation Dimensions: 1. Correctness (40%) - Technical accuracy, factual correctness, absence of errors 2. Clarity (25%) - Readability, logical structure, effective communication 3. Completeness (25%) - Coverage of requirements, edge cases, thoroughness 4. Safety (10%) - Ethical compliance, bias awareness, security considerations For each dimension, provide: - A score from 0-100 - Specific feedback explaining the score - Concrete suggestions for improvement Calculate the overall score: (correctness * 0.40) + (clarity * 0.25) + (completeness * 0.25) + (safety * 0.10) Respond in exact JSON format: { "score": 85, "feedback": { "correctness": "The implementation correctly handles the basic case but misses edge case X...", "clarity": "Well-structured but variable names could be more descriptive...", "completeness": "Covers requirements A and B but ignores requirement C...", "safety": "No safety concerns identified..." }, "overall": "Good effort with one critical edge case to fix.", "suggestions": ["Add input validation for empty strings", "Include error handling"] } ``` ### Task-Specific Prompts Customize the critic based on the output type: **For code reviews:** ``` Focus on: correctness, edge cases, error handling, code quality, security vulnerabilities. ``` **For written content:** ``` Focus on: argument coherence, evidence support, audience appropriateness, factual claims. ``` **For data analysis:** ``` Focus on: methodology soundness, statistical validity, conclusion support, bias detection. ``` ## Implementation ### Scripts **scripts/critic.js** - Main critic implementation that: - Accepts input JSON via stdin - Constructs appropriate critique prompt - Calls LLM with structured output enforcement - Validates and normalizes output - Returns JSON result **scripts/score-helper.js** - Utility for computing final score and thresholds ### References - `references/patterns.md` - Usage patterns and examples - `references/configuration.md` - Full configuration reference ## Integration Guide ### Single Critic Call ```javascript const result = await skill.run('critic-agent', { task: originalPrompt, agentOutput: generatedContent, context: { requirements: [...], constraints: [...] } }); if (result.score >= 70) { console.log('Passed:', result.overall); } else { console.log('Needs work:', result.suggestions); } ``` ### Retry Loop with Critic ```javascript async function generateWithQualityGate(task, maxAttempts = 3) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { const output = await generateAgentResponse(task); const critique = await skill.run('critic-agent', { task, agentOutput: output, context: {} }); if (critique.score >= 70) { return { output, critique }; } if (attempt === maxAttempts) break; // Incorporate feedback in next attempt task = `${task}\n\nPrevious feedback: ${critique.suggestions.join('; ')}`; } throw new Error('Failed to meet quality threshold after retries'); } ``` ### Parallel Critic Multi-Agent Workflow ``` Writer Agent → [Output] → Critic Agent → [Score + Feedback] ↓ If score < threshold ↓ Reject + Send feedback to Writer ↓ Writer revises and resubmits ``` ## Fallback Behavior If the critic agent fails (model unavailable, timeout, malformed response), the behavior depends on configuration: | Scenario | Default Behavior | Config Override | |----------|------------------|-----------------| | LLM API failure | Pass through original output with warning log | `onCriticError: "fail"` to reject | | Invalid JSON response | Use heuristic fallback scoring (simple keyword checks) | `onCriticError: "reject"` | | Timeout | Treat as score = 0 (fail) | `onCriticError: "pass"` to auto-pass | | Model not found | Fallback to configured default model | N/A (auto-handled) | Configure fallback: ```json { "onCriticError": "pass" | "fail" | "reject", "fallbackModel": "openrouter/default-fallback" } ``` ## Limitations - Critique quality depends on the underlying LLM's capability - Subjective dimensions (clarity) may vary between runs - Not suitable for real-time or streaming evaluation (requires complete output) - Cannot guarantee perfect detection of all safety issues - Scoring is indicative, not absolute truth ## Best Practices 1. **Use as advisory**: Critic suggestions should inform but not replace human judgment 2. **Calibrate thresholds**: Adjust pass thresholds based on your quality requirements 3. **Review borderline cases**: Scores 65-75 deserve human spot-check 4. **Log all critiques**: Record feedback for continuous improvement 5. **Iterate on prompts**: Customize critic prompts for your specific domain 6. **Combine multiple critics**: For high-stakes outputs, use 2-3 different critic models ## Future Enhancements - Multi-critic consensus (aggregate scores from multiple models) - Domain-specific rubrics (customize weights per task type) - Historical learning (store critiques to identify recurring issues) - Interactive critique (allow back-and-forth between writer and critic) - Automated remediation (auto-apply simple fixes from suggestions) ## Troubleshooting **Critic returns low scores on everything** - Check if requirements are clearly stated in context - Verify prompt template matches your output type - Try a more capable model **Scores inconsistent across runs** - Temperature may be too high; set to 0 for deterministic evaluation - Add specific examples in the system prompt to anchor scoring **Critic hangs or times out** - Increase timeout setting - Simplify lengthy outputs (critique focuses on key sections) - Use smaller, faster model for feedback generation

path: _meta.json
content: slug: critic-agent
version: 1.0.0

path: references/configuration.md
content: ## Critic Agent Configuration Reference

### Skill Metadata
- **Skill Slug**: `critic-agent`
- **Version**: 1.0.0
- **Location**: `skills/critic-agent/`

### Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Full documentation |
| `_meta.json` | Skill metadata (version, slug) |
| `scripts/compute-score.js` | Compute weighted score from dimension scores |
| `scripts/critic-system-prompt.txt` | System prompt template for critic agent |
| `scripts/test-critic.sh` | Test scenario demonstration |
| `references/patterns.md` | Integration patterns and best practices |

### Configuration Options

When invoking critic (in agent code or workflow):

```json
{
  "critic": {
    "enabled": true,
    "model": "openrouter/anthropic/claude-3.5-sonnet",
    "thresholds": {
      "pass": 70,
      "needsRevision": 50,
      "fail": 0
    },
    "autoRetry": false,
    "maxRetries": 3,
    "onCriticError": "pass"
  }
}
```

#### Parameter Details

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `enabled` | boolean | true | Master switch to enable/disable critic integration |
| `model` | string | agent's default | Model ID to use for critique (overrides default) |
| `thresholds.pass` | number | 70 | Minimum score to auto-approve delivery |
| `thresholds.needsRevision` | number | 50 | Minimum score to trigger auto-retry (if enabled) |
| `autoRetry` | boolean | false | If true, automatically regenerate when below `pass` |
| `maxRetries` | number | 3 | Maximum retry attempts before giving up |
| `onCriticError` | string | "pass" | Behavior on critic failure: `"pass"` (deliver anyway), `"reject"` (treat as fail), `"fail-safe"` (use heuristic fallback) |
| `temperature` | number | 0 | Temperature for critic model (0 recommended for deterministic scoring) |
| `timeout` | number | 30 | Timeout in seconds for critic API call |

### Input Schema (for script invocation)

When calling `compute-score.js` or spawning a critic:

```json
{
  "task": "string (the original prompt/task)",
  "agentOutput": "string (the content to critique)",
  "context": {
    "requirements": ["array of strings"],
    "constraints": ["array of strings"],
    "successCriteria": ["array of strings"]
  }
}
```

### Output Schema

Critic agent response (JSON):

```json
{
  "score": 85.5,
  "feedback": {
    "correctness": "...",
    "clarity": "...",
    "completeness": "...",
    "safety": "..."
  },
  "overall": "...",
  "suggestions": ["...", "..."],
  "dimensionScores": {
    "correctness": 85,
    "clarity": 80,
    "completeness": 70,
    "safety": 90
  }
}
```

### Using compute-score.js

```bash
# Input: JSON with dimension scores
echo '{"correctness":85,"clarity":80,"completeness":70,"safety":90}' | \
  node skills/critic-agent/scripts/compute-score.js

# Output:
# {
#   "score": 81.5,
#   "verdict": "good",
#   "breakdown": { ... }
# }
```

### Integration with AGENTS.md

Add rule to AGENTS.md:

```
## Critic Agent Integration

Before delivering final outputs:
1. Call critic using: openclaw agent --local -m "$(cat skills/critic-agent/scripts/critic-system-prompt.txt | template ...)" --json > critique.json
2. Parse score: SCORE=$(jq -r .score critique.json)
3. If SCORE >= 70: proceed
   Else if SCORE >= 50: auto-revise (max 2 retries)
   Else: reject and restart
4. Log all critiques to memory/critic-log.json
```

### Environment Variables

| Variable | Purpose |
|----------|---------|
| `OPENROUTER_API_KEY` | API key for LLM provider (required for --local agent calls) |
| `CRITIC_DEFAULT_MODEL` | Override default model (optional) |
| `CRITIC_LOG_PATH` | Path to critique log (default: `memory/critic-log.json`) |

### Troubleshooting Configuration

**Problem**: Critic always returns low scores
- **Check**: Is task description clear? Add more context.
- **Fix**: Adjust prompt to be more lenient or calibrate expectations.

**Problem**: Critic times out
- **Check**: Model endpoint reachable? API key valid?
- **Fix**: Set a lower `timeout`; use faster model; truncate long outputs.

**Problem**: Scores vary widely between runs
- **Check**: Temperature > 0? Model non-deterministic?
- **Fix**: Set `temperature: 0` in configuration.

**Problem**: Critic misses obvious errors
- **Check**: Model capability; prompt may need domain-specific instructions.
- **Fix**: Switch to more capable model; add explicit evaluation criteria to prompt.


path: references/patterns.md
content: ## Critic Agent Integration Patterns

### Pattern 1: Gatekeeper (Synchronous)
Use when output quality is critical and you cannot proceed without approval.

```
[Agent generates output] → [Critic evaluates] → if score >= threshold: deliver
                                               else: reject and revise
```
- Synchronous blocking call
- Guarantees quality before delivery
- Use for: customer contracts, security code, public releases

### Pattern 2: Advisor (Asynchronous)
Use when you want feedback but not a hard block.

```
[Agent generates output] → [Critic evaluates in background] → deliver immediately
                                     ↓
                            [Feedback logged for future improvement]
```
- Non-blocking: deliver first, critique later
- Feedback stored for training data, post-mortem
- Use for: internal drafts, exploratory work

### Pattern 3: Iterative Refinement
Use when multiple improvement cycles are acceptable.

```
[Output v1] → [Critic] → revision → [Critic] → revision → ... → deliver
```
- Each revision incorporates previous feedback
- Can auto-retry up to max attempts
- Use for: important documents, polished content

### Pattern 4: Multi-Critic Consensus
Use for high-stakes outputs where single critic may be biased or error-prone.

```
[Output] → [Critic A] → [Critic B] → [Critic C] → aggregate scores
                                   ↓
                          If consensus >= threshold: deliver
                          If major disagreement: escalate to human
```
- Multiple independent evaluations
- Consensus increases confidence
- Use for: legal documents, executive reports

### Model Selection Guide
- **Default**: Use the same model as the writer agent
- **Elevated**: Use a more capable model (Claude Opus, GPT-4) for nuanced critique
- **Specialized**: Use a model fine-tuned for the domain (code review models, fact-checking models)
- **Budget**: Use a smaller, faster model (Haiku, GPT-4o Mini) for high-volume cases

### Prompt Customization
Modify `scripts/critic-system-prompt.txt` to add domain-specific criteria:

**For code:**
```
Also evaluate:
- Code complexity (cyclomatic)
- Performance characteristics
- Test coverage
- Security practices (OWASP)
```

**For writing:**
```
Also evaluate:
- Argument flow and persuasion
- Tone appropriateness for audience
- Evidence quality and sourcing
- SEO considerations
```

**For data analysis:**
```
Also evaluate:
- Statistical methodology soundness
- Data visualization effectiveness
- Conclusion validity
- Assumption transparency
```

### Threshold Calibration Strategy
1. Run 20-30 outputs through critic with human validation
2. Calculate correlation between critic score and human acceptance
3. Set threshold at point where false positive rate < 5%
4. Review and adjust quarterly

### Logging and Monitoring
Every critique should be logged to `memory/critic-log.json`:

```json
{
  "timestamp": "2025-01-15T10:30:00Z",
  "task": "Generate API documentation",
  "outputHash": "abc123...",
  "score": 82,
  "verdict": "good",
  "dimensionScores": {...},
  "model": "claude-3.5-sonnet",
  "retryCount": 0,
  "delivered": true
}
```

Use this log to:
- Monitor quality trends over time
- Identify model degradation
- Spot systematic weaknesses in agent outputs


path: scripts/compute-score.js
content: #!/usr/bin/env node
/**
 * Critic Score Helper
 * Computes weighted overall score and verdict from dimension scores.
 *
 * Usage: echo '{"correctness":85,"clarity":90,"completeness":70,"safety":95}' | node compute-score.js
 */

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

let input = '';
rl.on('line', (line) => {
  input += line;
});

rl.on('close', () => {
  try {
    const scores = JSON.parse(input);
    const weights = {
      correctness: 0.40,
      clarity: 0.25,
      completeness: 0.25,
      safety: 0.10
    };

    // Validate scores are numbers 0-100
    for (const [dim, weight] of Object.entries(weights)) {
      if (typeof scores[dim] !== 'number' || scores[dim] < 0 || scores[dim] > 100) {
        throw new Error(`${dim} score must be a number between 0 and 100`);
      }
    }

    // Compute weighted sum
    const overall = Object.entries(weights).reduce(
      (sum, [dim, weight]) => sum + scores[dim] * weight,
      0
    );

    // Determine verdict
    let verdict;
    if (overall >= 80) {
      verdict = 'excellent';
    } else if (overall >= 70) {
      verdict = 'good';
    } else if (overall >= 50) {
      verdict = 'needsRevision';
    } else {
      verdict = 'fail';
    }

    const result = {
      score: Math.round(overall * 10) / 10, // one decimal
      verdict,
      breakdown: {
        correctness: {
          score: scores.correctness,
          weight: weights.correctness,
          contribution: Math.round(scores.correctness * weights.correctness * 10) / 10
        },
        clarity: {
          score: scores.clarity,
          weight: weights.clarity,
          contribution: Math.round(scores.clarity * weights.clarity * 10) / 10
        },
        completeness: {
          score: scores.completeness,
          weight: weights.completeness,
          contribution: Math.round(scores.completeness * weights.completeness * 10) / 10
        },
        safety: {
          score: scores.safety,
          weight: weights.safety,
          contribution: Math.round(scores.safety * weights.safety * 10) / 10
        }
      }
    };

    console.log(JSON.stringify(result, null, 2));
    process.exit(0);
  } catch (error) {
    console.error(JSON.stringify({ error: error.message }));
    process.exit(1);
  }
});


path: scripts/critic-system-prompt.txt
content: You are a Critic Agent responsible for evaluating the quality of outputs from other AI agents.

Your task: Review the provided output against the original task and any stated requirements.

Evaluation Dimensions:
1. Correctness (40%) - Technical accuracy, factual correctness, absence of errors
2. Clarity (25%) - Readability, logical structure, effective communication
3. Completeness (25%) - Coverage of requirements, edge cases, thoroughness
4. Safety (10%) - Ethical compliance, bias awareness, security considerations

For each dimension, provide:
- A score from 0-100
- Specific feedback explaining the score (2-3 sentences)
- Concrete suggestions for improvement (1-2 bullet points)

Scoring Guidelines:
- 90-100: Exceptional, exceeds expectations
- 80-89: Strong, meets all requirements with minor room for improvement
- 70-79: Good, meets core requirements but has some issues
- 50-69: Needs revision, significant gaps or errors
- 0-49: Fail, major problems requiring complete rework

Calculate the overall score: (correctness * 0.40) + (clarity * 0.25) + (completeness * 0.25) + (safety * 0.10)

Respond with ONLY a JSON object in this exact format:

{
  "score": 85.5,
  "feedback": {
    "correctness": "The implementation correctly handles the basic case but misses edge case X. There's a potential bug when Y occurs. The algorithm logic is sound overall.",
    "clarity": "Well-structured with clear sections. Variable names could be more descriptive. Some complex statements could be broken down.",
    "completeness": "Covers requirements A and B but ignores requirement C. Missing documentation on how to handle Z. Does not address potential performance concerns.",
    "safety": "No obvious security vulnerabilities. Input validation could be stronger. Consider adding rate limiting if this is network-facing."
  },
  "overall": "Solid implementation with good structure; address the edge case and add missing requirement.",
  "suggestions": [
    "Add input validation for empty or malformed data",
    "Implement error handling for the X scenario",
    "Include docstring explaining parameters and return values"
  ],
  "dimensionScores": {
    "correctness": 85,
    "clarity": 80,
    "completeness": 70,
    "safety": 90
  }
}

Do not include any text outside the JSON. Ensure all scores are integers 0-100.

Original Task:
{{TASK}}

Output to Review:
{{OUTPUT}}

Additional Context (requirements, constraints):
{{CONTEXT}}

Now provide your critique:


path: scripts/test-critic.sh
content: #!/bin/bash
# Critic Agent Test Scenario
# Demonstrates spawning a critic to review a sample task output

set -e

echo "🧪 Critic Agent Pattern - Test Scenario"
echo "========================================"
echo ""

# Check prerequisites
if ! command -v openclaw &> /dev/null; then
  echo "❌ openclaw CLI not found. Please install OpenClaw."
  exit 1
fi

if ! command -v jq &> /dev/null; then
  echo "❌ jq is required. Install with: apt install jq (or brew install jq)"
  exit 1
fi

# Test configuration
TASK="Write a Python function that checks if a string is a palindrome. Ignore spaces and case."
OUTPUT="def is_palindrome(s):\n    s = s.lower().replace(' ', '')\n    return s == s[::-1]"
CONTEXT='{"requirements": ["handle edge cases like empty string", "include docstring", "handle non-string inputs"]}'

echo "📋 Task:"
echo "$TASK"
echo ""
echo "📝 Agent Output:"
echo "$OUTPUT"
echo ""
echo "📦 Context:"
echo "$CONTEXT"
echo ""

# Build critic prompt
PROMPT_TEMPLATE="$(cat /home/weq/.openclaw/workspace/skills/critic-agent/scripts/critic-system-prompt.txt)"
FULL_PROMPT=$(echo "$PROMPT_TEMPLATE" \
  | sed "s/{{TASK}}/$TASK/g" \
  | sed "s/{{OUTPUT}}/$OUTPUT/g" \
  | sed "s/{{CONTEXT}}/$CONTEXT/g")

echo "🤖 Spawning Critic Agent..."
echo ""

# Run critic agent (using --local for deterministic test)
CRITIQUE_JSON=$(echo "$FULL_PROMPT" | openclaw agent --local --json -m "$FULL_PROMPT" 2>/dev/null)

# Check if we got valid JSON
if ! echo "$CRITIQUE_JSON" | jq . > /dev/null 2>&1; then
  echo "⚠️  Critic did not return valid JSON. This may be due to missing API keys or model configuration."
  echo "Raw output: $CRITIQUE_JSON"
  echo ""
  echo "To run this test successfully:"
  echo "1. Ensure your LLM provider API key is configured (e.g., OPENROUTER_API_KEY)"
  echo "2. Or adjust the test to use a different model"
  exit 1
fi

echo "✅ Critic response received:"
echo "$CRITIQUE_JSON" | jq .
echo ""

# Extract score
SCORE=$(echo "$CRITIQUE_JSON" | jq -r '.score')
VERDICT=$(echo "$CRITIQUE_JSON" | jq -r '.overall')
SUGGESTIONS=$(echo "$CRITIQUE_JSON" | jq -r '.suggestions[]')

echo "📊 Results"
echo "---------"
echo "Score: $SCORE"
echo "Verdict: $VERDICT"
echo ""
echo "Suggestions:"
echo "$SUGGESTIONS" | sed 's/^/  • /'
echo ""

# Compute final score using helper
echo "$CRITIQUE_JSON" | node /home/weq/.openclaw/workspace/skills/critic-agent/scripts/compute-score.js > /dev/null 2>&1 || true

# Determine pass/fail
if (( $(echo "$SCORE >= 70" | bc -l 2>/dev/null || echo "$SCORE >= 70" | awk '{print ($1 >= 70)}') )); then
  echo "✅ PASS - Output meets quality threshold"
  exit 0
else
  echo "❌ FAIL - Output needs revision"
  exit 1
fi


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)