Skip to content

feat(skills): vendor outsource (explore/review/write), re-broadcast from convertible#51

Merged
OriNachum merged 2 commits into
mainfrom
feat/vendor-outsource-skill
May 31, 2026
Merged

feat(skills): vendor outsource (explore/review/write), re-broadcast from convertible#51
OriNachum merged 2 commits into
mainfrom
feat/vendor-outsource-skill

Conversation

@OriNachum
Copy link
Copy Markdown
Contributor

@OriNachum OriNachum commented May 31, 2026

Vendor the outsource skill (re-broadcast from convertible)

guildmaster is the mesh's skills supplier, and the transition rule is "onboard
as a consumer first — you can't credibly manage the skill stack until you run it
yourself."
We were missing outsource, so this vendors it in.

outsource hands a scoped repo task to
convertible — a different
engine/mind, not a stronger one; diversity is the point. Three verbs:

Verb What Side effects
explore "<area>" Read-only investigation → findings None (throwaway git worktree at HEAD)
review "<focus>" [--base main] Diverse second opinion on the committed diff — the headline verb None (throwaway worktree)
write "<task>" [--pr] Delegate a small implementation convertible/<id> drive branch (or PR)

What's in this PR

  • .claude/skills/outsource/ — 5 files copied from convertible (SKILL.md,
    scripts/outsource.sh, prompts/{explore,review,write}.md).
  • guild/skills/__init__.py — register outsource → agentculture/convertible
    in INBOUND_ORIGINS, so guild teach / onboard / overview attribute it to
    convertible and frame it as re-broadcast (same inbound pattern as the
    devague workflow trio).
  • docs/skill-sources.md — new "Inbound first-party skill (origin =
    convertible, re-broadcast by guildmaster)" section. Downstream is empty by
    design — guildmaster is the first holder outside convertible. Cross-links
    culture-agent-template#8.

Divergence from upstream (recorded in the ledger)

The upstream copy already carries type: command (load-bearing on the culture
backend), so no frontmatter change. The only edit is the SKILL.md
Provenance paragraph — upstream says "the inverse of the other skills … which
convertible vendors from guildmaster" (true in convertible's repo, misleading
here), reframed to "guildmaster re-broadcasts it." No script or prompt body is
touched.

Runtime dependency

The convertible CLI on PATH (uv tool install convertible-cli) plus a
reachable engine (override the local default via --engine / --model /
--base-url or CONVERTIBLE_*). Absent the CLI, the wrapper exits with a clear
install hint rather than crashing.

Verification

  • uv run pytest -n auto216 passed (the skills-convention dogfood test
    validates the new skill: name == dir, sibling scripts/).
  • black / isort / flake8 clean; markdownlint-cli2 → 0 errors.
  • bash .claude/skills/outsource/scripts/outsource.sh --help resolves the CLI;
    bad-verb guard exits non-zero with a hint.

Version: 0.8.5 → 0.9.0 (new capability).

  • guildmaster (Claude)

…rom convertible

guildmaster now runs the skill it will broadcast. Vendor convertible's
first-party `outsource` skill into .claude/skills/outsource/ — hand a scoped
repo task to a *different* engine/mind via explore (read-only), review (diverse
second opinion on the committed diff), and write (delegate to a drive branch/PR).

- Register origin in guild.skills.INBOUND_ORIGINS (agentculture/convertible) so
  teach/onboard/overview attribute + re-broadcast it like the devague trio.
- Add the "Inbound first-party skill" ledger section in docs/skill-sources.md
  (sole divergence: a reframed Provenance paragraph; type: command already
  present upstream). Cross-links culture-agent-template#8.
- bump 0.8.5 -> 0.9.0.

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 from convertible with explore/review/write verbs

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Vendor outsource skill from convertible with three verbs: explore (read-only investigation),
  review (diverse second opinion on diff), write (delegate implementation)
• Register outsource origin in INBOUND_ORIGINS to re-broadcast from convertible like devague trio
• Add "Inbound first-party skill" ledger section in docs/skill-sources.md documenting outsource and
  its runtime dependency
• Bump version 0.8.5 → 0.9.0 for new capability
Diagram
flowchart LR
  convertible["convertible<br/>(upstream origin)"]
  guildmaster["guildmaster<br/>(re-broadcaster)"]
  mesh["mesh agents<br/>(downstream)"]
  
  convertible -- "outsource skill<br/>(explore/review/write)" --> guildmaster
  guildmaster -- "re-broadcast via<br/>guild teach" --> mesh
  
  guildmaster -- "register in<br/>INBOUND_ORIGINS" --> registry["skill registry"]
  guildmaster -- "document in<br/>skill-sources.md" --> ledger["ledger"]

Loading

Grey Divider

File Changes

1. guild/skills/__init__.py ⚙️ Configuration changes +4/-2

Register outsource origin in INBOUND_ORIGINS

guild/skills/init.py


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

Portable wrapper script for convertible CLI integration

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


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

Skill metadata and documentation for outsource

.claude/skills/outsource/SKILL.md


View more (6)
4. .claude/skills/outsource/prompts/explore.md 📝 Documentation +20/-0

Prompt template for read-only investigation verb

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


5. .claude/skills/outsource/prompts/review.md 📝 Documentation +27/-0

Prompt template for diverse second-opinion verb

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


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

Prompt template for implementation delegation verb

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


7. CHANGELOG.md 📝 Documentation +29/-0

Document 0.9.0 release with outsource skill addition

CHANGELOG.md


8. docs/skill-sources.md 📝 Documentation +36/-0

Add inbound first-party skill ledger section for outsource

docs/skill-sources.md


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

Bump version to 0.9.0

pyproject.toml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 31, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (3)

Context used
✅ Compliance rules (platform): 48 rules

Grey Divider


Action required

1. outsource write lacks --apply 📘 Rule violation ☼ Reliability
Description
The write verb always runs convertible drive in-place and can create commits/branches or open
PRs without a dry-run default or an explicit --apply gate. This risks unintended state changes
from a default invocation path for a write-capable command.
Code

.claude/skills/outsource/scripts/outsource.sh[R237-253]

Evidence
Rule 749397 requires write-capable CLI operations to default to dry-run and only apply changes when
an explicit --apply is provided. The run_write path unconditionally invokes convertible drive
against --repo "$REPO" (in-place) and has no --apply flag in parsing/usage, so writes can occur
without an explicit apply gate.

Rule 749397: CLI write operations must default to dry-run and require explicit --apply
.claude/skills/outsource/scripts/outsource.sh[237-253]
.claude/skills/outsource/scripts/outsource.sh[115-147]

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 `outsource write` flow performs state-changing operations (creating commits/branches and optionally pushing/opening PRs) without defaulting to dry-run and without requiring an explicit `--apply` flag.

## Issue Context
Compliance requires CLI write/state-changing operations to default to dry-run and only perform writes when `--apply` is explicitly provided.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[51-74]
- .claude/skills/outsource/scripts/outsource.sh[115-155]
- .claude/skills/outsource/scripts/outsource.sh[237-253]

## Implementation notes
- Add a boolean `--apply` flag (default false).
- When `VERB=write` and `--apply` is NOT set, run the drive in an isolated temporary worktree (like `run_readonly`) and ensure all created branches are deleted in cleanup so no persistent state remains.
- When `--apply` IS set, keep the current in-place behavior (drive branch or PR). Ensure output clearly indicates `[DRY-RUN]` vs `[APPLY]`.

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


2. --repo allows external paths 📘 Rule violation ≡ Correctness
Description
The skill accepts an arbitrary --repo PATH and resolves it to an absolute path, allowing
operations to target directories outside the current repository. This violates the constraint that
skill scripts must not reference paths outside the repository.
Code

.claude/skills/outsource/scripts/outsource.sh[R115-147]

Evidence
Rule 749406 forbids skill scripts from referencing paths outside the repository. The script
explicitly accepts --repo and turns it into an absolute path (REPO="$(cd "$REPO" && pwd)"), then
uses git -C "$REPO" ..., enabling operations against arbitrary external directories.

Rule 749406: Skill scripts must not reference paths outside the repository or other skills
.claude/skills/outsource/scripts/outsource.sh[60-66]
.claude/skills/outsource/scripts/outsource.sh[127-147]

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 skill script allows `--repo PATH` to point anywhere on disk and then operates on that path. Compliance requires skill scripts not to reference paths outside the repository.

## Issue Context
The current implementation accepts `--repo`, checks it is a directory, then normalizes it with `cd`/`pwd`, and uses it for git/worktree operations.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[51-74]
- .claude/skills/outsource/scripts/outsource.sh[115-147]

## Implementation notes
- Remove `--repo` entirely and always operate on the current repo (e.g., `REPO=$(git rev-parse --show-toplevel)`), or
- Enforce that any provided `--repo` must equal the current repo root and reject other paths with a stderr error + usage.

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


3. Nonportable mktemp worktree 🐞 Bug ☼ Reliability
Description
outsource.sh creates the read-only worktree directory via mktemp -d without a template, which
can fail on non-GNU mktemp implementations and break outsource explore/review before the
worktree is created.
Code

.claude/skills/outsource/scripts/outsource.sh[R223-226]

Evidence
The script’s read-only path always uses mktemp -d to create the worktree directory, and the
skill/docs explicitly frame this wrapper as portable.

.claude/skills/outsource/scripts/outsource.sh[218-226]
.claude/skills/outsource/SKILL.md[24-38]
docs/skill-sources.md[105-111]

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 explore` / `outsource review` use `mktemp -d` without a template. Some `mktemp` implementations require a template, so these verbs can fail immediately, contradicting the skill’s stated portability.

## Issue Context
The skill describes itself as a “portable wrapper”, and `explore/review` rely on this temp directory to host a throwaway `git worktree`.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[218-226]

## Implementation notes
- Prefer a template-based call that works broadly, e.g.:
 - `_WT="$(mktemp -d "${TMPDIR:-/tmp}/outsource.XXXXXX")"`
- Optionally add a small fallback for platforms with different flags if you want extra robustness (but keep it minimal).

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



Remediation recommended

4. Failure output printed to stdout 📘 Rule violation ☼ Reliability
Description
print_result() prints status and summary to stdout even when the result indicates failure,
then exits non-zero. This mixes error/diagnostic content into stdout and makes it harder to script
reliably.
Code

.claude/skills/outsource/scripts/outsource.sh[R174-196]

Evidence
Rule 749409 requires error/diagnostic output to go to stderr. The embedded Python in
print_result() always uses print(...) (stdout) for status and summary and only switches exit
code based on status, so failure output is still emitted to stdout.

Rule 749409: Separate CLI standard output from error output
.claude/skills/outsource/scripts/outsource.sh[174-196]

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 result printer writes status/summary to stdout regardless of success/failure, which can pollute stdout for callers that expect stdout to be reserved for successful output.

## Issue Context
Compliance requires separating standard output from error output for CLI messages.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[170-197]

## Implementation notes
- If `d.get("status") != "ok"`, write status/summary to `sys.stderr` instead of stdout.
- Optionally keep stdout clean for successful runs, and reserve stderr for failure summaries/diagnostics.

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


5. Base ref prompt injection 🐞 Bug ⛨ Security
Description
--base is accepted without validation and interpolated directly into the review prompt’s suggested
git diff $BASE...HEAD commands, so a crafted base value can change the commands the outsourced
agent runs during review.
Code

.claude/skills/outsource/prompts/review.md[R8-12]

Evidence
BASE is taken directly from CLI flags and rendered into the prompt, and the review prompt uses it
unquoted in git diff command lines.

.claude/skills/outsource/scripts/outsource.sh[127-135]
.claude/skills/outsource/scripts/outsource.sh[157-164]
.claude/skills/outsource/prompts/review.md[8-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 `review` prompt embeds `$BASE` into shell command examples (`git diff $BASE...HEAD`). Because `BASE` comes from `--base` without validation, a value containing whitespace/newlines or extra tokens can alter what the outsourced agent executes.

## Issue Context
- `outsource.sh` parses `--base` into `BASE` and renders it into the prompt via `render_prompt()`.
- The prompt instructs the outsourced agent to run `git diff $BASE...HEAD`.

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

## Implementation notes
- Validate `BASE` (at least for `review`) before rendering:
 - Reject values containing whitespace/control characters.
 - Ensure it resolves to a commit: `git -C "$REPO" rev-parse --verify "${BASE}^{commit}"`.
- Also quote in the prompt template to reduce accidental tokenization:
 - `git diff "$BASE"...HEAD --stat`
 - `git diff "$BASE"...HEAD`

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



Advisory comments

6. Prompt replacement order bug 🐞 Bug ⚙ Maintainability
Description
render_prompt() replaces $ARGUMENTS and then $BASE, so if the user’s argument text contains
the literal string $BASE, it will be rewritten to the branch name and the prompt sent to
convertible drive will be unintentionally modified.
Code

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

Evidence
The Python templating code does $ARGUMENTS replacement before $BASE, and the review prompt
includes both placeholders.

.claude/skills/outsource/scripts/outsource.sh[157-164]
.claude/skills/outsource/prompts/review.md[6-12]

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

## Issue description
`render_prompt()` performs chained global replacements. Because it replaces `$ARGUMENTS` first and `$BASE` second, any literal `$BASE` substring inside the inserted arguments will be replaced too, altering the user’s requested focus text.

## Issue Context
This mainly affects the `review` prompt, which contains both `$ARGUMENTS` and `$BASE` placeholders.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[157-164]

## Implementation notes
- Minimal fix: replace `$BASE` first, then `$ARGUMENTS` last, so inserted argument text is not post-processed.
- Alternatively, switch to a safer templating approach that only substitutes placeholders in the template, not in inserted values.

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


Grey Divider

Qodo Logo

Comment thread .claude/skills/outsource/scripts/outsource.sh
Comment thread .claude/skills/outsource/scripts/outsource.sh
Comment thread .claude/skills/outsource/scripts/outsource.sh
The lint CI job markdownlint-cli2 "**/*.md" flagged outsource's
prompts/{explore,review,write}.md (MD041 no top-level heading, MD032 blanks
around lists). Those are raw LLM instruction templates fed verbatim to a model
(they open with prose and carry $PLACEHOLDER tokens), not hand-authored docs —
linting them as markdown is a category error, and editing them would fork the
cite-don't-import copy. Ignore .claude/skills/**/prompts/** instead, mirroring
how culture-agent-template already ignores .claude/skills/** in its config.

SKILL.md files stay linted (they are real docs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@OriNachum OriNachum deployed to testpypi May 31, 2026 10:06 — with GitHub Actions Active
@sonarqubecloud
Copy link
Copy Markdown

@OriNachum OriNachum merged commit be5964b into main May 31, 2026
8 checks passed
@OriNachum OriNachum deleted the feat/vendor-outsource-skill branch May 31, 2026 10:13
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