Skip to content

feat(skills): vendor the outsource skill (explore/review/write)#2

Open
OriNachum wants to merge 1 commit into
mainfrom
feat/vendor-outsource-skill
Open

feat(skills): vendor the outsource skill (explore/review/write)#2
OriNachum wants to merge 1 commit into
mainfrom
feat/vendor-outsource-skill

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

Summary

  • Vendors the canonical outsource skill (explore/review/write) from guildmaster into .claude/skills/outsource/
  • Hands a scoped repo task to convertible (a different engine/mind) for a diverse second opinion — outsource review gives an independent diff review, outsource explore gives a fresh read of an area, outsource write delegates a small implementation
  • Cite-don't-import copy; INBOUND_ORIGINS=guildmaster; resolves the convertible CLI from PATH; read-only verbs run in an isolated throwaway git worktree
  • Markdownlint: .claude/skills/** is excluded by repo config — 0 errors, no changes needed
  • Patch bump (0.1.4 → 0.1.5) per version-check CI rule

Test plan

  • Confirm .claude/skills/outsource/SKILL.md is present with correct frontmatter name: outsource
  • Confirm .claude/skills/outsource/scripts/ directory exists with outsource.sh entry point
  • Run npx markdownlint-cli2 ".claude/skills/outsource/**/*.md" — expect 0 errors (excluded by repo config)
  • Run uv run pytest -n auto -v — all tests pass
  • Verify sloth --version reports 0.1.5
  • (Optional) If convertible is on PATH, run outsource review against a test diff

🤖 Generated with Claude Code

  • guildmaster (Claude)

Cite-don't-import copy of the canonical outsource skill from guildmaster:
hand a scoped repo task to convertible (a *different* engine/mind) for a
diverse second opinion — outsource review|explore|write. Portable wrapper;
resolves the convertible CLI from PATH. Patch bump per version-check rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Vendor outsource skill with convertible integration

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Vendors the canonical outsource skill from guildmaster into .claude/skills/outsource/
• Enables delegating scoped repo tasks to convertible (different engine/mind) for diverse second
  opinions
• Provides three verbs: explore (read-only investigation), review (independent diff review),
  write (implementation)
• Read-only verbs run isolated in throwaway git worktrees to prevent side effects
• Patch version bump from 0.1.4 to 0.1.5 per version-check CI rule
Diagram
flowchart LR
  User["User invokes outsource verb"] -->|explore| ReadOnly1["Read-only worktree investigation"]
  User -->|review| ReadOnly2["Read-only worktree diff review"]
  User -->|write| InPlace["In-place drive branch/PR"]
  ReadOnly1 --> Convertible["convertible drive CLI"]
  ReadOnly2 --> Convertible
  InPlace --> Convertible
  Convertible --> Result["TaskResult JSON parsed & printed"]

Loading

Grey Divider

File Changes

1. .claude/skills/outsource/scripts/outsource.sh ✨ Enhancement +259/-0

Outsource skill wrapper and CLI resolver

• Main entry point script that wraps convertible drive with three verbs (explore, review, write)
• Resolves convertible CLI portably from PATH or via uv run fallback
• Implements read-only isolation using throwaway git worktrees for explore/review verbs
• Parses command-line flags (--repo, --base, --engine, --model, --base-url, --max-steps, --timeout,
 --allow-dirty, --pr)
• Renders prompt templates with argument substitution and parses JSON output from convertible

.claude/skills/outsource/scripts/outsource.sh


2. .claude/skills/outsource/SKILL.md 📝 Documentation +104/-0

Outsource skill documentation and metadata

• Skill metadata and documentation with frontmatter (name: outsource, type: command)
• Explains the three verbs and their use cases with side-effect guarantees
• Documents all command-line options and environment variable overrides
• Specifies hard rules (read-only enforcement, dirty-tree guard, output as second opinion)
• Lists honest limits (worktree isolation + prompt constraint, committed-only review, single-model
 default)

.claude/skills/outsource/SKILL.md


3. .claude/skills/outsource/prompts/explore.md 📝 Documentation +20/-0

Explore verb prompt template

• Prompt template for the explore verb directing a fresh, independent investigation
• Enforces read-only constraints (read_file, list_dir, read-only run_command only)
• Instructs model to be concrete with file paths/line numbers and surface surprises/risks
• Guides efficient reading within step budget and structured findings report format

.claude/skills/outsource/prompts/explore.md


View more (4)
4. .claude/skills/outsource/prompts/review.md 📝 Documentation +27/-0

Review verb prompt template

• Prompt template for the review verb directing independent diff review
• Instructs model to start with git diff $BASE...HEAD analysis
• Enforces read-only constraints and prioritizes actionable findings over padding
• Guides structured review output with correctness risks, design concerns, and suggestions

.claude/skills/outsource/prompts/review.md


5. .claude/skills/outsource/prompts/write.md 📝 Documentation +13/-0

Write verb prompt template

• Prompt template for the write verb directing minimal, scoped implementation
• Instructs model to follow repository patterns and conventions
• Emphasizes smallest change that satisfies task without scope widening
• Guides concise summary output of changes and rationale

.claude/skills/outsource/prompts/write.md


6. CHANGELOG.md 📝 Documentation +8/-0

Add version 0.1.5 changelog entry

• Adds new section for version 0.1.5 with placeholder subsections (Added, Changed, Fixed)
• Maintains existing 0.1.4 section below

CHANGELOG.md


7. pyproject.toml ⚙️ Configuration changes +1/-1

Patch version bump to 0.1.5

• Bumps version from 0.1.4 to 0.1.5

pyproject.toml


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented May 31, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2)

Context used
✅ Compliance rules (platform): 20 rules

Grey Divider


Action required

1. outsource.sh error format violates 📘 Rule violation ✧ Quality
Description
Several new error paths print messages that are not exactly two non-empty lines in the required
error:/hint: format, and some omit a hint: line entirely. This breaks the standardized CLI
error contract and reduces usability/scripting consistency.
Code

.claude/skills/outsource/scripts/outsource.sh[R42-186]

Evidence
Rule 847434 requires CLI text-mode errors to be exactly two lines with error: then hint:. In
outsource.sh, resolve_convertible emits a multi-line heredoc (more than two lines),
render_prompt emits only an error: line with no hint:, and print_result emits multi-line
parse failures without a single two-line error:/hint: pair.

Rule 847434: CLI errors must include remediation hints and follow the two-line text format
.claude/skills/outsource/scripts/outsource.sh[42-49]
.claude/skills/outsource/scripts/outsource.sh[159-160]
.claude/skills/outsource/scripts/outsource.sh[177-185]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CLI errors must be exactly two non-empty lines in text mode:
1) `error: <message>`
2) `hint: <remediation>`

The new `outsource.sh` script has multiple error sites that either (a) print more than two lines, or (b) print an `error:` without any `hint:`.

## Issue Context
Compliance rule requires a consistent, two-line remediation format for user-facing CLI failures.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[42-49]
- .claude/skills/outsource/scripts/outsource.sh[146-146]
- .claude/skills/outsource/scripts/outsource.sh[159-160]
- .claude/skills/outsource/scripts/outsource.sh[177-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. outsource missing --json 📘 Rule violation ◔ Observability
Description
The new outsource CLI does not accept a --json flag for structured output even though it
introduces new verbs (explore, review, write). This violates the requirement that CLI verbs
support --json with structured stdout output.
Code

.claude/skills/outsource/scripts/outsource.sh[R51-155]

Evidence
Rule 847437 requires a --json flag for each new/modified CLI verb and structured JSON output when
enabled. The new outsource.sh usage/options and flag parsing omit any --json flag, and
print_result always prints human-readable lines like status: and summaries instead of providing
a structured JSON mode for outsource itself.

Rule 847437: CLI verbs must support a --json flag with structured output
.claude/skills/outsource/scripts/outsource.sh[51-74]
.claude/skills/outsource/scripts/outsource.sh[127-143]
.claude/skills/outsource/scripts/outsource.sh[170-197]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/modified CLI verbs must support a `--json` flag and, when enabled, emit valid JSON to stdout (with errors to stderr).

The new `outsource` script adds/defines verbs but provides no `--json` flag in usage text or option parsing, and always prints a human-formatted digest.

## Issue Context
Compliance rule 847437 requires `--json` support for CLI verbs so callers can reliably parse outputs.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[51-74]
- .claude/skills/outsource/scripts/outsource.sh[127-143]
- .claude/skills/outsource/scripts/outsource.sh[167-198]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Provenance tracking inconsistent 🐞 Bug ⚙ Maintainability
Description
.claude/skills/outsource/SKILL.md claims this skill is tracked in docs/skill-sources.md, but
docs/skill-sources.md contains no outsource entry, so provenance/re-sync documentation is now
incorrect.
Code

.claude/skills/outsource/SKILL.md[R100-103]

Evidence
The new SKILL.md explicitly claims provenance tracking exists in docs/skill-sources.md, but the
provenance table currently lists skills and does not include outsource, making the claim false
after this PR.

.claude/skills/outsource/SKILL.md[98-104]
docs/skill-sources.md[19-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`outsource/SKILL.md` states the skill is tracked in `docs/skill-sources.md`, but the repository’s provenance table does not include `outsource`. This breaks the repo’s stated “deterministic re-sync” workflow and leaves future vendors without the upstream/origin metadata.

## Issue Context
The repo uses `docs/skill-sources.md` as the single place to track skill provenance and re-sync procedure. New vendored skills should be added to the table.

## Fix Focus Areas
- docs/skill-sources.md[1-35]
- .claude/skills/outsource/SKILL.md[98-104]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

4. Prompt substitution rewrites arguments 🐞 Bug ≡ Correctness
Description
render_prompt() replaces $BASE after inserting $ARGUMENTS, so a user-supplied argument
containing the literal string $BASE will be rewritten to the base branch name, altering the
instruction content unexpectedly.
Code

.claude/skills/outsource/scripts/outsource.sh[R160-164]

Evidence
The renderer inserts user text at $ARGUMENTS and then performs a global $BASE replacement on the
entire result, which includes the inserted user text. The review prompt template shows $BASE is a
real token used in templates (so the substitution step exists and will run).

.claude/skills/outsource/scripts/outsource.sh[157-165]
.claude/skills/outsource/prompts/review.md[6-13]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The prompt renderer performs sequential string replacements: first `$ARGUMENTS`, then `$BASE`. If the user’s argument text contains the literal `$BASE`, it will be replaced during the second pass.

## Issue Context
The review prompt template legitimately uses `$BASE` for templating, but user-provided text should be treated as opaque and not subject to further substitutions.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[157-165]
- .claude/skills/outsource/prompts/review.md[6-13]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@sonarqubecloud

Copy link
Copy Markdown

Comment on lines +42 to +186
cat >&2 <<'EOF'
error: convertible CLI not found.
hint: install it with `uv tool install convertible-cli` (or `pipx install convertible-cli`),
or run from inside the convertible checkout with `uv` available.
https://github.com/agentculture/convertible
EOF
return 1
}

usage() {
cat <<'EOF'
outsource — hand a scoped repo task to convertible (a different engine/mind).

Usage:
outsource explore "<question or area>" Read-only investigation -> findings (no side effects)
outsource review "<what to focus on>" Diverse second-opinion on the committed diff (no side effects)
outsource write "<task>" [--pr] Implement a change (drive branch, or PR with --pr)

Options:
--repo PATH Target repo (default: .)
--base BRANCH Base for `review` diff (default: main)
--engine NAME Engine wheel (default: $CONVERTIBLE_ENGINE or vllm-openai)
--model NAME Model (default: $CONVERTIBLE_MODEL or mmangkad/Qwen3.6-27B-NVFP4)
--base-url URL OpenAI base URL (default: $CONVERTIBLE_BASE_URL or http://localhost:8001/v1)
--max-steps N Loop step budget (default: 20)
--timeout N Per-request timeout, seconds (default: $CONVERTIBLE_TIMEOUT or 300)
--allow-dirty (write) allow running on a dirty tree
--pr (write) push + open a PR instead of a local drive branch

explore/review run in a throwaway git worktree at HEAD — they cannot touch your
working tree or branch. review compares <base>...HEAD (committed changes only).
EOF
}

# ── parse the verb ──────────────────────────────────────────────────────────
VERB="${1:-}"
case "$VERB" in
explore | review | write) shift ;;
-h | --help) usage; exit 0 ;;
"") usage >&2; exit 2 ;;
*)
echo "error: unknown verb '$VERB' (expected explore|review|write)" >&2
echo "hint: run 'outsource --help'" >&2
exit 2
;;
esac

# Required external tools — fail fast with a clear message, not an opaque
# mid-run error, if the environment is missing one.
require_tools() {
local missing=() t
for t in python3 git grep mktemp; do
command -v "$t" >/dev/null 2>&1 || missing+=("$t")
done
if [[ ${#missing[@]} -gt 0 ]]; then
echo "error: missing required tool(s): ${missing[*]}" >&2
echo "hint: outsource needs python3, git, grep, and mktemp on PATH." >&2
exit 2
fi
}

# Guard a value-taking flag: a trailing flag with no value would otherwise
# dereference an unset $2 and abort under `set -u`.
need_value() { # $1 = remaining arg count ($#), $2 = flag name
[[ "$1" -ge 2 ]] || {
echo "error: $2 requires a value" >&2
echo "hint: run 'outsource --help'" >&2
exit 2
}
}

require_tools

# ── defaults + flag parsing ─────────────────────────────────────────────────
REPO="."
BASE="main"
ENGINE="${CONVERTIBLE_ENGINE:-vllm-openai}"
MODEL="${CONVERTIBLE_MODEL:-mmangkad/Qwen3.6-27B-NVFP4}"
BASE_URL="${CONVERTIBLE_BASE_URL:-http://localhost:8001/v1}"
MAX_STEPS=20
TIMEOUT="${CONVERTIBLE_TIMEOUT:-300}"
ALLOW_DIRTY=0
OPEN_PR=0
ARG=""

while [[ $# -gt 0 ]]; do
case "$1" in
--repo) need_value "$#" "$1"; REPO="$2"; shift 2 ;;
--base) need_value "$#" "$1"; BASE="$2"; shift 2 ;;
--engine) need_value "$#" "$1"; ENGINE="$2"; shift 2 ;;
--model) need_value "$#" "$1"; MODEL="$2"; shift 2 ;;
--base-url) need_value "$#" "$1"; BASE_URL="$2"; shift 2 ;;
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
--timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
--allow-dirty) ALLOW_DIRTY=1; shift ;;
--pr) OPEN_PR=1; shift ;;
-h | --help) usage; exit 0 ;;
--) shift; while [[ $# -gt 0 ]]; do ARG="${ARG:+$ARG }$1"; shift; done ;;
-*) echo "error: unknown option '$1'" >&2; echo "hint: run 'outsource --help'" >&2; exit 2 ;;
*) ARG="${ARG:+$ARG }$1"; shift ;;
esac
done

[[ -n "$ARG" ]] || { echo "error: $VERB needs a description argument" >&2; usage >&2; exit 2; }
[[ -d "$REPO" ]] || { echo "error: --repo is not a directory: $REPO" >&2; exit 2; }
REPO="$(cd "$REPO" && pwd)"

resolve_convertible || exit 2

# Per-request timeout is config (no drive flag); EngineConfig reads it from env.
# A local model can be slow on a growing context, so default generously.
export CONVERTIBLE_TIMEOUT="$TIMEOUT"
COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --max-steps "$MAX_STEPS" --json)

# ── render an instruction from a prompt template ────────────────────────────
render_prompt() {
local file="$PROMPTS_DIR/$1.md"
[[ -f "$file" ]] || { echo "error: missing prompt template: $file" >&2; exit 2; }
ARG="$ARG" BASE="$BASE" python3 - "$file" <<'PY'
import os, sys
tpl = open(sys.argv[1], encoding="utf-8").read()
sys.stdout.write(tpl.replace("$ARGUMENTS", os.environ["ARG"]).replace("$BASE", os.environ["BASE"]))
PY
}

# ── print the TaskResult that convertible emitted as JSON on stdout ─────────
# Reads JSON on stdin; prints a human/agent-readable digest; exits non-zero if
# the drive failed.
print_result() {
# NOTE: must be `python3 -c`, not `python3 - <<HEREDOC`: a heredoc becomes
# python's stdin (the script source), which would shadow the piped JSON and
# leave sys.stdin.read() empty. The script body uses no single quotes.
python3 -c '
import sys, json
raw = sys.stdin.read().strip()
if not raw:
sys.stderr.write("error: convertible produced no result on stdout (see diagnostics above)\n")
sys.exit(2)
try:
d = json.loads(raw)
except Exception:
sys.stderr.write("error: could not parse convertible --json output:\n")
sys.stderr.write(raw[:2000] + "\n")
sys.exit(2)
print("status:", d.get("status"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. outsource.sh error format violates 📘 Rule violation ✧ Quality

Several new error paths print messages that are not exactly two non-empty lines in the required
error:/hint: format, and some omit a hint: line entirely. This breaks the standardized CLI
error contract and reduces usability/scripting consistency.
Agent Prompt
## Issue description
CLI errors must be exactly two non-empty lines in text mode:
1) `error: <message>`
2) `hint: <remediation>`

The new `outsource.sh` script has multiple error sites that either (a) print more than two lines, or (b) print an `error:` without any `hint:`.

## Issue Context
Compliance rule requires a consistent, two-line remediation format for user-facing CLI failures.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[42-49]
- .claude/skills/outsource/scripts/outsource.sh[146-146]
- .claude/skills/outsource/scripts/outsource.sh[159-160]
- .claude/skills/outsource/scripts/outsource.sh[177-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +51 to +155
usage() {
cat <<'EOF'
outsource — hand a scoped repo task to convertible (a different engine/mind).

Usage:
outsource explore "<question or area>" Read-only investigation -> findings (no side effects)
outsource review "<what to focus on>" Diverse second-opinion on the committed diff (no side effects)
outsource write "<task>" [--pr] Implement a change (drive branch, or PR with --pr)

Options:
--repo PATH Target repo (default: .)
--base BRANCH Base for `review` diff (default: main)
--engine NAME Engine wheel (default: $CONVERTIBLE_ENGINE or vllm-openai)
--model NAME Model (default: $CONVERTIBLE_MODEL or mmangkad/Qwen3.6-27B-NVFP4)
--base-url URL OpenAI base URL (default: $CONVERTIBLE_BASE_URL or http://localhost:8001/v1)
--max-steps N Loop step budget (default: 20)
--timeout N Per-request timeout, seconds (default: $CONVERTIBLE_TIMEOUT or 300)
--allow-dirty (write) allow running on a dirty tree
--pr (write) push + open a PR instead of a local drive branch

explore/review run in a throwaway git worktree at HEAD — they cannot touch your
working tree or branch. review compares <base>...HEAD (committed changes only).
EOF
}

# ── parse the verb ──────────────────────────────────────────────────────────
VERB="${1:-}"
case "$VERB" in
explore | review | write) shift ;;
-h | --help) usage; exit 0 ;;
"") usage >&2; exit 2 ;;
*)
echo "error: unknown verb '$VERB' (expected explore|review|write)" >&2
echo "hint: run 'outsource --help'" >&2
exit 2
;;
esac

# Required external tools — fail fast with a clear message, not an opaque
# mid-run error, if the environment is missing one.
require_tools() {
local missing=() t
for t in python3 git grep mktemp; do
command -v "$t" >/dev/null 2>&1 || missing+=("$t")
done
if [[ ${#missing[@]} -gt 0 ]]; then
echo "error: missing required tool(s): ${missing[*]}" >&2
echo "hint: outsource needs python3, git, grep, and mktemp on PATH." >&2
exit 2
fi
}

# Guard a value-taking flag: a trailing flag with no value would otherwise
# dereference an unset $2 and abort under `set -u`.
need_value() { # $1 = remaining arg count ($#), $2 = flag name
[[ "$1" -ge 2 ]] || {
echo "error: $2 requires a value" >&2
echo "hint: run 'outsource --help'" >&2
exit 2
}
}

require_tools

# ── defaults + flag parsing ─────────────────────────────────────────────────
REPO="."
BASE="main"
ENGINE="${CONVERTIBLE_ENGINE:-vllm-openai}"
MODEL="${CONVERTIBLE_MODEL:-mmangkad/Qwen3.6-27B-NVFP4}"
BASE_URL="${CONVERTIBLE_BASE_URL:-http://localhost:8001/v1}"
MAX_STEPS=20
TIMEOUT="${CONVERTIBLE_TIMEOUT:-300}"
ALLOW_DIRTY=0
OPEN_PR=0
ARG=""

while [[ $# -gt 0 ]]; do
case "$1" in
--repo) need_value "$#" "$1"; REPO="$2"; shift 2 ;;
--base) need_value "$#" "$1"; BASE="$2"; shift 2 ;;
--engine) need_value "$#" "$1"; ENGINE="$2"; shift 2 ;;
--model) need_value "$#" "$1"; MODEL="$2"; shift 2 ;;
--base-url) need_value "$#" "$1"; BASE_URL="$2"; shift 2 ;;
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
--timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
--allow-dirty) ALLOW_DIRTY=1; shift ;;
--pr) OPEN_PR=1; shift ;;
-h | --help) usage; exit 0 ;;
--) shift; while [[ $# -gt 0 ]]; do ARG="${ARG:+$ARG }$1"; shift; done ;;
-*) echo "error: unknown option '$1'" >&2; echo "hint: run 'outsource --help'" >&2; exit 2 ;;
*) ARG="${ARG:+$ARG }$1"; shift ;;
esac
done

[[ -n "$ARG" ]] || { echo "error: $VERB needs a description argument" >&2; usage >&2; exit 2; }
[[ -d "$REPO" ]] || { echo "error: --repo is not a directory: $REPO" >&2; exit 2; }
REPO="$(cd "$REPO" && pwd)"

resolve_convertible || exit 2

# Per-request timeout is config (no drive flag); EngineConfig reads it from env.
# A local model can be slow on a growing context, so default generously.
export CONVERTIBLE_TIMEOUT="$TIMEOUT"
COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --max-steps "$MAX_STEPS" --json)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. outsource missing --json 📘 Rule violation ◔ Observability

The new outsource CLI does not accept a --json flag for structured output even though it
introduces new verbs (explore, review, write). This violates the requirement that CLI verbs
support --json with structured stdout output.
Agent Prompt
## Issue description
New/modified CLI verbs must support a `--json` flag and, when enabled, emit valid JSON to stdout (with errors to stderr).

The new `outsource` script adds/defines verbs but provides no `--json` flag in usage text or option parsing, and always prints a human-formatted digest.

## Issue Context
Compliance rule 847437 requires `--json` support for CLI verbs so callers can reliably parse outputs.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[51-74]
- .claude/skills/outsource/scripts/outsource.sh[127-143]
- .claude/skills/outsource/scripts/outsource.sh[167-198]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant