KingInYellows

smart-submit

'Stage, audit, commit, and submit uncommitted changes via Graphite, with parallel code-review agents. Use when user says "submit this", "ship it", or "commit and push", or has uncommitted work to turn into a PR. Requires uncommitted changes — a clean, already-committed branch needs only gt submit; amending an already-submitted branch is the gt-amend skill.'

KingInYellows 0 Updated 2w ago
GitHub

Install

npx skillscat add kinginyellows/yellow-plugins/smart-submit

Install via the SkillsCat registry.

SKILL.md

What It Does

Conducts a systematic code quality audit of all uncommitted changes using
specialized agents, then creates a conventional commit and submits via
Graphite. Ensures no anti-patterns, secrets, or silent failures enter the
codebase.

When to Use

  • User says "submit this", "ship it", or "commit and push", or has
    uncommitted work to turn into a PR.
  • Requires uncommitted changes — a clean, already-committed branch needs
    only gt submit; amending an already-submitted branch is the gt-amend
    skill instead.

Usage

Optional arguments:

  • --amend — Amend the current branch commit instead of creating a new branch
  • --dry-run — Run the audit but skip the actual submission
  • --no-verify — Skip the audit and submit directly (use with caution)
  • --publish — Override draft mode: submit as published even if submit.draft: true in .graphite.yml

The argument text provided after the skill name (if any) is available as
context for this invocation.

Phase 0: Read Convention File

Before any other work, check for a .graphite.yml convention file and parse
repo-level settings. Run a single Bash call:

REPO_TOP=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
GW_DRAFT=""
GW_MERGE_WHEN_READY=""
GW_RESTACK_BEFORE=""
GW_AUDIT_AGENTS=""
GW_SKIP_ON_DRAFT=""
GW_BRANCH_PREFIX=""

if command -v yq >/dev/null 2>&1 && \
   yq --help 2>&1 | grep -qi 'jq wrapper\|kislyuk' && \
   [ -f "$REPO_TOP/.graphite.yml" ]; then
  yq_err=""
  GW_DRAFT=$(yq -r '.submit.draft // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="submit.draft"
  GW_MERGE_WHEN_READY=$(yq -r '.submit.merge_when_ready // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="${yq_err:+$yq_err, }merge_when_ready"
  GW_RESTACK_BEFORE=$(yq -r '.submit.restack_before // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="${yq_err:+$yq_err, }restack_before"
  GW_AUDIT_AGENTS=$(yq -r '.audit.agents // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="${yq_err:+$yq_err, }audit.agents"
  GW_SKIP_ON_DRAFT=$(yq -r '.audit.skip_on_draft // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="${yq_err:+$yq_err, }skip_on_draft"
  GW_BRANCH_PREFIX=$(yq -r '.branch.prefix // ""' "$REPO_TOP/.graphite.yml" 2>/dev/null) || yq_err="${yq_err:+$yq_err, }branch.prefix"
  if [ -n "$yq_err" ]; then
    printf '[gt-workflow] Warning: yq failed to parse fields: %s. Using defaults for those.\n' "$yq_err" >&2
  else
    printf '[gt-workflow] Convention file loaded: %s/.graphite.yml\n' "$REPO_TOP" >&2
  fi
elif [ -f "$REPO_TOP/.graphite.yml" ]; then
  printf '[gt-workflow] Warning: .graphite.yml exists but yq (kislyuk) is not installed. Using defaults.\n' >&2
  printf '[gt-workflow] Install yq: pip install yq\n' >&2
fi

# Validate and clamp audit.agents to 1-3 range
if [ -n "$GW_AUDIT_AGENTS" ]; then
  case "$GW_AUDIT_AGENTS" in
    *[!0-9]*) printf '[gt-workflow] Warning: audit.agents value "%s" is not an integer. Using default 3.\n' "$GW_AUDIT_AGENTS" >&2; GW_AUDIT_AGENTS=3 ;;
  esac
  if [ "$GW_AUDIT_AGENTS" -lt 1 ] 2>/dev/null; then
    printf '[gt-workflow] Warning: audit.agents=%s is below minimum. Using 1.\n' "$GW_AUDIT_AGENTS" >&2
    GW_AUDIT_AGENTS=1
  elif [ "$GW_AUDIT_AGENTS" -gt 3 ] 2>/dev/null; then
    printf '[gt-workflow] Warning: audit.agents=%s exceeds maximum. Using 3.\n' "$GW_AUDIT_AGENTS" >&2
    GW_AUDIT_AGENTS=3
  fi
fi

# Validate branch.prefix against allow-list
if [ -n "$GW_BRANCH_PREFIX" ]; then
  if ! printf '%s' "$GW_BRANCH_PREFIX" | grep -qE '^[a-z0-9][a-z0-9/_-]*$'; then
    printf '[gt-workflow] Error: branch.prefix "%s" contains invalid characters. Using empty prefix.\n' "$GW_BRANCH_PREFIX" >&2
    GW_BRANCH_PREFIX=""
  fi
fi

Store these values for use in subsequent phases. When a value is empty, use the
hardcoded default (draft=false, merge_when_ready=false, restack_before=true,
audit_agents=3, skip_on_draft=false, branch_prefix="").

Phase 1: Understand Current State

1. Check for Changes

Run these commands in parallel to understand the working tree and stack
position:

git status --short
git diff --stat
gt log short
gt trunk

If there are no uncommitted changes, tell the user and exit.

2. Determine Branch Context

Check whether the current branch is trunk or a feature branch:

current=$(git branch --show-current)
trunk=$(gt trunk)
echo "current=$current trunk=$trunk"
  • If current == trunk → will use gt create <branch-name> -m "message" to
    create a new branch
  • If current != trunk → will use gt modify -m "message" to update the
    current branch
  • If --amend argument was passed and on a feature branch → will use
    gt commit amend instead

Phase 2: Audit (skip if --no-verify)

Skip-on-draft check: If $GW_SKIP_ON_DRAFT is true and $GW_DRAFT is
true (from .graphite.yml), skip the entire audit phase and proceed to
Phase 3.

Note: This check uses the config-derived values in $GW_SKIP_ON_DRAFT
and $GW_DRAFT from .graphite.yml. CLI flags such as --publish affect
the eventual submit mode, but they do not override the audit skip decision in
this phase.

0. Capture the Diff Once

Before spawning auditors, capture the full diff — staged and unstaged — so
all agents can use it without redundant calls. Use git diff HEAD rather
than a bare git diff: a bare git diff only shows unstaged changes, so
any changes the user staged with git add before invoking this skill would
be silently excluded from the audit while still ending up in the commit
(Phase 3 generates the commit message from git diff --cached and commits
the full index).

git diff HEAD

Store this output as $DIFF_OUTPUT (pass it as context to each agent below).

1. Run the Audit

Invoke the Skill tool with skill: "audit-review", passing $DIFF_OUTPUT
and $GW_AUDIT_AGENTS as context. (On Codex there is no Skill tool — read
the Codex-exposed audit-review skill and follow it directly with the same
context.) It runs the appropriate quick-code-review
/ quick-security-scan / quick-error-check prompts (1-3 of them, per
$GW_AUDIT_AGENTS) and returns a CRITICAL / MINOR / CLEAN verdict with
file:line findings.

2. Gate Check

If audit-review reports a dispatch failure (an audit failed to run or
timed out), inform the user which audit is missing and ask whether to
proceed with partial results or abort.

IF CRITICAL ISSUES (secrets, production mocks, silent failures):

  1. Display blocking issues with file:line references
  2. Use AskUserQuestion (on Codex, which lacks that tool: present the same
    options as a numbered list in your reply and wait for the user's answer)
    to ask:
    • "Fix issues before submitting (Recommended)"
    • "Submit anyway"
    • "Abort"
  3. If "Fix issues" → stop and let the user fix them
  4. If "Abort" → stop entirely

IF MINOR ISSUES (TODOs, style, minor logic):

  1. Display warnings
  2. Proceed but note them in the output

IF CLEAN: Proceed automatically.

Phase 3: Stage & Commit

1. Stage Specific Files

IMPORTANT: Do NOT use git add . or git add -A. Instead, stage only the
specific changed files to avoid accidentally committing secrets, binaries, or
unrelated files.

# Get the list of changed/untracked files
git diff --name-only
git ls-files --others --exclude-standard

Review the file list. Exclude any files that look like:

  • .env* files
  • Credential/key files
  • Large binaries
  • Build artifacts

Stage the appropriate files by name:

git add -- "<file1>" "<file2>"

2. Generate Conventional Commit Message

Analyze the staged diff to determine the commit type and scope:

git diff --cached --stat
git diff --cached

Generate a conventional commit message following this format:

  • feat: — new feature
  • fix: — bug fix
  • refactor: — code restructuring
  • docs: — documentation changes
  • test: — test additions/changes
  • chore: — maintenance, config, dependencies

The message should be concise (under 72 chars for the subject line). Include a
body if the changes are complex.

Take the Linear ID only from the last path segment of the branch name, which must start with [A-Z]{2,5}-[0-9]{1,6} followed by - or the end of the name, or from the stack item's Linear: field; ignore IDs mentioned anywhere else.
When an ID qualifies, end the body with Part of <ISSUE-ID>, and write Closes <ISSUE-ID> instead only when the user confirms through AskUserQuestion that
this change completes the issue (a stack built bottom-up would otherwise close
the issue from its first branch). Skip the line when no ID qualifies. Graphite
turns the commit body into the PR description, and the merge queue builds the
squash commit from it; the closing word is how Linear moves the issue to Done
even though the queue closes the PR instead of merging it. Keep the line when
--amend rewrites the message.

3. Create Commit via Graphite

If on trunk (creating new branch):

Derive the branch name from the commit type and a short slug (e.g.,
feat/add-user-auth, fix/null-pointer-crash). If $GW_BRANCH_PREFIX is set,
prepend it to the branch name:

gt create "<GW_BRANCH_PREFIX><branch-name>" -m "<conventional commit message>"

For example, with branch.prefix: "agent/" and slug feat/add-user-auth, the
branch name becomes agent/feat/add-user-auth.

If on feature branch (adding to existing):

gt modify -m "<conventional commit message>"

If --amend (modifying current branch):

gt commit amend -m "<conventional commit message>"

Phase 4: Submit

1. Push to GitHub

If --dry-run was provided, skip this step and do not run gt submit; instead,
only simulate the submission and proceed to the result summary without making
any remote changes.

Build the submit command with convention file flags. First, if $GW_RESTACK_BEFORE
is true, run restack as a separate preceding command:

gt stack restack

Then submit with flags based on .graphite.yml values:

gt submit --no-interactive

Append flags to the submit command (only if set and non-empty):

  • If $GW_DRAFT is true (and no explicit --publish argument): add --draft
  • If $GW_MERGE_WHEN_READY is true: add --merge-when-ready

After submitting, confirm the new stack state:

gt log short
gt pr

Output a summary:

  • Commit message used
  • Branch created/amended
  • PR link
  • Stack visualization
  • Any audit warnings that were noted

Success Criteria

  • All uncommitted code audited by 1-3 specialized agents (unless --no-verify)
  • No critical issues committed
  • Files staged individually (no blanket git add .)
  • Conventional commit message generated from diff analysis
  • Graphite stack created/updated and submitted (or a dry-run summary produced
    when --dry-run is used)
  • User provided with PR link and stack context