devague 0.12.0__tar.gz → 0.14.0__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 (146) hide show
  1. devague-0.14.0/.claude/skills/agent-config/SKILL.md +82 -0
  2. devague-0.14.0/.claude/skills/agent-config/data/backend-fingerprints.yaml +30 -0
  3. devague-0.14.0/.claude/skills/agent-config/scripts/show.sh +136 -0
  4. {devague-0.12.0 → devague-0.14.0}/.claude/skills/assign-to-workforce/SKILL.md +6 -5
  5. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/SKILL.md +37 -8
  6. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/scripts/portability-lint.sh +2 -2
  7. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/SKILL.md +4 -4
  8. devague-0.14.0/.claude/skills/communicate/scripts/templates/skill-new-brief.md +85 -0
  9. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +13 -13
  10. devague-0.14.0/.claude/skills/pypi-maintainer/SKILL.md +75 -0
  11. devague-0.14.0/.claude/skills/pypi-maintainer/scripts/switch-source.sh +102 -0
  12. devague-0.14.0/.claude/skills/recall/SKILL.md +181 -0
  13. devague-0.14.0/.claude/skills/recall/scripts/recall.sh +141 -0
  14. devague-0.14.0/.claude/skills/remember/SKILL.md +118 -0
  15. devague-0.14.0/.claude/skills/remember/scripts/remember.sh +138 -0
  16. {devague-0.12.0 → devague-0.14.0}/.claude/skills/spec-to-plan/SKILL.md +5 -4
  17. {devague-0.12.0 → devague-0.14.0}/.claude/skills/think/SKILL.md +5 -3
  18. {devague-0.12.0 → devague-0.14.0}/CHANGELOG.md +35 -0
  19. {devague-0.12.0 → devague-0.14.0}/CLAUDE.md +19 -4
  20. {devague-0.12.0 → devague-0.14.0}/PKG-INFO +1 -1
  21. devague-0.14.0/docs/skill-sources.md +74 -0
  22. {devague-0.12.0 → devague-0.14.0}/docs/skills.md +1 -1
  23. {devague-0.12.0 → devague-0.14.0}/pyproject.toml +1 -1
  24. {devague-0.12.0 → devague-0.14.0}/uv.lock +1 -1
  25. devague-0.12.0/docs/skill-sources.md +0 -55
  26. {devague-0.12.0 → devague-0.14.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  27. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  28. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  29. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  30. {devague-0.12.0 → devague-0.14.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  31. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  32. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  33. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  34. {devague-0.12.0 → devague-0.14.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  35. {devague-0.12.0 → devague-0.14.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  36. {devague-0.12.0 → devague-0.14.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  37. {devague-0.12.0 → devague-0.14.0}/.claude/skills/run-tests/SKILL.md +0 -0
  38. {devague-0.12.0 → devague-0.14.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  39. {devague-0.12.0 → devague-0.14.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  40. {devague-0.12.0 → devague-0.14.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  41. {devague-0.12.0 → devague-0.14.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  42. {devague-0.12.0 → devague-0.14.0}/.claude/skills/think/scripts/think.sh +0 -0
  43. {devague-0.12.0 → devague-0.14.0}/.claude/skills/version-bump/SKILL.md +0 -0
  44. {devague-0.12.0 → devague-0.14.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  45. {devague-0.12.0 → devague-0.14.0}/.claude/skills.local.yaml.example +0 -0
  46. {devague-0.12.0 → devague-0.14.0}/.devague/current_plan +0 -0
  47. {devague-0.12.0 → devague-0.14.0}/.devague/frames/devague-0-6-0-ships-the-human-review-loop-devague.json +0 -0
  48. {devague-0.12.0 → devague-0.14.0}/.devague/frames/devague-now-ships-a-documented-spec-contract-every.json +0 -0
  49. {devague-0.12.0 → devague-0.14.0}/.devague/frames/devague-turns-a-converged-plan-into-parallel-simpl.json +0 -0
  50. {devague-0.12.0 → devague-0.14.0}/.devague/plans/devague-0-6-0-ships-the-human-review-loop-devague.json +0 -0
  51. {devague-0.12.0 → devague-0.14.0}/.devague/plans/devague-now-ships-a-documented-spec-contract-every.json +0 -0
  52. {devague-0.12.0 → devague-0.14.0}/.devague/plans/devague-turns-a-converged-plan-into-parallel-simpl.json +0 -0
  53. {devague-0.12.0 → devague-0.14.0}/.flake8 +0 -0
  54. {devague-0.12.0 → devague-0.14.0}/.github/workflows/publish.yml +0 -0
  55. {devague-0.12.0 → devague-0.14.0}/.github/workflows/security-checks.yml +0 -0
  56. {devague-0.12.0 → devague-0.14.0}/.github/workflows/tests.yml +0 -0
  57. {devague-0.12.0 → devague-0.14.0}/.gitignore +0 -0
  58. {devague-0.12.0 → devague-0.14.0}/.markdownlint-cli2.yaml +0 -0
  59. {devague-0.12.0 → devague-0.14.0}/.pre-commit-config.yaml +0 -0
  60. {devague-0.12.0 → devague-0.14.0}/LICENSE +0 -0
  61. {devague-0.12.0 → devague-0.14.0}/README.md +0 -0
  62. {devague-0.12.0 → devague-0.14.0}/culture.yaml +0 -0
  63. {devague-0.12.0 → devague-0.14.0}/devague/__init__.py +0 -0
  64. {devague-0.12.0 → devague-0.14.0}/devague/__main__.py +0 -0
  65. {devague-0.12.0 → devague-0.14.0}/devague/cli/__init__.py +0 -0
  66. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/__init__.py +0 -0
  67. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/capture.py +0 -0
  68. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/confirm.py +0 -0
  69. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/converge.py +0 -0
  70. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/explain.py +0 -0
  71. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/export.py +0 -0
  72. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/interrogate.py +0 -0
  73. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/learn.py +0 -0
  74. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/list_frames.py +0 -0
  75. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/new.py +0 -0
  76. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/park.py +0 -0
  77. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/plan.py +0 -0
  78. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/question.py +0 -0
  79. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/reject.py +0 -0
  80. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/review.py +0 -0
  81. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/show.py +0 -0
  82. {devague-0.12.0 → devague-0.14.0}/devague/cli/_commands/status.py +0 -0
  83. {devague-0.12.0 → devague-0.14.0}/devague/cli/_errors.py +0 -0
  84. {devague-0.12.0 → devague-0.14.0}/devague/cli/_frames.py +0 -0
  85. {devague-0.12.0 → devague-0.14.0}/devague/cli/_output.py +0 -0
  86. {devague-0.12.0 → devague-0.14.0}/devague/cli/_paths.py +0 -0
  87. {devague-0.12.0 → devague-0.14.0}/devague/cli/_plans.py +0 -0
  88. {devague-0.12.0 → devague-0.14.0}/devague/cli/_status.py +0 -0
  89. {devague-0.12.0 → devague-0.14.0}/devague/convergence.py +0 -0
  90. {devague-0.12.0 → devague-0.14.0}/devague/frame.py +0 -0
  91. {devague-0.12.0 → devague-0.14.0}/devague/plan.py +0 -0
  92. {devague-0.12.0 → devague-0.14.0}/devague/plan_convergence.py +0 -0
  93. {devague-0.12.0 → devague-0.14.0}/devague/plan_store.py +0 -0
  94. {devague-0.12.0 → devague-0.14.0}/devague/questions_io.py +0 -0
  95. {devague-0.12.0 → devague-0.14.0}/devague/render/__init__.py +0 -0
  96. {devague-0.12.0 → devague-0.14.0}/devague/render/frame_md.py +0 -0
  97. {devague-0.12.0 → devague-0.14.0}/devague/render/plan_md.py +0 -0
  98. {devague-0.12.0 → devague-0.14.0}/devague/render/review_md.py +0 -0
  99. {devague-0.12.0 → devague-0.14.0}/devague/render/spec_md.py +0 -0
  100. {devague-0.12.0 → devague-0.14.0}/devague/store.py +0 -0
  101. {devague-0.12.0 → devague-0.14.0}/docs/assign-to-workforce-worked-example.md +0 -0
  102. {devague-0.12.0 → devague-0.14.0}/docs/examples/contract-example.json +0 -0
  103. {devague-0.12.0 → devague-0.14.0}/docs/llm-guidance.md +0 -0
  104. {devague-0.12.0 → devague-0.14.0}/docs/plans/2026-05-23-devague-0-6-0-ships-the-human-review-loop-devague.md +0 -0
  105. {devague-0.12.0 → devague-0.14.0}/docs/plans/2026-05-23-devague-now-ships-a-documented-spec-contract-every.md +0 -0
  106. {devague-0.12.0 → devague-0.14.0}/docs/plans/2026-05-23-devague-turns-a-converged-plan-into-parallel-simpl.md +0 -0
  107. {devague-0.12.0 → devague-0.14.0}/docs/reviews/spec-contract-frame-review.md +0 -0
  108. {devague-0.12.0 → devague-0.14.0}/docs/spec-contract.md +0 -0
  109. {devague-0.12.0 → devague-0.14.0}/docs/specs/2026-05-23-devague-0-6-0-ships-the-human-review-loop-devague.md +0 -0
  110. {devague-0.12.0 → devague-0.14.0}/docs/specs/2026-05-23-devague-now-ships-a-documented-spec-contract-every.md +0 -0
  111. {devague-0.12.0 → devague-0.14.0}/docs/specs/2026-05-23-devague-turns-a-converged-plan-into-parallel-simpl.md +0 -0
  112. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/plans/2026-05-22-specifix-onboarding.md +0 -0
  113. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/plans/2026-05-23-devague-rename.md +0 -0
  114. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/plans/2026-05-23-devague-working-backwards-engine.md +0 -0
  115. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/specs/2026-05-22-specifix-onboarding-design.md +0 -0
  116. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md +0 -0
  117. {devague-0.12.0 → devague-0.14.0}/docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md +0 -0
  118. {devague-0.12.0 → devague-0.14.0}/sonar-project.properties +0 -0
  119. {devague-0.12.0 → devague-0.14.0}/tests/__init__.py +0 -0
  120. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_affordances.py +0 -0
  121. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_chassis.py +0 -0
  122. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_converge_export.py +0 -0
  123. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_errors.py +0 -0
  124. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_learn.py +0 -0
  125. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_moves.py +0 -0
  126. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_output.py +0 -0
  127. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_paths.py +0 -0
  128. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_plan.py +0 -0
  129. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_question.py +0 -0
  130. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_review.py +0 -0
  131. {devague-0.12.0 → devague-0.14.0}/tests/test_cli_status.py +0 -0
  132. {devague-0.12.0 → devague-0.14.0}/tests/test_contract.py +0 -0
  133. {devague-0.12.0 → devague-0.14.0}/tests/test_convergence.py +0 -0
  134. {devague-0.12.0 → devague-0.14.0}/tests/test_frame.py +0 -0
  135. {devague-0.12.0 → devague-0.14.0}/tests/test_offline.py +0 -0
  136. {devague-0.12.0 → devague-0.14.0}/tests/test_package.py +0 -0
  137. {devague-0.12.0 → devague-0.14.0}/tests/test_plan.py +0 -0
  138. {devague-0.12.0 → devague-0.14.0}/tests/test_plan_convergence.py +0 -0
  139. {devague-0.12.0 → devague-0.14.0}/tests/test_plan_store.py +0 -0
  140. {devague-0.12.0 → devague-0.14.0}/tests/test_render.py +0 -0
  141. {devague-0.12.0 → devague-0.14.0}/tests/test_render_plan.py +0 -0
  142. {devague-0.12.0 → devague-0.14.0}/tests/test_review_loop_integration.py +0 -0
  143. {devague-0.12.0 → devague-0.14.0}/tests/test_review_loop_invariants.py +0 -0
  144. {devague-0.12.0 → devague-0.14.0}/tests/test_spec_to_plan_skill.py +0 -0
  145. {devague-0.12.0 → devague-0.14.0}/tests/test_store.py +0 -0
  146. {devague-0.12.0 → devague-0.14.0}/tests/test_think_skill.py +0 -0
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: agent-config
3
+ description: >
4
+ Show a Culture agent's full configuration in one read-only view: its
5
+ system-prompt file (CLAUDE.md / AGENTS.md / GEMINI.md), the parallel
6
+ culture.yaml, and the agent's local .claude/skills index. Use when an
7
+ operator says "show agent <name>", "what does <agent> look like", or before
8
+ teaching/onboarding an agent and you need to see its current kit + config.
9
+ Backs the `guild show` verb. Vendored from steward (cite-don't-import);
10
+ inventory only — it reports, it does not judge alignment or drift.
11
+ type: command
12
+ ---
13
+
14
+ # agent-config — surface a Culture agent's config in one view
15
+
16
+ guildmaster is the mesh's skills supplier and owns the **inventory** surfaces:
17
+ "what kit + config does this agent have?" This skill answers exactly that for a
18
+ single agent, showing the three artifacts that together define it:
19
+
20
+ 1. **System-prompt file** (`CLAUDE.md` / `AGENTS.md` / `GEMINI.md`) — the
21
+ prompt-side guidance for the agent's backend. The script detects which file
22
+ is present from a backend-fingerprint registry.
23
+ 2. **`culture.yaml`** — the runtime-side config (`agents:` list with `suffix`,
24
+ `backend`, `model`, `system_prompt`, `channels`, `tags`, `acp_command`,
25
+ `extras`). Lives parallel to the prompt file at the project root.
26
+ 3. **`.claude/skills/*/SKILL.md`** — the per-project skills the agent can
27
+ invoke, one line each (name + truncated description).
28
+
29
+ This is the **inventory half** of the steward → guildmaster split
30
+ ([issue #12](https://github.com/agentculture/guildmaster/issues/12)): it reports
31
+ the config, it does **not** interpret drift or judge alignment. The relationship
32
+ graph and the "is this agent aligned?" judgment stay with `steward overview` /
33
+ `steward doctor`.
34
+
35
+ ## When to use
36
+
37
+ - Before `guild teach` / `guild onboard` — see an agent's current kit + config.
38
+ - When an operator asks "show me agent `<name>`" or "what does `<agent>` run".
39
+ - Read it, don't guess — before answering a question about what an agent does.
40
+
41
+ ## How to run
42
+
43
+ One script, two ways to call it (or just run `guild show`, which wraps it):
44
+
45
+ ```bash
46
+ # Path mode — point at any directory with a prompt file + culture.yaml
47
+ .claude/skills/agent-config/scripts/show.sh ../culture
48
+
49
+ # Suffix mode — resolve a registered agent suffix via the Culture server's
50
+ # manifest (location set by culture_server_yaml in skills.local.yaml)
51
+ .claude/skills/agent-config/scripts/show.sh daria
52
+ ```
53
+
54
+ Output is three sections: the detected system-prompt file, `culture.yaml` (or
55
+ `(missing)`), and a one-line summary per local skill (name + description,
56
+ truncated to 120 chars).
57
+
58
+ ## What to look at in `culture.yaml`
59
+
60
+ | Field | Why it matters |
61
+ |-------|----------------|
62
+ | `suffix` | Identifies the agent on the mesh. |
63
+ | `backend` | One of `claude` / `codex` / `copilot` / `acp`. The all-backends rule means a feature in one must land in all four. |
64
+ | `model` | Drift here changes behavior silently. |
65
+ | `system_prompt` | Should not contradict the prompt file. |
66
+ | `channels` | Where the agent listens. |
67
+ | `tags`, `extras`, `acp_command` | Backend-specific. |
68
+
69
+ ## Notes
70
+
71
+ - **Read-only.** The script never edits agent files. It reports; it does not
72
+ flag or fix drift — that judgment is steward's lane.
73
+ - **Backend-aware.** Prompt-file detection comes from
74
+ `data/backend-fingerprints.yaml` (the `prompt:` mapping), falling back to the
75
+ built-in `(CLAUDE.md AGENTS.md GEMINI.md)` list if the registry is absent.
76
+ - **Per-machine config.** Suffix mode reads `culture_server_yaml` from
77
+ `.claude/skills.local.yaml` (git-ignored), falling back to
78
+ `.claude/skills.local.yaml.example`.
79
+ - **Vendored from steward** (`agent-config`). guildmaster owns this copy and may
80
+ diverge; re-sync from steward's canonical copy when it changes. Divergences:
81
+ the SKILL.md is reframed for guildmaster's inventory role and adds
82
+ `type: command` for the culture backend's skill loader.
@@ -0,0 +1,30 @@
1
+ # Canonical backend fingerprint registry. Vendored from steward's agent-config
2
+ # skill (cite-don't-import); guildmaster owns this copy. Read by the agent-config
3
+ # show.sh (bash), which `guild show` shells out to. Upstream steward also reads
4
+ # it from a Python detector; guildmaster has no parallel detector, so only the
5
+ # `backends:` prompt mapping below is load-bearing here. Keep that mapping in
6
+ # sync with upstream when re-syncing.
7
+ #
8
+ # `prompt` — the backend's system-prompt filename at the repo root.
9
+ # `steering` — files/dirs distinctive enough to attribute to this backend.
10
+ # `shared_steering` — files/dirs that belong to NO specific backend. A repo
11
+ # declared as any backend may have these without triggering a
12
+ # mismatch. `.agents` is a generic Culture agent-config
13
+ # convention. `.claude/settings.json` and
14
+ # `.claude/settings.local.json` are generic Claude Code
15
+ # (editor/CLI) workspace config files — they appear in any
16
+ # repo that uses Claude Code as the development tool,
17
+ # regardless of the agent backend, so they must never be used
18
+ # to infer the backend or flag a mismatch. The claude backend
19
+ # is identified solely by its `CLAUDE.md` prompt file.
20
+ # `.github/copilot-instructions.md` is generic GitHub Copilot
21
+ # editor/IDE config — any repo may have it regardless of the
22
+ # declared agent backend, so it must not trigger a mismatch.
23
+ backends:
24
+ claude: { prompt: CLAUDE.md, steering: [] }
25
+ codex: { prompt: AGENTS.md, steering: [".codex"] }
26
+ acp: { prompt: AGENTS.md, steering: [".kiro"] }
27
+ copilot: { prompt: AGENTS.md, steering: [] }
28
+ gemini: { prompt: GEMINI.md, steering: [".gemini"] }
29
+ shared_steering: [".agents", ".claude/settings.json", ".claude/settings.local.json", ".github/copilot-instructions.md"]
30
+ prompt_fallback: AGENTS.md
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # Show a Culture agent's full configuration in one view:
4
+ # the detected system-prompt file (CLAUDE.md / AGENTS.md / GEMINI.md), the
5
+ # parallel culture.yaml, and the .claude/skills/ index.
6
+ #
7
+ # Usage: show.sh <path-or-agent-suffix>
8
+ #
9
+ # Path mode: show.sh ../culture
10
+ # Suffix mode: show.sh daria (resolved via culture_server_yaml in skills.local.yaml)
11
+ #
12
+ # Exit codes:
13
+ # 0 success
14
+ # 1 environment error (missing manifest, missing PyYAML for suffix mode)
15
+ # 2 user error (no target given, unknown suffix, target path doesn't exist)
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+ SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
19
+ REPO_ROOT="$(cd "$SKILL_DIR/../../.." && pwd)"
20
+
21
+ CFG="$REPO_ROOT/.claude/skills.local.yaml"
22
+ [ -f "$CFG" ] || CFG="$REPO_ROOT/.claude/skills.local.yaml.example"
23
+
24
+ # Read a top-level YAML scalar from CFG. Schema is intentionally tiny:
25
+ # key: value (with optional surrounding quotes / trailing comment)
26
+ # No PyYAML dependency.
27
+ read_cfg() {
28
+ awk -v key="$1" '
29
+ $0 ~ ("^" key ":[[:space:]]*") {
30
+ sub("^" key ":[[:space:]]*", "")
31
+ sub(/[[:space:]]*#.*$/, "")
32
+ sub(/^[[:space:]]+/, ""); sub(/[[:space:]]+$/, "")
33
+ sub(/^["\047]/, ""); sub(/["\047]$/, "")
34
+ print
35
+ exit
36
+ }
37
+ ' "$CFG"
38
+ }
39
+
40
+ target="${1:-}"
41
+ if [ -z "$target" ]; then
42
+ echo "Usage: $(basename "$0") <path-or-agent-suffix>" >&2
43
+ exit 2
44
+ fi
45
+
46
+ if [ -d "$target" ]; then
47
+ DIR="$target"
48
+ else
49
+ SERVER_YAML_RAW="$(read_cfg culture_server_yaml)"
50
+ SERVER_YAML="${SERVER_YAML_RAW/#\~/$HOME}"
51
+ if [ ! -f "$SERVER_YAML" ]; then
52
+ echo "no server manifest at $SERVER_YAML — set culture_server_yaml in $CFG" >&2
53
+ echo "or pass an explicit path instead of suffix '$target'" >&2
54
+ exit 1
55
+ fi
56
+ # Suffix mode parses Culture's server manifest, whose schema is dictated by
57
+ # Culture (not by us) and includes nested mappings — too rich for awk.
58
+ # We use python+PyYAML here, with a friendly install hint if it's missing.
59
+ if ! python3 -c 'import yaml' 2>/dev/null; then
60
+ echo "suffix mode needs Python + PyYAML to parse $SERVER_YAML" >&2
61
+ echo " install: pip install --user pyyaml (or: uv pip install pyyaml)" >&2
62
+ echo " or pass an explicit path instead of suffix '$target'" >&2
63
+ exit 1
64
+ fi
65
+ # Use a dedicated exit code (2) for "unknown suffix" so the steward CLI
66
+ # wrapper can distinguish user errors (typo'd suffix) from env errors
67
+ # (missing manifest / PyYAML).
68
+ if ! DIR=$(python3 - "$SERVER_YAML" "$target" <<'PY'
69
+ import sys, yaml, pathlib
70
+ manifest_path, suffix = sys.argv[1], sys.argv[2]
71
+ m = yaml.safe_load(pathlib.Path(manifest_path).read_text()) or {}
72
+ agents = m.get('agents', {})
73
+ entry = agents.get(suffix)
74
+ if entry is None:
75
+ print(f"no agent registered with suffix {suffix!r} in {manifest_path}", file=sys.stderr)
76
+ sys.exit(2)
77
+ print(entry['directory'] if isinstance(entry, dict) else entry)
78
+ PY
79
+ ); then
80
+ exit 2
81
+ fi
82
+ fi
83
+
84
+ DIR="${DIR/#\~/$HOME}"
85
+
86
+ # Recognized prompt filenames come from the shared registry (single source
87
+ # of truth with the Python detector). Fall back to the built-in list if the
88
+ # registry isn't present (e.g. skill vendored without the data file).
89
+ REGISTRY="$SKILL_DIR/data/backend-fingerprints.yaml"
90
+ prompt_files=()
91
+ if [ -f "$REGISTRY" ]; then
92
+ while IFS= read -r pf; do
93
+ [ -n "$pf" ] && prompt_files+=("$pf")
94
+ done < <(grep -oE 'prompt:[[:space:]]*[^,}[:space:]]+' "$REGISTRY" | awk '{print $NF}' | sort -u)
95
+ fi
96
+ [ ${#prompt_files[@]} -eq 0 ] && prompt_files=(CLAUDE.md AGENTS.md GEMINI.md)
97
+
98
+ shown=0
99
+ for pf in "${prompt_files[@]}"; do
100
+ if [ -f "$DIR/$pf" ]; then
101
+ echo "=== $DIR/$pf ==="
102
+ cat "$DIR/$pf"
103
+ echo
104
+ shown=1
105
+ fi
106
+ done
107
+ if [ "$shown" -eq 0 ]; then
108
+ echo "=== $DIR (system prompt) ==="
109
+ echo "(no recognized prompt file: ${prompt_files[*]})"
110
+ echo
111
+ fi
112
+ echo "=== $DIR/culture.yaml ==="
113
+ if [ -f "$DIR/culture.yaml" ]; then cat "$DIR/culture.yaml"; else echo "(missing)"; fi
114
+ echo
115
+ echo "=== $DIR/.claude/skills/ ==="
116
+ found=0
117
+ for s in "$DIR"/.claude/skills/*/SKILL.md; do
118
+ [ -f "$s" ] || continue
119
+ found=1
120
+ name=$(awk '/^name:/{print $2; exit}' "$s")
121
+ desc=$(awk '
122
+ /^description:/ {
123
+ sub(/^description:[[:space:]]*/, "")
124
+ buf = $0
125
+ flag = 1
126
+ next
127
+ }
128
+ flag && /^[a-z_-]+:/ { flag = 0 }
129
+ flag { buf = buf " " $0 }
130
+ END { gsub(/^[[:space:]]+|[[:space:]]+$/, "", buf); print buf }
131
+ ' "$s")
132
+ printf " %-30s %s\n" "$name" "${desc:0:120}"
133
+ done
134
+ if [ "$found" -eq 0 ]; then
135
+ echo " (no skills)"
136
+ fi
@@ -10,8 +10,9 @@ description: >
10
10
  performs the fan-out. Use when the user says "assign to workforce",
11
11
  "fan out the plan", "parallel subagents", or after /spec-to-plan exports a
12
12
  plan. Authored and maintained in agentculture/devague (origin = devague);
13
- steward pulls this skill from here and broadcasts it to the AgentCulture
14
- mesh — it is NOT vendored from steward like the other skills here.
13
+ guildmaster pulls this skill from here and broadcasts it to the AgentCulture
14
+ mesh — it is NOT vendored from guildmaster like the other skills here.
15
+ type: command
15
16
  ---
16
17
 
17
18
  # assign-to-workforce — fan out a converged plan's waves to parallel agents
@@ -235,7 +236,7 @@ This is a **first-party** skill — its origin is `agentculture/devague`, where
235
236
  the devague agent maintains it alongside the tools it operates (dogfooding),
236
237
  next to its siblings `/think` and `/spec-to-plan`. It is the *third* skill in
237
238
  that outbound family, covering the implementation leg after a plan converges.
238
- The flow runs the *opposite* direction of the vendored steward skills: steward
239
- pulls this **from** devague and broadcasts it to the rest of the AgentCulture
240
- mesh. The `cite, don't import` policy still holds: downstream repos copy it,
239
+ The flow runs the *opposite* direction of the vendored guildmaster skills:
240
+ guildmaster pulls this **from** devague and broadcasts it to the rest of the
241
+ AgentCulture mesh. The `cite, don't import` policy still holds: downstream repos copy it,
241
242
  they don't symlink or depend on it. See `docs/skill-sources.md`.
@@ -1,17 +1,17 @@
1
1
  ---
2
2
  name: cicd
3
3
  description: >
4
- Steward's CI/CD lane, layered on `agex pr`. Delegates lint / open /
5
- read / reply / delta to agex; adds two steward extensions — `status`
4
+ guildmaster's CI/CD lane, layered on `agex pr`. Delegates lint / open /
5
+ read / reply / delta to agex; adds two extensions — `status`
6
6
  (SonarCloud quality gate + hotspots + unresolved-thread tally) and
7
7
  `await` (read --wait + status with non-zero exit on Sonar ERROR or
8
- unresolved threads). Use when: creating PRs in steward, handling
8
+ unresolved threads). Use when: creating PRs in guildmaster, handling
9
9
  review feedback, polling CI status, or the user says "create PR",
10
10
  "review comments", "address feedback", "resolve threads". Renamed
11
11
  from `pr-review` in steward 0.7.0; rebased on agex in 0.12.0.
12
12
  ---
13
13
 
14
- # CI/CD — Steward edition
14
+ # CI/CD — guildmaster edition
15
15
 
16
16
  `agex pr` (in `agentculture/agex-cli`) is the upstream for the
17
17
  five core PR-lifecycle verbs — `lint`, `open`, `read`, `reply`,
@@ -25,14 +25,43 @@ What's left in this skill is **the steward-specific gating layer**:
25
25
  Sonar `ERROR` / unresolved threads. The single command to run after
26
26
  pushing a fix when you want "wake me when this PR is triage-able."
27
27
 
28
- Those two are the steward unique surface today. They're filed as a
29
- feature ask upstream
30
- ([agex-cli#41](https://github.com/agentculture/agex-cli/issues/41));
31
- once they land they migrate out of this skill.
28
+ Those two are the steward unique surface today. The `await` combo verb
29
+ landed natively in agex
30
+ ([agex-cli#41](https://github.com/agentculture/agex-cli/issues/41), now
31
+ closed); the gate extras that aren't yet native — SonarCloud hotspots,
32
+ deploy-preview URL, an explicit resolved/unresolved thread tally — are
33
+ tracked upstream in
34
+ [agex-cli#52](https://github.com/agentculture/agex-cli/issues/52) and
35
+ migrate out of this skill once they land.
32
36
 
33
37
  The workflow is encapsulated in `scripts/workflow.sh` — follow that
34
38
  (or call `agex pr` directly).
35
39
 
40
+ ## The agex-cli inversion (upstream-as-consumer)
41
+
42
+ One consumer is special: **agex-cli itself**, the repo that owns `agex pr`.
43
+ Vendoring this skill there verbatim would re-vendor bash that just wraps the
44
+ Python agex-cli already ships, so agex-cli vendors it **adapted-thin**
45
+ ([agex-cli#53](https://github.com/agentculture/agex-cli/pull/53)):
46
+ `workflow.sh` is the only script and it forwards
47
+ `lint | open | read | reply | delta | await` straight to the native
48
+ `agex pr <verb>` — including the native `agex pr await` combo verb (agex-cli
49
+ 0.21.0). The steward `status` / `await` shell extensions and the vendored
50
+ helpers (`pr-reply.sh`, `_resolve-nick.sh`, `portability-lint.sh`) are all
51
+ redundant there, each superseded by a native verb. For that one consumer the
52
+ skill collapses to a **pure delegate**.
53
+
54
+ The only gate bits not yet native are SonarCloud **hotspots**, the
55
+ **deploy-preview URL**, and an explicit **resolved/unresolved thread tally** —
56
+ tracked upstream in
57
+ [agex-cli#52](https://github.com/agentculture/agex-cli/issues/52). Once those
58
+ land, steward retires `pr-status.sh` too and `workflow.sh status/await`
59
+ delegates to native `agex pr` everywhere.
60
+
61
+ **For broadcasts:** a skill-update brief to agex-cli should expect this thin
62
+ `workflow.sh`-only shape, not steward's five-file layout. (Ref:
63
+ [steward#53](https://github.com/agentculture/steward/issues/53).)
64
+
36
65
  ## Prerequisites
37
66
 
38
67
  Hard requirements: `agex` (>=0.1), `gh` (GitHub CLI), `jq`, `bash`,
@@ -22,7 +22,7 @@ esac
22
22
 
23
23
  # ----- Check 1: hard-coded /home/<user>/... paths -----
24
24
  # devague-divergence: drop GNU-only `xargs -r` (fails on BSD/macOS); `$files`
25
- # is already guarded non-empty above. Upstream to steward; remove on re-vendor.
25
+ # is already guarded non-empty above. Upstream to guildmaster; remove on re-vendor.
26
26
  hits1=$(echo "$files" | xargs grep -nE '/home/[a-z][a-z0-9_-]+/' 2>/dev/null || true)
27
27
 
28
28
  # ----- Check 2: per-user dotfile *config* refs in committed docs/configs -----
@@ -32,7 +32,7 @@ hits1=$(echo "$files" | xargs grep -nE '/home/[a-z][a-z0-9_-]+/' 2>/dev/null ||
32
32
  md_yaml=$(echo "$files" | grep -E '\.(md|ya?ml|toml|json|jsonc)$' || true)
33
33
  if [ -n "$md_yaml" ]; then
34
34
  # devague-divergence: drop GNU-only `xargs -r` (see Check 1); `$md_yaml`
35
- # is guarded non-empty by the `if` above. Upstream to steward.
35
+ # is guarded non-empty by the `if` above. Upstream to guildmaster.
36
36
  hits2=$(echo "$md_yaml" | xargs grep -nE '~/\.[A-Za-z]' 2>/dev/null \
37
37
  | grep -vE '~/\.claude/skills/[^[:space:]"]+/scripts/' \
38
38
  | grep -vE '~/\.culture/' \
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: communicate
3
3
  description: >
4
- Cross-repo + mesh communication from steward: file tracked GitHub issues
4
+ Cross-repo + mesh communication from guildmaster: file tracked GitHub issues
5
5
  on sibling repos, fetch issues from sibling repos to inline current state
6
6
  into briefs, and send live messages to Culture mesh channels. Use when
7
- the next step lives outside steward (a brief for a sibling-repo agent, a
7
+ the next step lives outside guildmaster (a brief for a sibling-repo agent, a
8
8
  status ping for a Culture channel, or pulling an issue body + comments
9
- into context). Issue posts auto-sign with `- steward (Claude)`; mesh
10
- messages are unsigned (the IRC nick is the speaker). Not for in-steward
9
+ into context). Issue posts auto-sign with `- guildmaster (Claude)`; mesh
10
+ messages are unsigned (the IRC nick is the speaker). Not for in-guildmaster
11
11
  issues — use `gh issue create` or the `cicd` skill for those. Renamed
12
12
  from `coordinate` in steward 0.8.0; absorbed `gh-issues` in 0.9.1.
13
13
  Issue I/O is backed by `agtag` (>=0.1) starting in 0.11.0.
@@ -0,0 +1,85 @@
1
+ <!-- markdownlint-disable MD041 -->
2
+ <!-- This file is the NEW-SKILL template rendered by announce-skill-update -->
3
+ <!-- when --new is passed. It posts as an issue body where GitHub supplies -->
4
+ <!-- the title, so there's no H1 here on purpose. Placeholders use the -->
5
+ <!-- `{{NAME}}` syntax; {{ORIGIN_BLOCK}} is empty unless --origin is given. -->
6
+
7
+ ## A new skill is available to vendor
8
+
9
+ `{{SKILL}}` is a **new** skill in the AgentCulture mesh. Your repo does
10
+ not have it yet — this brief tells you how to **add it fresh** (there is no
11
+ older vendored copy to replace). If you maintain a `docs/skill-sources.md`
12
+ provenance ledger, add a row for it; if not, just drop it into
13
+ `.claude/skills/`.
14
+
15
+ {{ORIGIN_BLOCK}}
16
+
17
+ Relevant guildmaster CHANGELOG entries (where guildmaster picked the skill up):
18
+
19
+ {{CHANGELOG_BLOCK}}
20
+
21
+ ## Cite locations (source of truth)
22
+
23
+ - Local sibling checkout (preferred when available):
24
+ `../guildmaster/.claude/skills/{{SKILL}}/`
25
+ - Remote, if the workspace doesn't include a local guildmaster checkout:
26
+ <https://github.com/agentculture/guildmaster/tree/main/.claude/skills/{{SKILL}}>
27
+
28
+ guildmaster re-broadcasts this skill to the mesh, so its copy is the citation
29
+ point even when the skill originates in another sibling (see origin note
30
+ above, if present). The directory ships a `SKILL.md` and a `scripts/`
31
+ directory per the AgentCulture skills-portability rule (each skill is
32
+ self-contained; nothing reaches across skill boundaries at runtime).
33
+
34
+ ## What's in the upstream now
35
+
36
+ `{{SKILL}}/scripts/` ({{UPSTREAM_SCRIPT_COUNT}} files):
37
+
38
+ {{UPSTREAM_SCRIPT_LIST}}
39
+
40
+ {{DELTA_BLOCK}}
41
+
42
+ {{NOTE_BLOCK}}
43
+
44
+ ## What to do
45
+
46
+ ```bash
47
+ # 0. Branch.
48
+ git checkout -b skill/{{SKILL}}-add
49
+
50
+ # 1. Add the skill fresh from upstream (no existing copy to remove).
51
+ cp -R ../guildmaster/.claude/skills/{{SKILL}} .claude/skills/
52
+ chmod +x .claude/skills/{{SKILL}}/scripts/*.sh 2>/dev/null || true
53
+
54
+ # 2. If you keep docs/skill-sources.md, add a row pointing at
55
+ # ../guildmaster/.claude/skills/{{SKILL}}/ (record any local divergence).
56
+
57
+ # 3. Bump version per project convention (CI version-check enforces in
58
+ # AgentCulture siblings); add a CHANGELOG entry.
59
+ ```
60
+
61
+ ## Acceptance criteria
62
+
63
+ - `.claude/skills/{{SKILL}}/SKILL.md` is present with frontmatter
64
+ `name: {{SKILL}}`. **On the culture/agex backend, also add
65
+ `type: command`** — `core.skill_loader` requires all of `name`,
66
+ `description`, and `type:`, and a SKILL.md lacking `type:` is silently
67
+ skipped by `backends/claude_code/probe.py`.
68
+ - `.claude/skills/{{SKILL}}/scripts/` contains the
69
+ {{UPSTREAM_SCRIPT_COUNT}} files listed above (and only those, unless your
70
+ repo intentionally adds extras — record divergence in the SKILL.md
71
+ frontmatter `description` per the AgentCulture vendoring policy).
72
+ - All scripts are executable (`chmod +x`).
73
+ - If you keep a `docs/skill-sources.md`, it lists `{{SKILL}}` with the
74
+ upstream `../guildmaster/.claude/skills/{{SKILL}}/`.
75
+ - `CHANGELOG.md` has a new version entry describing the addition; the
76
+ version is bumped per project convention; CI's `version-check` job is green.
77
+
78
+ ## References
79
+
80
+ - guildmaster CHANGELOG (release-by-release deltas):
81
+ <https://github.com/agentculture/guildmaster/blob/main/CHANGELOG.md>
82
+ - `{{SKILL}}` SKILL.md:
83
+ <https://github.com/agentculture/guildmaster/blob/main/.claude/skills/{{SKILL}}/SKILL.md>
84
+ - AgentCulture skills-portability rule (each vendor owns and may adapt its
85
+ copy): the `communicate` SKILL.md "Conventions in use" section.
@@ -7,17 +7,17 @@
7
7
 
8
8
  Your repo's `.claude/skills/{{SKILL}}/` (or its older vendored
9
9
  name — see your `docs/skill-sources.md` if you keep a provenance
10
- ledger) is a vendored copy of the steward skill that has since
11
- moved on. Relevant CHANGELOG entries from steward:
10
+ ledger) is a vendored copy of the guildmaster skill that has since
11
+ moved on. Relevant CHANGELOG entries from guildmaster:
12
12
 
13
13
  {{CHANGELOG_BLOCK}}
14
14
 
15
15
  ## Cite locations (source of truth)
16
16
 
17
17
  - Local sibling checkout (preferred when available):
18
- `../steward/.claude/skills/{{SKILL}}/`
19
- - Remote, if the workspace doesn't include a local steward checkout:
20
- <https://github.com/agentculture/steward/tree/main/.claude/skills/{{SKILL}}>
18
+ `../guildmaster/.claude/skills/{{SKILL}}/`
19
+ - Remote, if the workspace doesn't include a local guildmaster checkout:
20
+ <https://github.com/agentculture/guildmaster/tree/main/.claude/skills/{{SKILL}}>
21
21
 
22
22
  The directory ships with a `SKILL.md` and a `scripts/` directory
23
23
  per the AgentCulture skills-portability rule (each skill is
@@ -44,14 +44,14 @@ git checkout -b skill/{{SKILL}}-resync
44
44
  # If your old vendored name differs (e.g. pr-review → cicd),
45
45
  # `git rm` the old dir first.
46
46
  git rm -r .claude/skills/<old-name-if-different> # skip if name is already {{SKILL}}
47
- cp -R ../steward/.claude/skills/{{SKILL}} .claude/skills/
47
+ cp -R ../guildmaster/.claude/skills/{{SKILL}} .claude/skills/
48
48
  chmod +x .claude/skills/{{SKILL}}/scripts/*.sh 2>/dev/null || true
49
49
 
50
50
  # 2. Adapt identifiers per the existing "identifier-only adapted"
51
51
  # pattern in your docs/skill-sources.md (if you keep one):
52
- # - SKILL.md prose framing: replace "steward" with your repo
52
+ # - SKILL.md prose framing: replace "guildmaster" with your repo
53
53
  # name where it identifies the consumer (NOT where it cites
54
- # steward as the upstream).
54
+ # guildmaster as the upstream).
55
55
  # - For any script that hard-codes a signature literal, change it
56
56
  # to `- <your-repo> (Claude)`. (The communicate skill no longer
57
57
  # hard-codes one — agtag resolves the nick from your local
@@ -80,9 +80,9 @@ grep -rn '<old-name-if-different>' .claude docs CLAUDE.md README.md 2>/dev/null
80
80
  AgentCulture vendoring policy).
81
81
  - All scripts are executable (`chmod +x`).
82
82
  - If the skill hard-codes a signature literal anywhere, your
83
- vendored copy uses your repo's signature, not `- steward (Claude)`.
83
+ vendored copy uses your repo's signature, not `- guildmaster (Claude)`.
84
84
  - If you keep a `docs/skill-sources.md`, it lists `{{SKILL}}` with
85
- the upstream `../steward/.claude/skills/{{SKILL}}/`; no row
85
+ the upstream `../guildmaster/.claude/skills/{{SKILL}}/`; no row
86
86
  remains for the old vendored name.
87
87
  - `grep -rn '<old-name-if-different>' .claude docs CLAUDE.md README.md`
88
88
  returns zero hits, or only historical mentions in CHANGELOG.
@@ -92,10 +92,10 @@ grep -rn '<old-name-if-different>' .claude docs CLAUDE.md README.md 2>/dev/null
92
92
 
93
93
  ## References
94
94
 
95
- - Steward CHANGELOG (release-by-release deltas):
96
- <https://github.com/agentculture/steward/blob/main/CHANGELOG.md>
95
+ - guildmaster CHANGELOG (release-by-release deltas):
96
+ <https://github.com/agentculture/guildmaster/blob/main/CHANGELOG.md>
97
97
  - `{{SKILL}}` SKILL.md:
98
- <https://github.com/agentculture/steward/blob/main/.claude/skills/{{SKILL}}/SKILL.md>
98
+ <https://github.com/agentculture/guildmaster/blob/main/.claude/skills/{{SKILL}}/SKILL.md>
99
99
  - AgentCulture skills-portability rule (why each vendor adapts
100
100
  signature literals locally): the `communicate` SKILL.md
101
101
  "Per-channel signature rules" + "Conventions in use" sections.
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: pypi-maintainer
3
+ description: >
4
+ Switch a PyPI package install between the production index, TestPyPI
5
+ pre-release builds, and a local editable checkout. Use when an agent
6
+ maintains a package and needs to verify a TestPyPI dev build before
7
+ promoting to production, or when the user says "install from
8
+ test-pypi", "switch to local", "change package source", or
9
+ "install from pypi".
10
+ ---
11
+
12
+ # PyPI Maintainer
13
+
14
+ Switch the install source for a package the agent maintains. Three sources
15
+ are supported: production PyPI, TestPyPI (pre-release / dev builds), and a
16
+ local editable checkout. The same script works for any package an
17
+ AgentCulture sibling publishes — pass the package name as the first
18
+ argument.
19
+
20
+ ## When to use
21
+
22
+ - Verifying a PR's TestPyPI dev build before merging.
23
+ - Reproducing a user-reported bug against the published version.
24
+ - Hot-patching against a local checkout while a fix is in flight.
25
+ - Restoring the production install after local-mode debugging.
26
+
27
+ ## Usage
28
+
29
+ ```bash
30
+ # Production PyPI
31
+ bash .claude/skills/pypi-maintainer/scripts/switch-source.sh <package> pypi
32
+
33
+ # TestPyPI (pre-release dev builds)
34
+ bash .claude/skills/pypi-maintainer/scripts/switch-source.sh <package> test-pypi
35
+
36
+ # TestPyPI, pinned to a specific dev version
37
+ bash .claude/skills/pypi-maintainer/scripts/switch-source.sh <package> test-pypi --version 0.4.0.dev42
38
+
39
+ # Local editable checkout (defaults to current directory)
40
+ bash .claude/skills/pypi-maintainer/scripts/switch-source.sh <package> local
41
+
42
+ # Local editable from an explicit path
43
+ bash .claude/skills/pypi-maintainer/scripts/switch-source.sh <package> local --path ../<package>
44
+ ```
45
+
46
+ ## Prerequisites
47
+
48
+ The script requires the following tools on `PATH`:
49
+
50
+ - `bash`
51
+ - `uv` — the script delegates to `uv tool install` and `uv tool list`
52
+ (or `uv pip install` for `local`).
53
+
54
+ ## Why TestPyPI needs special flags
55
+
56
+ When a package is published to **both** PyPI and TestPyPI, `uv tool install`
57
+ finds the production version on PyPI first and never looks at TestPyPI.
58
+ The script passes `--index-strategy unsafe-best-match` so uv compares the
59
+ two index sets and picks the highest version, plus `--prerelease=allow`
60
+ because TestPyPI builds carry dev suffixes (e.g. `0.4.0.dev42`).
61
+
62
+ ## After running
63
+
64
+ The script prints the resolved version once install completes — cross-check
65
+ that against the expected version (PR run number, local `pyproject.toml`)
66
+ before continuing.
67
+
68
+ ## Arguments
69
+
70
+ | Position / flag | Meaning |
71
+ |-----------------|---------|
72
+ | `<package>` (required) | The PyPI distribution name, e.g. `steward-cli`, `culture`, `daria-cli`. |
73
+ | `<source>` (required) | One of `pypi`, `test-pypi`, `local`. |
74
+ | `--version VERSION` | Pin to a specific version (TestPyPI builds typically need this). |
75
+ | `--path PATH` | Local-source-only: path to the editable checkout (default: cwd). |