From layerline
Run the Layerline review/approval flow — create reviews, add files and reviewers, leave threaded comments with severity and type, submit per-reviewer or per-file decisions, attach checklists, and use AI helpers for change summaries and feedback rewriting. Use whenever the user asks Claude Code to start a review on an asset or task, request approvals, comment on a review, mark a comment resolved, approve/reject/request-changes, run a pre-submit check, or estimate approval readiness. Covers the full review lifecycle (draft → submitted → in_review → decided → reopened/superseded), reviewer roles (reviewer/approver/final_approver/observer), and AI-assisted tools that summarize comments, rewrite vague feedback, and score readiness.
How this skill is triggered — by the user, by Claude, or both
Slash command
/layerline:reviewsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Workflow for the review/approval flow (`mcp__layerline__*` tools, review domain).
Workflow for the review/approval flow (mcp__layerline__* tools, review domain).
draft → submitted → in_review → decided (approved | changes_requested | rejected)
↓
reopened → in_review → …
↓
superseded by newer review
A review hangs off either an asset or a task (provide one of asset_id / task_id), inside a project. It lists file versions, has reviewers with roles, collects comments and per-reviewer decisions, and can carry checklists.
list_reviews(projectId, asset_id?, status_id?, decision?, reviewer_id?, due_before?, due_after?, page?, limit?)
get_review(projectId, reviewId)
list_review_comments(projectId, reviewId, status?, type?, severity?, author_id?, review_file_id?)
list_review_decisions(projectId, reviewId)
get_reviewers(projectId, reviewId)
get_review_checklists(reviewId)
create_review(projectId, asset_id? | task_id?, title?, description?, review_type?, due_at?, file_version_ids?[])
update_review(projectId, reviewId, title?, description?, due_at?) // due_at: null clears it
delete_review(projectId, reviewId) // soft delete
submit_for_review(projectId, reviewId) // draft → submitted
start_review(projectId, reviewId) // submitted → in_review
change_review_status(projectId, reviewId, statusId) // jump to any project review status
reopen_review(projectId, reviewId) // decided → in_review (clears decision)
supersede_review(projectId, reviewId, newReviewId) // close old; reference newer
file_version_ids shape:
[{ file_id: <ls fileId>, file_version_id: <ls versionId>, compare_version_id?: <ls versionId> }]
Resolve file ids via the storage tools (ls_list_files, ls_find_file_by_path, ls_get_version_history).
add_files_to_review(projectId, reviewId, file_version_ids[])
remove_file_from_review(projectId, reviewId, reviewFileId)
reviewFileId is the junction id (returned by add_files_to_review / get_review), not the underlying file id.
assign_reviewers(projectId, reviewId, reviewers[])
// reviewers: [{ user_id, role: "reviewer"|"approver"|"final_approver"|"observer" }]
remove_reviewer(projectId, reviewId, reviewerUserId)
get_reviewers(projectId, reviewId)
Roles, briefly:
reviewer — leaves comments, no formal decision.approver — submits a decision; counts toward approval.final_approver — same as approver; their decision is the gate.observer — read-only; cannot submit decisions.Threaded with parent_id; can be attached to a specific reviewed file via review_file_id.
create_review_comment(projectId, reviewId, body, type?, severity?, parent_id?, review_file_id?)
// type: "general" | "blocker" | "suggestion" | "question" | "praise"
list_review_comments(projectId, reviewId, status?, type?, severity?, author_id?, review_file_id?)
update_review_comment(projectId, reviewId, commentId, body?, type?, severity?)
delete_review_comment(projectId, reviewId, commentId)
resolve_review_comment(projectId, reviewId, commentId)
reopen_review_comment(projectId, reviewId, commentId)
type: "blocker" is special — open blockers prevent approval and trigger warnings in pre_submit_check.
submit_review_decision(projectId, reviewId, decision, reason?)
// decision: "approved" | "changes_requested" | "rejected"
list_review_decisions(projectId, reviewId)
submit_file_decision(projectId, reviewId, reviewFileId, decision, reason?)
The authenticated user must already be an assigned reviewer (not observer) to submit a decision. Per-file decisions live alongside per-reviewer decisions — useful when a review covers multiple files and one is fine but another needs changes.
get_review_checklists(reviewId)
attach_checklist(reviewId, template_id? | (name + items[]))
update_checklist_item(itemId, result, notes?)
// result: "pass" | "fail" | "na" | null (null = clear)
Either pass a template_id (org-wide saved checklist) or pass a custom name + items[] (array of label strings) for a one-off.
generate_review_change_summary(reviewId)
// Cached summary of file diffs; returns structured payload for AI consumption.
summarize_review_comments(reviewId)
// Counts, blockers, type/severity breakdown, suggestedAction.
rewrite_feedback_actionable(originalText, reviewId?)
// Returns instruction to rewrite vague feedback into { area, problem, desired_outcome, severity }.
estimate_approval_readiness(reviewId)
// Score 0–1, verdict (likely_approved | likely_needs_changes | unlikely_to_approve | blocked).
pre_submit_check(reviewId)
// Checks unresolved blockers, unchecked checklist items, failed checklist items.
// Returns { passed: boolean, warnings[], recommendation }.
These are great when the user says "is this ready to ship?" or "summarise the feedback" — they avoid you needing to read every comment.
projectId, assetId (Hero Knight).ls_find_file_by_path(projectId, "Characters/Hero Knight/Modeling/hero_v05.fbx") → get fileId.ls_get_version_history(fileId) → grab the latest version.id.create_review(projectId, asset_id=heroId, title="Hero Knight modeling pass v05", file_version_ids=[{ file_id, file_version_id }]).assign_reviewers(projectId, reviewId, [{ user_id: artLeadId, role: "approver" }]).submit_for_review(projectId, reviewId).pre_submit_check(reviewId).passed: false, list the warnings to the user and stop. Don't auto-fix.get_reviewers(projectId, reviewId) → confirm the user is an assigned approver.submit_review_decision(projectId, reviewId, decision="approved", reason?).summarize_review_comments(reviewId) — gives counts + blockers.list_review_comments(projectId, reviewId, status="open").attach_checklist(reviewId, name="Animation QA", items=["Foot sliding fixed","Loop seamless","No clipping","FPS stable"]).update_checklist_item(itemId, result="pass"|"fail"|"na", notes?).layerline:storage (ls_* tools).task_id instead of asset_id to create_review.rewrite_feedback_actionable — pair with update_review_comment to actually replace the text.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub bitvoke/layerline-skills --plugin layerline