Claude-skill-registry feedback-handler
Handles FABER workflow feedback requests - posting to issues and tracking responses
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/feedback-handler" ~/.claude/skills/majiayu000-claude-skill-registry-feedback-handler && rm -rf "$T"
skills/data/feedback-handler/SKILL.mdFeedback Handler Skill
<CONTEXT> You are the feedback-handler skill responsible for managing human-in-the-loop (HITL) feedback requests in FABER workflows. You handle:- Posting feedback requests to issue comments when feedback is needed
- Tracking feedback state in run state files
- Formatting feedback requests with clear context and options
You work with the work plugin (comment-creator) to post comments and the run-manager to update state. </CONTEXT>
<CRITICAL_RULES>
- ALWAYS emit decision_point event when requesting feedback
- ALWAYS update run state with feedback_request details
- ALWAYS format feedback comments with clear context and options
- ALWAYS include example @faber command in issue comments (for future integration)
- NEVER post feedback request without updating state first
- ALWAYS track notification_sent status in state </CRITICAL_RULES>
Request feedback from user and optionally post to issue.
{ "operation": "request-feedback", "parameters": { "run_id": "fractary/claude-plugins/abc-123-...", "work_id": "258", "phase": "architect", "step": "design-review", "feedback_type": "approval", "prompt": "Please review the architectural design and approve to proceed.", "options": ["approve", "reject", "request_changes"], "context": { "artifact_path": "/specs/WORK-00258-design.md", "summary": "Design proposes 3-layer architecture with handler pattern" }, "post_to_issue": true, "cli_prompt": true } }
Parameters:
(required): FABER run identifierrun_id
(optional): Issue ID for posting commentwork_id
(required): Current workflow phasephase
(required): Current workflow stepstep
(required): Type of feedback (see FEEDBACK_TYPES)feedback_type
(required): Human-readable question/requestprompt
(required): Array of valid response optionsoptions
(optional): Additional context for the decisioncontext
(optional, default: true if work_id present): Post as issue commentpost_to_issue
(optional, default: true): Show prompt in CLIcli_prompt
process-response operation
Process a feedback response and update state.
</INPUTS>{ "operation": "process-response", "parameters": { "run_id": "fractary/claude-plugins/abc-123-...", "request_id": "fr-20251206-001", "response": "approve", "comment": "Looks good, proceed with implementation", "source": "cli", "user": "jmcwilliam" } }
<FEEDBACK_TYPES>
| Type | Description | Default Options |
|---|---|---|
| Binary approval decision | ["approve", "reject"] |
| Confirm destructive action | ["confirm", "cancel"] |
| Choose from options | [custom list required] |
| Request information | [free text accepted] |
| Review with feedback option | ["approve", "request_changes", "reject"] |
| Error occurred, decide action | ["retry", "skip", "abort"] |
| </FEEDBACK_TYPES> |
-
Generate request ID
request_id = "fr-" + timestamp + "-" + short_uuid Example: fr-20251206-a1b2c3 -
Build feedback request object
{ "request_id": "fr-20251206-a1b2c3", "type": "approval", "prompt": "Please review the design...", "options": ["approve", "reject", "request_changes"], "context": { ... }, "requested_at": "2025-12-06T18:00:00Z", "notification_sent": { "cli": false, "issue_comment": false, "comment_url": null } } -
Emit decision_point event
plugins/faber/skills/run-manager/scripts/emit-event.sh \ --run-id "{run_id}" \ --type "decision_point" \ --phase "{phase}" \ --step "{step}" \ --message "Awaiting feedback: {prompt}" \ --metadata '{"request_id": "{request_id}", "type": "{feedback_type}", "options": {options}}' -
Update run state
{ "status": "awaiting_feedback", "current_phase": "{phase}", "current_step": "{step}", "feedback_request": { ... request object ... }, "resume_point": { "phase": "{phase}", "step": "{step}", "step_index": {current_step_index} } } -
Post to issue (if work_id present and post_to_issue=true)
- Use comment-creator skill
- Format using ISSUE_COMMENT_TEMPLATE
- Store comment_url in notification_sent
-
Show CLI prompt (if cli_prompt=true)
- Use AskUserQuestion tool
- Present options from feedback_request
-
Return request details
{ "status": "success", "operation": "request-feedback", "result": { "request_id": "fr-20251206-a1b2c3", "state_updated": true, "notifications": { "cli": true, "issue_comment": true, "comment_url": "https://..." } } }
process-response Operation
-
Load current state
- Verify status is "awaiting_feedback"
- Verify request_id matches pending request
-
Validate response
- Check response is in options list (or accept free text for clarification type)
-
Emit feedback_received event
plugins/faber/skills/run-manager/scripts/emit-event.sh \ --run-id "{run_id}" \ --type "feedback_received" \ --phase "{phase}" \ --step "{step}" \ --message "Feedback received: {response}" \ --metadata '{"request_id": "{request_id}", "response": "{response}", "user": "{user}", "source": "{source}"}' -
Update state
- Clear feedback_request
- Set status to "in_progress"
- Add to feedback_history array
-
Return processed response
{ "status": "success", "operation": "process-response", "result": { "request_id": "fr-20251206-a1b2c3", "response": "approve", "action": "continue", "resume_point": { ... } } }
<ISSUE_COMMENT_TEMPLATE> When posting feedback requests to GitHub issues:
## Feedback Requested **Workflow Run**: `{run_id}` **Phase**: {phase} **Step**: {step} **Requested**: {timestamp} UTC ### Decision Needed {prompt} {#if context.summary} **Summary**: {context.summary} {/if} {#if context.artifact_path} **Artifact**: [{artifact_filename}]({context.artifact_path}) {/if} ### Options {#each options} {index}. **{option}** - {option_description} {/each} ### How to Respond Reply to this issue with your decision. Include `@faber resume` in your comment to trigger workflow continuation. **Example response:**
I approve this design. The approach looks good.
@faber resume
--- _This feedback request will remain open until addressed._ _Run ID: `{run_id}` | Request ID: `{request_id}`_
Option Descriptions (based on type):
For
approval:
- approve: Continue to next phase
- reject: Cancel this workflow run
For
review:
- approve: Continue to next phase
- request_changes: Provide feedback for revision
- reject: Cancel this workflow run
For
error_resolution:
- retry: Attempt the step again
- skip: Skip this step and continue
- abort: Cancel this workflow run
For
confirmation:
- confirm: Proceed with the action
- cancel: Do not proceed </ISSUE_COMMENT_TEMPLATE>
{ "status": "success", "operation": "request-feedback", "message": "Feedback request created", "details": { "request_id": "fr-20251206-a1b2c3", "type": "approval", "phase": "architect", "step": "design-review" }, "notifications": { "cli": true, "issue_comment": true, "comment_url": "https://github.com/fractary/claude-plugins/issues/258#issuecomment-xyz" } }
process-response Success
</OUTPUTS>{ "status": "success", "operation": "process-response", "message": "Feedback processed: approve", "details": { "request_id": "fr-20251206-a1b2c3", "response": "approve", "action": "continue", "resume_point": { "phase": "architect", "step": "design-review" } } }
<ERROR_HANDLING>
| Error | Code | Action |
|---|---|---|
| Missing run_id | 1 | Return error, cannot proceed |
| Invalid feedback_type | 2 | Return error, list valid types |
| State not awaiting_feedback | 3 | Return error, nothing to process |
| Request ID mismatch | 4 | Return error, may be stale request |
| Invalid response option | 5 | Re-prompt with valid options |
| Issue comment failed | 6 | Warn but continue (non-critical) |
| State update failed | 7 | Return error (critical) |
| </ERROR_HANDLING> |
<COMPLETION_CRITERIA> request-feedback complete when:
- Decision_point event emitted
- State updated to awaiting_feedback
- Notification sent (CLI and/or issue comment)
- Request details returned
process-response complete when:
- Response validated
- Feedback_received event emitted
- State updated to in_progress
- Action determined and returned </COMPLETION_CRITERIA>
request-feedback Start:
🎯 STARTING: Feedback Handler (request-feedback) Run ID: fractary/claude-plugins/abc-123-... Type: approval Phase: architect Step: design-review ───────────────────────────────────────
request-feedback End:
✅ COMPLETED: Feedback Handler (request-feedback) Request ID: fr-20251206-a1b2c3 Notifications: CLI ✓, Issue Comment ✓ Comment URL: https://github.com/... ─────────────────────────────────────── Status: awaiting_feedback Next: User must provide feedback to continue
process-response Start:
🎯 STARTING: Feedback Handler (process-response) Request ID: fr-20251206-a1b2c3 Response: approve ───────────────────────────────────────
process-response End:
✅ COMPLETED: Feedback Handler (process-response) Action: continue Resume Point: architect:design-review ─────────────────────────────────────── Next: Workflow will resume from design-review
Integration Points
Called By:
- faber-manager agent (at autonomy gates)
- faber-manager agent (on step failure for error_resolution)
Invokes:
- run-manager scripts (emit-event.sh)
- comment-creator skill (for issue comments)
State Files:
- Reads/Writes:
.fractary/plugins/faber/runs/{run_id}/state.json
Scripts:
- Generate unique feedback request IDscripts/generate-request-id.sh
- Format feedback request as markdownscripts/format-feedback-comment.sh
- Update run state with feedback detailsscripts/update-feedback-state.sh
Script Usage
generate-request-id.sh
# Generate a new request ID ./scripts/generate-request-id.sh # Output: fr-20251206-a1b2c3
format-feedback-comment.sh
./scripts/format-feedback-comment.sh \ --run-id "fractary/claude-plugins/abc-123" \ --request-id "fr-20251206-a1b2c3" \ --type "approval" \ --phase "architect" \ --step "design-review" \ --prompt "Please review the design" \ --options '["approve", "reject"]' \ --context '{"summary": "3-layer architecture"}' # Outputs formatted markdown comment to stdout
update-feedback-state.sh
# Set awaiting_feedback status ./scripts/update-feedback-state.sh \ --run-id "fractary/claude-plugins/abc-123" \ --operation set-awaiting \ --request-id "fr-20251206-a1b2c3" \ --type "approval" \ --prompt "Please review" \ --options '["approve", "reject"]' \ --phase "architect" \ --step "design-review" # Clear awaiting status after feedback ./scripts/update-feedback-state.sh \ --run-id "fractary/claude-plugins/abc-123" \ --operation clear-awaiting \ --phase "architect" \ --step "design-review" # Add to feedback history ./scripts/update-feedback-state.sh \ --run-id "fractary/claude-plugins/abc-123" \ --operation add-history \ --request-id "fr-20251206-a1b2c3" \ --type "approval" \ --response "approve" \ --user "jmcwilliam" \ --source "cli"
Comment-Creator Integration
To post feedback request to issue:
Invoke Skill: fractary-work:comment-creator Operation: create-comment Parameters: issue_id: "{work_id}" message: "{formatted_markdown}" # From format-feedback-comment.sh output author_context: "ops"
The comment-creator returns
comment_url which should be stored in the run state via update-feedback-state.sh --comment-url.
</DOCUMENTATION>