guild-cli 0.8.5__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. guild_cli-0.9.1/.claude/skills/outsource/SKILL.md +104 -0
  2. guild_cli-0.9.1/.claude/skills/outsource/prompts/explore.md +20 -0
  3. guild_cli-0.9.1/.claude/skills/outsource/prompts/review.md +27 -0
  4. guild_cli-0.9.1/.claude/skills/outsource/prompts/write.md +13 -0
  5. guild_cli-0.9.1/.claude/skills/outsource/scripts/outsource.sh +259 -0
  6. {guild_cli-0.8.5 → guild_cli-0.9.1}/.markdownlint-cli2.yaml +6 -0
  7. {guild_cli-0.8.5 → guild_cli-0.9.1}/CHANGELOG.md +48 -0
  8. {guild_cli-0.8.5 → guild_cli-0.9.1}/PKG-INFO +1 -1
  9. {guild_cli-0.8.5 → guild_cli-0.9.1}/docs/skill-sources.md +47 -11
  10. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/skills/__init__.py +4 -2
  11. {guild_cli-0.8.5 → guild_cli-0.9.1}/pyproject.toml +1 -1
  12. {guild_cli-0.8.5 → guild_cli-0.9.1}/uv.lock +1 -1
  13. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/agent-config/SKILL.md +0 -0
  14. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  15. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/agent-config/scripts/show.sh +0 -0
  16. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  17. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  18. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/SKILL.md +0 -0
  19. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  20. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  21. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  22. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  23. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  24. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/SKILL.md +0 -0
  25. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  26. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  27. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  28. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  29. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
  30. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  31. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  32. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  33. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/guild/SKILL.md +0 -0
  34. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/guild/scripts/configure-repo.sh +0 -0
  35. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/guild/scripts/create.sh +0 -0
  36. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/guild/scripts/overview.sh +0 -0
  37. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/onboard/SKILL.md +0 -0
  38. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/onboard/scripts/onboard.sh +0 -0
  39. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  40. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  41. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/run-tests/SKILL.md +0 -0
  42. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
  43. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/sonarclaude/SKILL.md +0 -0
  44. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  45. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  46. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  47. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/teach/SKILL.md +0 -0
  48. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/teach/scripts/teach.sh +0 -0
  49. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/think/SKILL.md +0 -0
  50. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/think/scripts/think.sh +0 -0
  51. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/version-bump/SKILL.md +0 -0
  52. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills/version-bump/scripts/bump.py +0 -0
  53. {guild_cli-0.8.5 → guild_cli-0.9.1}/.claude/skills.local.yaml.example +0 -0
  54. {guild_cli-0.8.5 → guild_cli-0.9.1}/.devague/frames/guildmaster-ships-teach-and-onboard-two-agent-firs.json +0 -0
  55. {guild_cli-0.8.5 → guild_cli-0.9.1}/.devague/plans/guildmaster-ships-teach-and-onboard-two-agent-firs.json +0 -0
  56. {guild_cli-0.8.5 → guild_cli-0.9.1}/.flake8 +0 -0
  57. {guild_cli-0.8.5 → guild_cli-0.9.1}/.github/workflows/publish.yml +0 -0
  58. {guild_cli-0.8.5 → guild_cli-0.9.1}/.github/workflows/tests.yml +0 -0
  59. {guild_cli-0.8.5 → guild_cli-0.9.1}/.gitignore +0 -0
  60. {guild_cli-0.8.5 → guild_cli-0.9.1}/CLAUDE.md +0 -0
  61. {guild_cli-0.8.5 → guild_cli-0.9.1}/LICENSE +0 -0
  62. {guild_cli-0.8.5 → guild_cli-0.9.1}/README.md +0 -0
  63. {guild_cli-0.8.5 → guild_cli-0.9.1}/culture.yaml +0 -0
  64. {guild_cli-0.8.5 → guild_cli-0.9.1}/docs/cutover.md +0 -0
  65. {guild_cli-0.8.5 → guild_cli-0.9.1}/docs/plans/2026-05-24-guildmaster-ships-teach-and-onboard-two-agent-firs.md +0 -0
  66. {guild_cli-0.8.5 → guild_cli-0.9.1}/docs/specs/2026-05-24-guildmaster-ships-teach-and-onboard-two-agent-firs.md +0 -0
  67. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/__init__.py +0 -0
  68. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/__main__.py +0 -0
  69. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/__init__.py +0 -0
  70. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/__init__.py +0 -0
  71. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/_broadcast.py +0 -0
  72. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/_provision_template.py +0 -0
  73. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/create.py +0 -0
  74. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/explain.py +0 -0
  75. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/learn.py +0 -0
  76. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/onboard.py +0 -0
  77. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/overview.py +0 -0
  78. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/show.py +0 -0
  79. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/teach.py +0 -0
  80. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_commands/whoami.py +0 -0
  81. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_errors.py +0 -0
  82. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_output.py +0 -0
  83. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/cli/_repo.py +0 -0
  84. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/scaffold/__init__.py +0 -0
  85. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/scaffold/instantiate.py +0 -0
  86. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/skills/identity.py +0 -0
  87. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/skills/ledger.py +0 -0
  88. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/skills/render.py +0 -0
  89. {guild_cli-0.8.5 → guild_cli-0.9.1}/guild/skills/sources.py +0 -0
  90. {guild_cli-0.8.5 → guild_cli-0.9.1}/sonar-project.properties +0 -0
  91. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/__init__.py +0 -0
  92. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_broadcast_post.py +0 -0
  93. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli.py +0 -0
  94. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_create.py +0 -0
  95. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_explain.py +0 -0
  96. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_learn.py +0 -0
  97. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_onboard.py +0 -0
  98. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_overview.py +0 -0
  99. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_show.py +0 -0
  100. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_teach.py +0 -0
  101. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_cli_whoami.py +0 -0
  102. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_scaffold_instantiate.py +0 -0
  103. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_skills_convention.py +0 -0
  104. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_skills_identity.py +0 -0
  105. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_skills_ledger.py +0 -0
  106. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_skills_render.py +0 -0
  107. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_skills_sources.py +0 -0
  108. {guild_cli-0.8.5 → guild_cli-0.9.1}/tests/test_version_fallback.py +0 -0
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: outsource
3
+ type: command
4
+ description: >
5
+ Hand a scoped repo task to convertible — a *different* engine/model than you
6
+ (e.g. a local vLLM Qwen) — and fold its answer back. The point isn't a stronger
7
+ model; it's a different mind, and diversity helps: `outsource review` gets an
8
+ independent second opinion on a diff, `outsource explore` gets a fresh read of
9
+ an area, `outsource write` delegates a small implementation. Use when the user
10
+ says "outsource this", "get a second opinion", "have convertible review/explore/
11
+ write", "ask the other model", or when you want a diverse perspective rather
12
+ than just doing it yourself. Read-only verbs (explore/review) run isolated in a
13
+ throwaway git worktree and cannot touch the working tree.
14
+ ---
15
+
16
+ # outsource — use convertible as a different mind
17
+
18
+ `outsource` drives the **`convertible`** CLI so a Claude agent can hand a scoped
19
+ task to a *different* engine (default: a local vLLM `Qwen3.6-27B` on
20
+ `:8001`). Convertible's model is **not** assumed to be stronger than you — its
21
+ value is **diversity**. A second, independent mind catches things the author's
22
+ mind glides past, which is why **review** is the headline verb.
23
+
24
+ This skill is the operator: a portable wrapper that resolves the CLI and turns
25
+ each verb into a `convertible drive`, then prints the drive's result summary.
26
+
27
+ ## How to run
28
+
29
+ The entry point is `scripts/outsource.sh`. Invoke it from the repo you want
30
+ convertible to work on:
31
+
32
+ ```bash
33
+ bash .claude/skills/outsource/scripts/outsource.sh <verb> "<text>" [options]
34
+ ```
35
+
36
+ It resolves the CLI portably — an installed `convertible` on `PATH` (the normal
37
+ case), falling back to `uv run convertible` when inside the convertible checkout,
38
+ else an install hint.
39
+
40
+ ### Verbs
41
+
42
+ | Verb | What it does | Side effects |
43
+ |------|--------------|--------------|
44
+ | `explore "<question or area>"` | Read-only investigation of the repo; the model reads and reports findings. | **None** — runs in a throwaway worktree at HEAD. |
45
+ | `review "<what to focus on>" [--base main]` | A diverse second opinion on the **committed** diff (`<base>...HEAD`). | **None** — throwaway worktree; reviews committed changes only. |
46
+ | `write "<task>" [--pr]` | Implement a change. Commits to a drive branch by default; `--pr` pushes + opens a PR. | In-place: a `convertible/<id>` drive branch (or a PR). |
47
+
48
+ ### Options
49
+
50
+ | Option | Meaning |
51
+ |--------|---------|
52
+ | `--repo PATH` | Target repo (default: `.`). |
53
+ | `--base BRANCH` | Base for the `review` diff (default: `main`). |
54
+ | `--engine NAME` | Engine wheel (default: `$CONVERTIBLE_ENGINE` or `vllm-openai`). |
55
+ | `--model NAME` | Model (default: `$CONVERTIBLE_MODEL` or `mmangkad/Qwen3.6-27B-NVFP4`). |
56
+ | `--base-url URL` | OpenAI base URL (default: `$CONVERTIBLE_BASE_URL` or `http://localhost:8001/v1`). |
57
+ | `--max-steps N` | Loop step budget (default: 20). |
58
+ | `--allow-dirty` | (`write`) allow running on a dirty tree. |
59
+ | `--pr` | (`write`) push + open a PR instead of a local drive branch. |
60
+
61
+ The result printed to stdout is the drive's `TaskResult.summary` (plus
62
+ `changed_files` / drive branch for `write`), parsed from `convertible drive
63
+ --json`. Per-step progress streams to stderr while it runs.
64
+
65
+ ## When to reach for which verb
66
+
67
+ - **review** — the standing use. You wrote (or an agent wrote) a change and you
68
+ want a candid, independent pass over the *committed* diff before you trust it.
69
+ Treat the output as a second opinion to weigh, not a verdict.
70
+ - **explore** — you want a fresh, unbiased read of an unfamiliar area ("how does
71
+ X work here?") without anchoring on your own assumptions.
72
+ - **write** — a small, well-scoped implementation you're happy to delegate. The
73
+ result lands on a drive branch you can inspect, merge, or discard.
74
+
75
+ ## Hard rules (do not violate)
76
+
77
+ - **explore and review are read-only.** They run in a throwaway `git worktree`
78
+ at HEAD, so a stray write can't reach your working tree or branch; the prompts
79
+ also tell the model not to modify anything. Don't route a change-making task
80
+ through them — use `write`.
81
+ - **`write` refuses a dirty tree** unless you pass `--allow-dirty`. This guards
82
+ the dirty-tree hazard: `convertible drive --no-pr` commits *uncommitted* edits
83
+ onto the drive branch and leaves you there. Commit or stash first.
84
+ - **Outsourced output is a second opinion, not authority.** The engine may be a
85
+ smaller/different model; weigh its findings, verify its claims, and own the
86
+ decision yourself.
87
+
88
+ ## Honest limits
89
+
90
+ - Read-only is enforced by **worktree isolation + prompt constraint**, not a
91
+ sandbox — the loop always exposes `write_file`/`run_command`, so the model can
92
+ still run arbitrary *read-only* commands.
93
+ - `review` covers **committed** changes only (`<base>...HEAD`). To review
94
+ uncommitted work, commit it first.
95
+ - The default engine is whatever single model is running locally; a multi-model
96
+ fleet (different model per verb) is separate infrastructure.
97
+
98
+ ## Provenance
99
+
100
+ This is a **first-party convertible** skill — `agentculture/convertible` is its
101
+ origin. guildmaster **re-broadcasts** it to the mesh (the same inbound pattern as
102
+ the devague-origin workflow skills), tracking it in `docs/skill-sources.md`. The
103
+ `cite, don't import` policy holds: downstream repos copy it, they don't symlink
104
+ or depend on it.
@@ -0,0 +1,20 @@
1
+ You are a second, independent mind brought in for a fresh read of this repository.
2
+ You are NOT the original author — your value is a different perspective, not authority.
3
+
4
+ Investigate the following and report what you find:
5
+
6
+ $ARGUMENTS
7
+
8
+ Rules:
9
+ - This is READ-ONLY. Use read_file, list_dir, and read-only run_command only
10
+ (e.g. `git log`, `git grep`, `ls`, `rg`). Do NOT create, modify, or delete any
11
+ file, and do NOT run any command that changes state.
12
+ - Be concrete: cite file paths and line numbers; quote the key code you rely on.
13
+ - Surface what's surprising, risky, or unclear — not just a tidy summary.
14
+ - You have a limited step budget. Read efficiently and call finish with your
15
+ report well before you run out — a focused finding beats endless reading.
16
+
17
+ When you are done, call finish with a structured findings report:
18
+ 1. What it is / how it works (with file:line references).
19
+ 2. Notable details, edge cases, or surprises.
20
+ 3. Open questions or risks worth a closer look.
@@ -0,0 +1,27 @@
1
+ You are an independent reviewer — a different mind from whoever wrote this change.
2
+ Your job is a candid second opinion, not a rubber stamp.
3
+
4
+ Focus the review on:
5
+
6
+ $ARGUMENTS
7
+
8
+ The change under review is the committed diff on this branch versus its base
9
+ (`$BASE`). Start by running, read-only:
10
+
11
+ git diff $BASE...HEAD --stat
12
+ git diff $BASE...HEAD
13
+
14
+ then read the touched files for the context you need.
15
+
16
+ Rules:
17
+ - READ-ONLY. Do NOT modify, create, or delete any file. Only read and run
18
+ read-only commands.
19
+ - Be terse and prioritized — lead with what actually matters. Don't pad.
20
+ - Call out real problems; if it's genuinely fine, say so and say why.
21
+ - You have a limited step budget. Read the diff efficiently and call finish with
22
+ your review well before you run out of steps.
23
+
24
+ When you are done, call finish with a structured review:
25
+ 1. Correctness risks / likely bugs (with file:line).
26
+ 2. Design, clarity, or maintainability concerns.
27
+ 3. Concrete, actionable suggestions (ranked; most important first).
@@ -0,0 +1,13 @@
1
+ Implement the following task in this repository:
2
+
3
+ $ARGUMENTS
4
+
5
+ Rules:
6
+ - Make the SMALLEST change that correctly satisfies the task.
7
+ - Follow the repository's existing patterns, style, and conventions — read the
8
+ neighbouring files first so your change reads like the surrounding code.
9
+ - You may read, create, modify files, and run commands as needed.
10
+ - Don't widen the scope: do exactly what was asked, nothing more.
11
+
12
+ When you are done, call finish with a short summary of exactly what you changed
13
+ and why.
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # outsource — hand a scoped repo task to convertible (a different engine/mind).
4
+ #
5
+ # Convertible's engine is not necessarily stronger than the calling agent; it is
6
+ # a *different* mind, and diversity helps — which is why `review` is the headline
7
+ # verb. Three verbs drive `convertible drive` and print the result:
8
+ #
9
+ # outsource explore "<question or area>" read-only investigation -> findings
10
+ # outsource review "<what to focus on>" diverse second-opinion on the diff
11
+ # outsource write "<task>" [--pr] implement a change
12
+ #
13
+ # explore/review run in a throwaway `git worktree` at HEAD, so they can never
14
+ # touch your working tree or branch (any stray write is discarded). write runs
15
+ # in-place and lands a drive branch (or a PR with --pr).
16
+ #
17
+ set -euo pipefail
18
+
19
+ SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
20
+ PROMPTS_DIR="$SKILL_DIR/prompts"
21
+
22
+ # ── resolve the convertible CLI (installed, then local-dev fallback) ─────────
23
+ CONVERTIBLE=()
24
+ resolve_convertible() {
25
+ if command -v convertible >/dev/null 2>&1; then
26
+ CONVERTIBLE=(convertible) # installed tool — the normal case
27
+ return 0
28
+ fi
29
+ # Local-dev fallback: inside the convertible checkout, run via uv.
30
+ local dir="$PWD"
31
+ while [[ -n "$dir" ]] && [[ "$dir" != "/" ]]; do
32
+ if [[ -f "$dir/pyproject.toml" ]] \
33
+ && grep -q '^name = "convertible-cli"' "$dir/pyproject.toml" 2>/dev/null; then
34
+ if command -v uv >/dev/null 2>&1; then
35
+ CONVERTIBLE=(uv run convertible)
36
+ return 0
37
+ fi
38
+ break
39
+ fi
40
+ dir=$(dirname "$dir")
41
+ done
42
+ cat >&2 <<'EOF'
43
+ error: convertible CLI not found.
44
+ hint: install it with `uv tool install convertible-cli` (or `pipx install convertible-cli`),
45
+ or run from inside the convertible checkout with `uv` available.
46
+ https://github.com/agentculture/convertible
47
+ EOF
48
+ return 1
49
+ }
50
+
51
+ usage() {
52
+ cat <<'EOF'
53
+ outsource — hand a scoped repo task to convertible (a different engine/mind).
54
+
55
+ Usage:
56
+ outsource explore "<question or area>" Read-only investigation -> findings (no side effects)
57
+ outsource review "<what to focus on>" Diverse second-opinion on the committed diff (no side effects)
58
+ outsource write "<task>" [--pr] Implement a change (drive branch, or PR with --pr)
59
+
60
+ Options:
61
+ --repo PATH Target repo (default: .)
62
+ --base BRANCH Base for `review` diff (default: main)
63
+ --engine NAME Engine wheel (default: $CONVERTIBLE_ENGINE or vllm-openai)
64
+ --model NAME Model (default: $CONVERTIBLE_MODEL or mmangkad/Qwen3.6-27B-NVFP4)
65
+ --base-url URL OpenAI base URL (default: $CONVERTIBLE_BASE_URL or http://localhost:8001/v1)
66
+ --max-steps N Loop step budget (default: 20)
67
+ --timeout N Per-request timeout, seconds (default: $CONVERTIBLE_TIMEOUT or 300)
68
+ --allow-dirty (write) allow running on a dirty tree
69
+ --pr (write) push + open a PR instead of a local drive branch
70
+
71
+ explore/review run in a throwaway git worktree at HEAD — they cannot touch your
72
+ working tree or branch. review compares <base>...HEAD (committed changes only).
73
+ EOF
74
+ }
75
+
76
+ # ── parse the verb ──────────────────────────────────────────────────────────
77
+ VERB="${1:-}"
78
+ case "$VERB" in
79
+ explore | review | write) shift ;;
80
+ -h | --help) usage; exit 0 ;;
81
+ "") usage >&2; exit 2 ;;
82
+ *)
83
+ echo "error: unknown verb '$VERB' (expected explore|review|write)" >&2
84
+ echo "hint: run 'outsource --help'" >&2
85
+ exit 2
86
+ ;;
87
+ esac
88
+
89
+ # Required external tools — fail fast with a clear message, not an opaque
90
+ # mid-run error, if the environment is missing one.
91
+ require_tools() {
92
+ local missing=() t
93
+ for t in python3 git grep mktemp; do
94
+ command -v "$t" >/dev/null 2>&1 || missing+=("$t")
95
+ done
96
+ if [[ ${#missing[@]} -gt 0 ]]; then
97
+ echo "error: missing required tool(s): ${missing[*]}" >&2
98
+ echo "hint: outsource needs python3, git, grep, and mktemp on PATH." >&2
99
+ exit 2
100
+ fi
101
+ }
102
+
103
+ # Guard a value-taking flag: a trailing flag with no value would otherwise
104
+ # dereference an unset $2 and abort under `set -u`.
105
+ need_value() { # $1 = remaining arg count ($#), $2 = flag name
106
+ [[ "$1" -ge 2 ]] || {
107
+ echo "error: $2 requires a value" >&2
108
+ echo "hint: run 'outsource --help'" >&2
109
+ exit 2
110
+ }
111
+ }
112
+
113
+ require_tools
114
+
115
+ # ── defaults + flag parsing ─────────────────────────────────────────────────
116
+ REPO="."
117
+ BASE="main"
118
+ ENGINE="${CONVERTIBLE_ENGINE:-vllm-openai}"
119
+ MODEL="${CONVERTIBLE_MODEL:-mmangkad/Qwen3.6-27B-NVFP4}"
120
+ BASE_URL="${CONVERTIBLE_BASE_URL:-http://localhost:8001/v1}"
121
+ MAX_STEPS=20
122
+ TIMEOUT="${CONVERTIBLE_TIMEOUT:-300}"
123
+ ALLOW_DIRTY=0
124
+ OPEN_PR=0
125
+ ARG=""
126
+
127
+ while [[ $# -gt 0 ]]; do
128
+ case "$1" in
129
+ --repo) need_value "$#" "$1"; REPO="$2"; shift 2 ;;
130
+ --base) need_value "$#" "$1"; BASE="$2"; shift 2 ;;
131
+ --engine) need_value "$#" "$1"; ENGINE="$2"; shift 2 ;;
132
+ --model) need_value "$#" "$1"; MODEL="$2"; shift 2 ;;
133
+ --base-url) need_value "$#" "$1"; BASE_URL="$2"; shift 2 ;;
134
+ --max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
135
+ --timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
136
+ --allow-dirty) ALLOW_DIRTY=1; shift ;;
137
+ --pr) OPEN_PR=1; shift ;;
138
+ -h | --help) usage; exit 0 ;;
139
+ --) shift; while [[ $# -gt 0 ]]; do ARG="${ARG:+$ARG }$1"; shift; done ;;
140
+ -*) echo "error: unknown option '$1'" >&2; echo "hint: run 'outsource --help'" >&2; exit 2 ;;
141
+ *) ARG="${ARG:+$ARG }$1"; shift ;;
142
+ esac
143
+ done
144
+
145
+ [[ -n "$ARG" ]] || { echo "error: $VERB needs a description argument" >&2; usage >&2; exit 2; }
146
+ [[ -d "$REPO" ]] || { echo "error: --repo is not a directory: $REPO" >&2; exit 2; }
147
+ REPO="$(cd "$REPO" && pwd)"
148
+
149
+ resolve_convertible || exit 2
150
+
151
+ # Per-request timeout is config (no drive flag); EngineConfig reads it from env.
152
+ # A local model can be slow on a growing context, so default generously.
153
+ export CONVERTIBLE_TIMEOUT="$TIMEOUT"
154
+ COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --max-steps "$MAX_STEPS" --json)
155
+
156
+ # ── render an instruction from a prompt template ────────────────────────────
157
+ render_prompt() {
158
+ local file="$PROMPTS_DIR/$1.md"
159
+ [[ -f "$file" ]] || { echo "error: missing prompt template: $file" >&2; exit 2; }
160
+ ARG="$ARG" BASE="$BASE" python3 - "$file" <<'PY'
161
+ import os, sys
162
+ tpl = open(sys.argv[1], encoding="utf-8").read()
163
+ sys.stdout.write(tpl.replace("$ARGUMENTS", os.environ["ARG"]).replace("$BASE", os.environ["BASE"]))
164
+ PY
165
+ }
166
+
167
+ # ── print the TaskResult that convertible emitted as JSON on stdout ─────────
168
+ # Reads JSON on stdin; prints a human/agent-readable digest; exits non-zero if
169
+ # the drive failed.
170
+ print_result() {
171
+ # NOTE: must be `python3 -c`, not `python3 - <<HEREDOC`: a heredoc becomes
172
+ # python's stdin (the script source), which would shadow the piped JSON and
173
+ # leave sys.stdin.read() empty. The script body uses no single quotes.
174
+ python3 -c '
175
+ import sys, json
176
+ raw = sys.stdin.read().strip()
177
+ if not raw:
178
+ sys.stderr.write("error: convertible produced no result on stdout (see diagnostics above)\n")
179
+ sys.exit(2)
180
+ try:
181
+ d = json.loads(raw)
182
+ except Exception:
183
+ sys.stderr.write("error: could not parse convertible --json output:\n")
184
+ sys.stderr.write(raw[:2000] + "\n")
185
+ sys.exit(2)
186
+ print("status:", d.get("status"))
187
+ print()
188
+ print((d.get("summary") or "").rstrip())
189
+ cf = d.get("changed_files") or []
190
+ if cf:
191
+ print("\nchanged files:", ", ".join(cf))
192
+ if d.get("branch"):
193
+ print("drive branch:", d["branch"])
194
+ if d.get("artifacts_path"):
195
+ print("artifact:", d["artifacts_path"])
196
+ sys.exit(0 if d.get("status") == "ok" else 1)
197
+ '
198
+ }
199
+
200
+ # ── read-only verbs: isolate the drive in a throwaway worktree at HEAD ──────
201
+ # Worktree state is module-global, not a function local: the EXIT trap fires
202
+ # *after* run_readonly returns, so under `set -u` a local would be unbound.
203
+ _WT=""
204
+ _DRIVE_BRANCH=""
205
+
206
+ _cleanup_worktree() {
207
+ [[ -n "$_WT" ]] || return 0
208
+ git -C "$REPO" worktree remove --force "$_WT" >/dev/null 2>&1 || true
209
+ rm -rf "$_WT" >/dev/null 2>&1 || true
210
+ # Only ever delete the ephemeral drive branch convertible names
211
+ # (convertible/<task_id>) — never an unrelated local branch, even if the
212
+ # JSON `branch` value were unexpected.
213
+ if [[ "$_DRIVE_BRANCH" == convertible/* ]]; then
214
+ git -C "$REPO" branch -D "$_DRIVE_BRANCH" >/dev/null 2>&1 || true
215
+ fi
216
+ }
217
+
218
+ run_readonly() {
219
+ local instruction="$1"
220
+ git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
221
+ || { echo "error: --repo is not a git repository: $REPO" >&2; exit 2; }
222
+
223
+ _WT="$(mktemp -d)"
224
+ trap _cleanup_worktree EXIT
225
+ git -C "$REPO" worktree add -q --detach "$_WT" HEAD
226
+
227
+ local out
228
+ out="$("${CONVERTIBLE[@]}" drive "$instruction" --repo "$_WT" --no-pr "${COMMON_FLAGS[@]}")" || true
229
+ _DRIVE_BRANCH="$(printf '%s' "$out" | python3 -c 'import sys, json
230
+ try:
231
+ print(json.load(sys.stdin).get("branch") or "")
232
+ except Exception:
233
+ print("")' 2>/dev/null || true)"
234
+ printf '%s' "$out" | print_result
235
+ }
236
+
237
+ # ── write verb: in-place drive (drive branch, or PR with --pr) ──────────────
238
+ run_write() {
239
+ local instruction="$1"
240
+ if [[ "$ALLOW_DIRTY" -eq 0 ]] \
241
+ && [[ -n "$(git -C "$REPO" status --porcelain 2>/dev/null)" ]]; then
242
+ echo "error: working tree is dirty — commit/stash first, or pass --allow-dirty" >&2
243
+ echo "hint: 'convertible drive --no-pr' commits uncommitted edits onto the drive branch" >&2
244
+ exit 2
245
+ fi
246
+ local out
247
+ if [[ "$OPEN_PR" -eq 1 ]]; then
248
+ out="$("${CONVERTIBLE[@]}" drive "$instruction" --repo "$REPO" "${COMMON_FLAGS[@]}")"
249
+ else
250
+ out="$("${CONVERTIBLE[@]}" drive "$instruction" --repo "$REPO" --no-pr "${COMMON_FLAGS[@]}")"
251
+ fi
252
+ printf '%s' "$out" | print_result
253
+ }
254
+
255
+ case "$VERB" in
256
+ explore) run_readonly "$(render_prompt explore)" ;;
257
+ review) run_readonly "$(render_prompt review)" ;;
258
+ write) run_write "$(render_prompt write)" ;;
259
+ esac
@@ -24,3 +24,9 @@ ignores:
24
24
  # devague working state (frames/plans are committed as JSON; reviews are
25
25
  # git-ignored) — not hand-authored prose.
26
26
  - ".devague/**"
27
+ # Vendored skill prompt templates (e.g. outsource's explore/review/write) are
28
+ # raw LLM instruction text fed verbatim to a model, not hand-authored docs —
29
+ # they intentionally open with prose, not an H1 (MD041), and carry $PLACEHOLDER
30
+ # tokens. Linting them as markdown is a category error, and editing them to
31
+ # satisfy a linter would fork the cited-verbatim copy (cite-don't-import).
32
+ - ".claude/skills/**/prompts/**"
@@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file.
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/). This project
6
6
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.9.1] - 2026-06-02
9
+
10
+ ### Added
11
+
12
+ - **Register `rtx-spark-cli` as a downstream consumer** in
13
+ `docs/skill-sources.md`. Provisioned via `guild create --apply`
14
+ (`agentculture/rtx-spark-cli` — agent/CLI for operating an NVIDIA RTX
15
+ workstation; sibling of `dgx-spark-cli`, command/pkg/dist all the repo-token
16
+ default `rtx-spark-cli`). Adds it to the downstream column of every canonical
17
+ skill (`agent-config`, `cicd`, `communicate`, `doc-test-alignment`,
18
+ `pypi-maintainer`, `run-tests`, `sonarclaude`, `version-bump`), the vendored
19
+ devague trio (`think`, `spec-to-plan`, `assign-to-workforce`), and
20
+ `outsource`. Build brief filed as
21
+ [`rtx-spark-cli#1`](https://github.com/agentculture/rtx-spark-cli/issues/1).
22
+
23
+ ### Changed
24
+
25
+ ### Fixed
26
+
27
+ ## [0.9.0] - 2026-05-31
28
+
29
+ ### Added
30
+
31
+ - **Vendor the `outsource` skill** (`.claude/skills/outsource/`) — guildmaster
32
+ now runs the skill it will broadcast. `outsource` hands a scoped repo task to
33
+ [`convertible`](https://github.com/agentculture/convertible) — a *different*
34
+ engine/mind, not a stronger one — via three verbs: `explore` (read-only
35
+ investigation), `review` (a diverse second opinion on the committed diff, the
36
+ headline verb), and `write` (delegate a small implementation to a drive branch
37
+ or PR). `explore`/`review` run isolated in a throwaway `git worktree` at HEAD;
38
+ `write` refuses a dirty tree unless `--allow-dirty`.
39
+ - **Register `outsource`'s origin** in `guild.skills.INBOUND_ORIGINS`
40
+ (`agentculture/convertible`) so `guild teach` / `onboard` / `overview` attribute
41
+ it to convertible and frame it as *re-broadcast*, the same inbound pattern as
42
+ the devague workflow trio.
43
+ - **Ledger:** new "Inbound first-party skill (origin = `convertible`,
44
+ re-broadcast by `guildmaster`)" section in `docs/skill-sources.md` recording
45
+ `outsource`, its sole divergence (a reframed Provenance paragraph; upstream
46
+ already carries `type: command`), and its runtime dependency on the
47
+ `convertible` CLI. Downstream is empty by design — guildmaster is the first
48
+ holder outside convertible. Cross-links
49
+ [`culture-agent-template#8`](https://github.com/agentculture/culture-agent-template/issues/8),
50
+ which proposes adding `outsource` to the clone template.
51
+
52
+ ### Changed
53
+
54
+ ### Fixed
55
+
8
56
  ## [0.8.5] - 2026-05-31
9
57
 
10
58
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: guild-cli
3
- Version: 0.8.5
3
+ Version: 0.9.1
4
4
  Summary: guildmaster — an agent and CLI that manages skills for the AgentCulture mesh.
5
5
  Project-URL: Homepage, https://github.com/agentculture/guildmaster
6
6
  Project-URL: Issues, https://github.com/agentculture/guildmaster/issues
@@ -32,14 +32,14 @@ current by `guild overview --scope mesh`.
32
32
 
33
33
  | Skill | Upstream | Downstream copies (known) | Notes |
34
34
  |-------|----------|---------------------------|-------|
35
- | `agent-config` | `guildmaster` (`.claude/skills/agent-config/`) | `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Inventory variant backing `guild show` ([#12](https://github.com/agentculture/guildmaster/issues/12)); `show.sh` + `data/backend-fingerprints.yaml` vendored verbatim from steward, SKILL.md reframed from alignment-judgment to inventory + `type: command` added. **Forked from steward:** steward retains its own alignment-focused `agent-config` variant; the inventory variant is guildmaster's to supply. |
36
- | `cicd` | `guildmaster` (`.claude/skills/cicd/`) — layered on `devex pr` (in `agentculture/devex`) | `afi-cli`, `devex` (adapted-thin delegate — owns `devex pr`; see [devex#53](https://github.com/agentculture/devex/pull/53)), `agtag`, `antoine`, `appsec`, `auntiepypi`, `cfafi` (still named `pr-review`), `code-lens-cli`, `culture` (still named `pr-review`), `devague`, `katvan`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `grant` (still named `pr-review`), `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Thin delegate to `devex pr` for lint / open / read / reply / delta, plus guildmaster's `status` (SonarCloud quality gate + hotspots + unresolved-thread tally) and `await` (composes `devex pr read --wait` with `status`, non-zero exit on Sonar ERROR / unresolved threads) extensions. **Inverted case:** devex, as the `devex pr` upstream, vendors the skill adapted-thin — a `workflow.sh`-only pure delegate ([devex#53](https://github.com/agentculture/devex/pull/53)). Renamed from `pr-review` in steward 0.7.0; downstream copies may keep the old name on their own cadence. |
37
- | `communicate` | `guildmaster` (`.claude/skills/communicate/`) | `afi-cli`, `devex` (identifier-only — vendored steward 0.11.0; scripts current as of 0.18.0), `agtag`, `antoine`, `appsec`, `auntiepypi`, `code-lens-cli`, `culture` (still named `coordinate`), `devague`, `katvan`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Cross-repo + mesh communication: file issues / hand off briefs to sibling-repo agents (auto-signed), comment on existing issues, fetch issues to inline state into briefs, and send live messages to Culture mesh channels (unsigned — nick is the speaker). Renamed from `coordinate` in steward 0.8.0; absorbed `gh-issues` (as `fetch-issues.sh`) in 0.9.1. Issue I/O backed by `agtag` (>=0.1) since steward 0.11.0 — signature resolves from local `culture.yaml` (override via `--as`). |
38
- | `doc-test-alignment` | `guildmaster` (`.claude/skills/doc-test-alignment/`) | `devague`, `lecodeur`, `lepenseur`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Stub; real implementation TBD. `scripts/check.sh` exits not-yet-implemented today. |
39
- | `pypi-maintainer` | `guildmaster` (`.claude/skills/pypi-maintainer/`) | `agtag`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Switches a PyPI package install between pypi / test-pypi / local. Generalised from the original culture-specific `change-package`. |
40
- | `run-tests` | `guildmaster` (`.claude/skills/run-tests/`) | `agtag`, `antoine`, `appsec`, `code-lens-cli`, `culture`, `culture-sonar-cli`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `grant`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Coverage source resolves from `[tool.coverage.run]` in `pyproject.toml`, so the script is portable across siblings without modification. |
41
- | `sonarclaude` | `guildmaster` (`.claude/skills/sonarclaude/`) | `antoine`, `appsec`, `code-lens-cli`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | SonarCloud API client. Project key resolves from `$SONAR_PROJECT` or `--project KEY`. |
42
- | `version-bump` | `guildmaster` (`.claude/skills/version-bump/`) | `afi-cli`, `agtag`, `antoine`, `appsec`, `auntiepypi`, `cfafi`, `code-lens-cli`, `culture`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `grant`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Pure Python, prepends a Keep-a-Changelog entry; no per-repo customization needed. |
35
+ | `agent-config` | `guildmaster` (`.claude/skills/agent-config/`) | `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Inventory variant backing `guild show` ([#12](https://github.com/agentculture/guildmaster/issues/12)); `show.sh` + `data/backend-fingerprints.yaml` vendored verbatim from steward, SKILL.md reframed from alignment-judgment to inventory + `type: command` added. **Forked from steward:** steward retains its own alignment-focused `agent-config` variant; the inventory variant is guildmaster's to supply. |
36
+ | `cicd` | `guildmaster` (`.claude/skills/cicd/`) — layered on `devex pr` (in `agentculture/devex`) | `afi-cli`, `devex` (adapted-thin delegate — owns `devex pr`; see [devex#53](https://github.com/agentculture/devex/pull/53)), `agtag`, `antoine`, `appsec`, `auntiepypi`, `cfafi` (still named `pr-review`), `code-lens-cli`, `culture` (still named `pr-review`), `devague`, `katvan`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `grant` (still named `pr-review`), `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Thin delegate to `devex pr` for lint / open / read / reply / delta, plus guildmaster's `status` (SonarCloud quality gate + hotspots + unresolved-thread tally) and `await` (composes `devex pr read --wait` with `status`, non-zero exit on Sonar ERROR / unresolved threads) extensions. **Inverted case:** devex, as the `devex pr` upstream, vendors the skill adapted-thin — a `workflow.sh`-only pure delegate ([devex#53](https://github.com/agentculture/devex/pull/53)). Renamed from `pr-review` in steward 0.7.0; downstream copies may keep the old name on their own cadence. |
37
+ | `communicate` | `guildmaster` (`.claude/skills/communicate/`) | `afi-cli`, `devex` (identifier-only — vendored steward 0.11.0; scripts current as of 0.18.0), `agtag`, `antoine`, `appsec`, `auntiepypi`, `code-lens-cli`, `culture` (still named `coordinate`), `devague`, `katvan`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Cross-repo + mesh communication: file issues / hand off briefs to sibling-repo agents (auto-signed), comment on existing issues, fetch issues to inline state into briefs, and send live messages to Culture mesh channels (unsigned — nick is the speaker). Renamed from `coordinate` in steward 0.8.0; absorbed `gh-issues` (as `fetch-issues.sh`) in 0.9.1. Issue I/O backed by `agtag` (>=0.1) since steward 0.11.0 — signature resolves from local `culture.yaml` (override via `--as`). |
38
+ | `doc-test-alignment` | `guildmaster` (`.claude/skills/doc-test-alignment/`) | `devague`, `lecodeur`, `lepenseur`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Stub; real implementation TBD. `scripts/check.sh` exits not-yet-implemented today. |
39
+ | `pypi-maintainer` | `guildmaster` (`.claude/skills/pypi-maintainer/`) | `agtag`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Switches a PyPI package install between pypi / test-pypi / local. Generalised from the original culture-specific `change-package`. |
40
+ | `run-tests` | `guildmaster` (`.claude/skills/run-tests/`) | `agtag`, `antoine`, `appsec`, `code-lens-cli`, `culture`, `culture-sonar-cli`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `grant`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Coverage source resolves from `[tool.coverage.run]` in `pyproject.toml`, so the script is portable across siblings without modification. |
41
+ | `sonarclaude` | `guildmaster` (`.claude/skills/sonarclaude/`) | `antoine`, `appsec`, `code-lens-cli`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | SonarCloud API client. Project key resolves from `$SONAR_PROJECT` or `--project KEY`. |
42
+ | `version-bump` | `guildmaster` (`.claude/skills/version-bump/`) | `afi-cli`, `agtag`, `antoine`, `appsec`, `auntiepypi`, `cfafi`, `code-lens-cli`, `culture`, `devague`, `lecodeur`, `lepenseur`, `seer-cli`, `grant`, `telek`, `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Pure Python, prepends a Keep-a-Changelog entry; no per-repo customization needed. |
43
43
 
44
44
  > **How the downstream column is maintained.** The "Downstream copies (known)"
45
45
  > entries are kept in sync with guildmaster's own drift detector:
@@ -86,14 +86,50 @@ harmless on `claude-code`. This is the only divergence from upstream.
86
86
 
87
87
  | Skill | Origin | Downstream copies (known) | Notes |
88
88
  |-------|--------|---------------------------|-------|
89
- | `think` | `devague` (`agentculture/devague`, `../devague/.claude/skills/think/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Operator for the **idea→spec** leg (announcement frame → capture/classify claims → interrogate with honesty conditions → park open vagueness → `export` once the frame converges). Renamed from `devague` in devague 0.4.0. **Divergence:** `type: command` added. Runtime dep: `uv tool install devague`. |
90
- | `spec-to-plan` | `devague` (`agentculture/devague`, `../devague/.claude/skills/spec-to-plan/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Operator for the **spec→plan** leg (`devague plan ...`): seed from a converged frame, cover every coverage target with acceptance-gated, acyclically-ordered tasks, park unknowns as risks, `export` once the plan converges. New in devague 0.4.0. **Divergence:** `type: command` added. Runtime dep: `uv tool install devague`. |
91
- | `assign-to-workforce` | `devague` (`agentculture/devague`, `../devague/.claude/skills/assign-to-workforce/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist` | Operator for the **implementation** leg: reads `devague plan waves` (read-only) and fans out independent tasks to one agent per task per wave in isolated git worktrees, with main-agent TDD-gated merges. Three human gates: spec / split plan / final PR. The CLI stays non-orchestrating ([devague#20](https://github.com/agentculture/devague/issues/20)). New in devague 0.10.0. **Divergence:** `type: command` added. Runtime deps: `uv tool install devague`, `git worktree`, the vendored `cicd` skill (for gate-3 `devex pr open`). |
89
+ | `think` | `devague` (`agentculture/devague`, `../devague/.claude/skills/think/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Operator for the **idea→spec** leg (announcement frame → capture/classify claims → interrogate with honesty conditions → park open vagueness → `export` once the frame converges). Renamed from `devague` in devague 0.4.0. **Divergence:** `type: command` added. Runtime dep: `uv tool install devague`. |
90
+ | `spec-to-plan` | `devague` (`agentculture/devague`, `../devague/.claude/skills/spec-to-plan/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Operator for the **spec→plan** leg (`devague plan ...`): seed from a converged frame, cover every coverage target with acceptance-gated, acyclically-ordered tasks, park unknowns as risks, `export` once the plan converges. New in devague 0.4.0. **Divergence:** `type: command` added. Runtime dep: `uv tool install devague`. |
91
+ | `assign-to-workforce` | `devague` (`agentculture/devague`, `../devague/.claude/skills/assign-to-workforce/`) | — (broadcast pending), `agenda`, `dominion-breaker`, `convertible`, `jetson`, `reachy-mini-cli`, `jetson-ai-lab-cli`, `dgx-spark-cli`, `unsloth-cli`, `discord-bot-cli`, `arxivist`, `rtx-spark-cli` | Operator for the **implementation** leg: reads `devague plan waves` (read-only) and fans out independent tasks to one agent per task per wave in isolated git worktrees, with main-agent TDD-gated merges. Three human gates: spec / split plan / final PR. The CLI stays non-orchestrating ([devague#20](https://github.com/agentculture/devague/issues/20)). New in devague 0.10.0. **Divergence:** `type: command` added. Runtime deps: `uv tool install devague`, `git worktree`, the vendored `cicd` skill (for gate-3 `devex pr open`). |
92
92
 
93
93
  Downstream is empty by design: these are still being introduced to the mesh.
94
94
  `guild teach --new --skill <name> --to <repos>` frames them as *new* skills to
95
95
  add fresh (not stale copies to resync).
96
96
 
97
+ ## Inbound first-party skill (origin = `convertible`, re-broadcast by `guildmaster`)
98
+
99
+ `outsource` flows the **same opposite direction** as the devague trio above: a
100
+ sibling, [`convertible`](https://github.com/agentculture/convertible), is its
101
+ author/upstream; guildmaster pulls it from convertible and re-broadcasts it to
102
+ the mesh. `cite, don't import` still applies — re-sync, when it later changes
103
+ upstream, from `../convertible/.claude/skills/outsource/`.
104
+
105
+ Where the devague skills drive a deterministic CLI, `outsource` is a portable
106
+ wrapper (`scripts/outsource.sh`) that drives the **`convertible` CLI** so a
107
+ Claude agent can hand a scoped task to a *different* engine/mind (default: a
108
+ local vLLM `Qwen3.6-27B`) — `explore` (read-only investigation), `review` (a
109
+ diverse second opinion on the committed diff, the headline verb), and `write`
110
+ (delegate a small implementation to a drive branch / PR). `explore`/`review` run
111
+ isolated in a throwaway `git worktree` at HEAD; `write` refuses a dirty tree.
112
+
113
+ **Divergence from verbatim.** The upstream copy already carries `type: command`
114
+ (load-bearing on the culture backend), so no frontmatter change was needed. The
115
+ **only** edit is the SKILL.md *Provenance* paragraph: upstream says "the inverse
116
+ of the other skills … which convertible vendors *from* guildmaster" — true in
117
+ convertible's repo, misleading here — reframed to "guildmaster re-broadcasts it
118
+ … tracking it in `docs/skill-sources.md`." No script or prompt body is edited.
119
+
120
+ **Runtime dependency:** the `convertible` CLI on `PATH`
121
+ (`uv tool install convertible-cli`) plus a reachable engine (override the local
122
+ default via `--engine` / `--model` / `--base-url` or `CONVERTIBLE_*` env). Absent
123
+ the CLI, the wrapper exits with a clear install hint rather than crashing.
124
+
125
+ | Skill | Origin | Downstream copies (known) | Notes |
126
+ |-------|--------|---------------------------|-------|
127
+ | `outsource` | `convertible` (`agentculture/convertible`, `../convertible/.claude/skills/outsource/`) | — (broadcast pending; [`culture-agent-template#8`](https://github.com/agentculture/culture-agent-template/issues/8) proposes adding it to the clone template), `rtx-spark-cli` | First-party convertible skill: hand a scoped task to a *different* engine/mind. Verbs `explore` / `review` / `write`. **Divergence:** Provenance paragraph reframed for re-broadcast (above); `type: command` already present upstream. Runtime dep: `uv tool install convertible-cli` + a reachable engine. |
128
+
129
+ Downstream is empty by design — guildmaster is the first holder outside
130
+ convertible. `guild teach --new --skill outsource --to <repos>` frames it as a
131
+ *new* skill when broadcasting.
132
+
97
133
  ## guildmaster-origin skills (origin = `guildmaster`)
98
134
 
99
135
  These are guildmaster's **own** operator skills — not vendored from anyone and
@@ -15,12 +15,14 @@ from __future__ import annotations
15
15
 
16
16
  # Skills whose origin is a *sibling* (not guildmaster): re-broadcasting them
17
17
  # carries an origin-attribution block so consumers know guildmaster only
18
- # re-broadcasts. Mirrors the "Inbound workflow skills" section of
19
- # ``docs/skill-sources.md`` (the devague trio).
18
+ # re-broadcasts. Mirrors the "Inbound workflow skills" + "Inbound first-party"
19
+ # sections of ``docs/skill-sources.md`` (the devague trio; convertible's
20
+ # ``outsource``).
20
21
  INBOUND_ORIGINS: dict[str, str] = {
21
22
  "think": "agentculture/devague",
22
23
  "spec-to-plan": "agentculture/devague",
23
24
  "assign-to-workforce": "agentculture/devague",
25
+ "outsource": "agentculture/convertible",
24
26
  }
25
27
 
26
28
  # guildmaster's own skills — present in ``.claude/skills/`` but NOT part of the
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "guild-cli"
3
- version = "0.8.5"
3
+ version = "0.9.1"
4
4
  description = "guildmaster — an agent and CLI that manages skills for the AgentCulture mesh."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -179,7 +179,7 @@ wheels = [
179
179
 
180
180
  [[package]]
181
181
  name = "guild-cli"
182
- version = "0.8.5"
182
+ version = "0.9.1"
183
183
  source = { editable = "." }
184
184
  dependencies = [
185
185
  { name = "pyyaml" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes