guild-cli 0.25.1__tar.gz → 0.26.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 (149) hide show
  1. guild_cli-0.26.0/.claude/skills/agent-config/data/backend-fingerprints.yaml +47 -0
  2. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/agent-config/scripts/show.sh +18 -3
  3. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/guild/SKILL.md +11 -0
  4. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/guild/scripts/create.sh +13 -2
  5. guild_cli-0.26.0/.devague/current +1 -0
  6. guild_cli-0.26.0/.devague/current_plan +1 -0
  7. guild_cli-0.26.0/.devague/deliveries/template-supports-four-harnesses.json +275 -0
  8. guild_cli-0.26.0/.devague/frames/template-supports-four-harnesses.json +1982 -0
  9. guild_cli-0.26.0/.devague/plans/template-supports-four-harnesses.json +1103 -0
  10. guild_cli-0.26.0/.eidetic/memory/culture-agent-template__public.jsonl +1 -0
  11. {guild_cli-0.25.1 → guild_cli-0.26.0}/.eidetic/memory/guildmaster__public.jsonl +8 -5
  12. {guild_cli-0.25.1 → guild_cli-0.26.0}/.gitignore +2 -0
  13. {guild_cli-0.25.1 → guild_cli-0.26.0}/CHANGELOG.md +40 -0
  14. {guild_cli-0.25.1 → guild_cli-0.26.0}/CLAUDE.md +1 -1
  15. {guild_cli-0.25.1 → guild_cli-0.26.0}/PKG-INFO +32 -1
  16. {guild_cli-0.25.1 → guild_cli-0.26.0}/README.md +31 -0
  17. guild_cli-0.26.0/docs/deliveries/2026-09-05-template-supports-four-harnesses.md +112 -0
  18. guild_cli-0.26.0/docs/plans/2026-09-05-template-supports-four-harnesses-split.md +233 -0
  19. guild_cli-0.26.0/docs/plans/2026-09-05-template-supports-four-harnesses.md +165 -0
  20. guild_cli-0.26.0/docs/specs/2026-09-05-template-supports-four-harnesses.md +282 -0
  21. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/__init__.py +2 -0
  22. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/__init__.py +5 -0
  23. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/_provision_template.py +277 -8
  24. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/create.py +160 -12
  25. guild_cli-0.26.0/guild/cli/_commands/harness.py +223 -0
  26. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/onboard.py +86 -9
  27. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/show.py +10 -3
  28. guild_cli-0.26.0/guild/scaffold/harness.py +330 -0
  29. guild_cli-0.26.0/guild/scaffold/harness_use.py +253 -0
  30. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/scaffold/instantiate.py +65 -29
  31. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/skills/identity.py +38 -12
  32. {guild_cli-0.25.1 → guild_cli-0.26.0}/pyproject.toml +1 -1
  33. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_create.py +174 -3
  34. guild_cli-0.26.0/tests/test_cli_harness.py +255 -0
  35. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_onboard.py +91 -0
  36. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_show.py +41 -0
  37. guild_cli-0.26.0/tests/test_create_gate.py +493 -0
  38. guild_cli-0.26.0/tests/test_scaffold_harness.py +177 -0
  39. guild_cli-0.26.0/tests/test_scaffold_harness_use.py +206 -0
  40. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_scaffold_instantiate.py +100 -2
  41. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_skills_identity.py +38 -0
  42. {guild_cli-0.25.1 → guild_cli-0.26.0}/uv.lock +1 -1
  43. guild_cli-0.25.1/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -30
  44. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/agent-config/SKILL.md +0 -0
  45. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/ask-colleague/SKILL.md +0 -0
  46. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/ask-colleague/prompts/explore.md +0 -0
  47. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/ask-colleague/prompts/review.md +0 -0
  48. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/ask-colleague/prompts/write.md +0 -0
  49. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +0 -0
  50. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  51. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  52. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/challenge/SKILL.md +0 -0
  53. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/challenge/scripts/challenge.sh +0 -0
  54. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/SKILL.md +0 -0
  55. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  56. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  57. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  58. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  59. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  60. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/SKILL.md +0 -0
  61. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  62. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  63. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  64. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  65. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
  66. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  67. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/deviate/SKILL.md +0 -0
  68. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/deviate/scripts/deviate.sh +0 -0
  69. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  70. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  71. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/guild/scripts/configure-repo.sh +0 -0
  72. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/guild/scripts/overview.sh +0 -0
  73. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/onboard/SKILL.md +0 -0
  74. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/onboard/scripts/onboard.sh +0 -0
  75. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/outsource/SKILL.md +0 -0
  76. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/outsource/prompts/explore.md +0 -0
  77. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/outsource/prompts/review.md +0 -0
  78. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/outsource/prompts/write.md +0 -0
  79. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/outsource/scripts/outsource.sh +0 -0
  80. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  81. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  82. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/recall/SKILL.md +0 -0
  83. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/recall/scripts/recall.sh +0 -0
  84. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/remember/SKILL.md +0 -0
  85. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/remember/scripts/remember.sh +0 -0
  86. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/run-tests/SKILL.md +0 -0
  87. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  88. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/scope/SKILL.md +0 -0
  89. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/scope/scripts/scope.sh +0 -0
  90. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  91. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  92. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  93. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  94. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/summarize-delivery/SKILL.md +0 -0
  95. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/summarize-delivery/scripts/summarize-delivery.sh +0 -0
  96. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/teach/SKILL.md +0 -0
  97. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/teach/scripts/teach.sh +0 -0
  98. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/think/SKILL.md +0 -0
  99. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/think/scripts/think.sh +0 -0
  100. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/validate-delivery/SKILL.md +0 -0
  101. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/validate-delivery/scripts/validate-delivery.sh +0 -0
  102. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/version-bump/SKILL.md +0 -0
  103. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  104. {guild_cli-0.25.1 → guild_cli-0.26.0}/.claude/skills.local.yaml.example +0 -0
  105. {guild_cli-0.25.1 → guild_cli-0.26.0}/.devague/frames/guildmaster-ships-teach-and-onboard-two-agent-firs.json +0 -0
  106. {guild_cli-0.25.1 → guild_cli-0.26.0}/.devague/plans/guildmaster-ships-teach-and-onboard-two-agent-firs.json +0 -0
  107. {guild_cli-0.25.1 → guild_cli-0.26.0}/.eidetic/memory/default__public.jsonl +0 -0
  108. {guild_cli-0.25.1 → guild_cli-0.26.0}/.flake8 +0 -0
  109. {guild_cli-0.25.1 → guild_cli-0.26.0}/.github/workflows/publish.yml +0 -0
  110. {guild_cli-0.25.1 → guild_cli-0.26.0}/.github/workflows/tests.yml +0 -0
  111. {guild_cli-0.25.1 → guild_cli-0.26.0}/.markdownlint-cli2.yaml +0 -0
  112. {guild_cli-0.25.1 → guild_cli-0.26.0}/LICENSE +0 -0
  113. {guild_cli-0.25.1 → guild_cli-0.26.0}/culture.yaml +0 -0
  114. {guild_cli-0.25.1 → guild_cli-0.26.0}/docs/cutover.md +0 -0
  115. {guild_cli-0.25.1 → guild_cli-0.26.0}/docs/onboarding/reachy-mini-mcp.json +0 -0
  116. {guild_cli-0.25.1 → guild_cli-0.26.0}/docs/plans/2026-05-24-guildmaster-ships-teach-and-onboard-two-agent-firs.md +0 -0
  117. {guild_cli-0.25.1 → guild_cli-0.26.0}/docs/skill-sources.md +0 -0
  118. {guild_cli-0.25.1 → guild_cli-0.26.0}/docs/specs/2026-05-24-guildmaster-ships-teach-and-onboard-two-agent-firs.md +0 -0
  119. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/__init__.py +0 -0
  120. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/__main__.py +0 -0
  121. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/_broadcast.py +0 -0
  122. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/explain.py +0 -0
  123. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/learn.py +0 -0
  124. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/overview.py +0 -0
  125. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/teach.py +0 -0
  126. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_commands/whoami.py +0 -0
  127. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_errors.py +0 -0
  128. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_output.py +0 -0
  129. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/cli/_repo.py +0 -0
  130. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/scaffold/__init__.py +0 -0
  131. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/skills/__init__.py +0 -0
  132. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/skills/ledger.py +0 -0
  133. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/skills/render.py +0 -0
  134. {guild_cli-0.25.1 → guild_cli-0.26.0}/guild/skills/sources.py +0 -0
  135. {guild_cli-0.25.1 → guild_cli-0.26.0}/sonar-project.properties +0 -0
  136. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/__init__.py +0 -0
  137. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_broadcast_post.py +0 -0
  138. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli.py +0 -0
  139. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_explain.py +0 -0
  140. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_learn.py +0 -0
  141. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_overview.py +0 -0
  142. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_teach.py +0 -0
  143. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_cli_whoami.py +0 -0
  144. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_configure_repo_sonar.py +0 -0
  145. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_skills_convention.py +0 -0
  146. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_skills_ledger.py +0 -0
  147. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_skills_render.py +0 -0
  148. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_skills_sources.py +0 -0
  149. {guild_cli-0.25.1 → guild_cli-0.26.0}/tests/test_version_fallback.py +0 -0
@@ -0,0 +1,47 @@
1
+ # Canonical backend fingerprint registry. Read by the agent-config show.sh
2
+ # (bash) and by steward/cli/_commands/_agents.py (Python). Single source of
3
+ # truth — tests/test_agents.py asserts the Python fallback constant matches
4
+ # this file so the two never drift.
5
+ #
6
+ # `prompt` — the backend's system-prompt file(s), as a repo-relative
7
+ # path. May be a single scalar (legacy, still supported for
8
+ # vendored copies) or a LIST: a backend matches if ANY of
9
+ # its listed prompts is present on disk. The list form
10
+ # exists because four agent harnesses occupy only two
11
+ # backend names — Qwen Code runs on `acp` (QWEN.md) and
12
+ # associate/Pi runs on `colleague` (AGENTS.override.md as
13
+ # context plus .pi/SYSTEM.md as the system prompt). Values
14
+ # may be nested paths, not just root filenames.
15
+ # `steering` — files/dirs distinctive enough to attribute to this backend.
16
+ # `shared_steering` — files/dirs that belong to NO specific backend. A repo
17
+ # declared as any backend may have these without triggering a
18
+ # mismatch. `.agents` is a generic Culture agent-config
19
+ # convention. `.claude/settings.json` and
20
+ # `.claude/settings.local.json` are generic Claude Code
21
+ # (editor/CLI) workspace config files — they appear in any
22
+ # repo that uses Claude Code as the development tool,
23
+ # regardless of the agent backend, so they must never be used
24
+ # to infer the backend or flag a mismatch. The claude backend
25
+ # is identified solely by its `CLAUDE.md` prompt file.
26
+ # `.github/copilot-instructions.md` is generic GitHub Copilot
27
+ # editor/IDE config — any repo may have it regardless of the
28
+ # declared agent backend, so it must not trigger a mismatch.
29
+ # `.colleague` is the colleague CLI's gitignored bookkeeping
30
+ # dir — it appears in ANY repo where `colleague` / the
31
+ # ask-colleague skill has run, regardless of the agent
32
+ # backend, so it is generic residue, not a `colleague`-backend
33
+ # fingerprint. The colleague backend is identified solely by
34
+ # its prompt files. `.pi` is the associate/Pi harness's
35
+ # config dir — it holds that harness's own system prompt
36
+ # (.pi/SYSTEM.md) and can appear alongside any declared
37
+ # backend, so it must never trigger a foreign-steering
38
+ # mismatch.
39
+ backends:
40
+ claude: { prompt: CLAUDE.md, steering: [] }
41
+ codex: { prompt: AGENTS.md, steering: [".codex"] }
42
+ acp: { prompt: [AGENTS.md, QWEN.md], steering: [".kiro"] }
43
+ copilot: { prompt: AGENTS.md, steering: [] }
44
+ gemini: { prompt: GEMINI.md, steering: [".gemini"] }
45
+ colleague: { prompt: [AGENTS.colleague.md, AGENTS.override.md, .pi/SYSTEM.md], steering: [] }
46
+ shared_steering: [".agents", ".claude/settings.json", ".claude/settings.local.json", ".github/copilot-instructions.md", ".colleague", ".pi"]
47
+ prompt_fallback: AGENTS.md
@@ -83,15 +83,30 @@ fi
83
83
 
84
84
  DIR="${DIR/#\~/$HOME}"
85
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
86
+ # Recognized prompt paths come from the shared registry (single source of
87
+ # truth with the Python detector). Fall back to the built-in list if the
88
88
  # registry isn't present (e.g. skill vendored without the data file).
89
+ #
90
+ # A registry `prompt` value is either a scalar (`prompt: CLAUDE.md`, the legacy
91
+ # shape) or a flow list (`prompt: [AGENTS.md, QWEN.md]`), and a value may be a
92
+ # nested path (`.pi/SYSTEM.md`), not just a bare root filename. The extraction
93
+ # below therefore matches a bracketed list OR a bare token, strips the
94
+ # brackets, splits on commas, and trims whitespace/quotes. Order is preserved
95
+ # (first occurrence wins) rather than sorted, so a backend's primary prompt is
96
+ # catted first.
89
97
  REGISTRY="$SKILL_DIR/data/backend-fingerprints.yaml"
90
98
  prompt_files=()
91
99
  if [ -f "$REGISTRY" ]; then
92
100
  while IFS= read -r pf; do
93
101
  [ -n "$pf" ] && prompt_files+=("$pf")
94
- done < <(grep -oE 'prompt:[[:space:]]*[^,}[:space:]]+' "$REGISTRY" | awk '{print $NF}' | sort -u)
102
+ done < <(
103
+ grep -oE 'prompt:[[:space:]]*(\[[^]]*\]|[^],}[:space:]]+)' "$REGISTRY" \
104
+ | sed -E 's/^prompt:[[:space:]]*//; s/^\[//; s/\]$//' \
105
+ | tr ',' '\n' \
106
+ | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//; s/^["'"'"']//; s/["'"'"']$//' \
107
+ | grep -v '^[[:space:]]*$' \
108
+ | awk '!seen[$0]++'
109
+ )
95
110
  fi
96
111
  [ ${#prompt_files[@]} -eq 0 ] && prompt_files=(CLAUDE.md AGENTS.md GEMINI.md)
97
112
 
@@ -116,6 +116,17 @@ Provision a new sibling by instantiating the GitHub template and customising it:
116
116
  --template myorg/my-template \
117
117
  --apply
118
118
 
119
+ # Pick the agent harness (it selects the prompt file that gets the seed:
120
+ # claude -> CLAUDE.md, colleague -> AGENTS.colleague.md,
121
+ # associate -> .pi/SYSTEM.md, qwen -> QWEN.md, acp -> AGENTS.md).
122
+ # A harness is not a backend: associate is backend colleague + model associate,
123
+ # qwen is backend acp + acp_command [qwen, --acp].
124
+ .claude/skills/guild/scripts/create.sh \
125
+ --agent agentculture/new-agent \
126
+ --desc "A Qwen Code sibling." \
127
+ --harness qwen \
128
+ --apply
129
+
119
130
  # Custom PyPI dist name (command + import package stay the repo name)
120
131
  .claude/skills/guild/scripts/create.sh \
121
132
  --agent agentculture/jetson \
@@ -4,17 +4,28 @@ set -euo pipefail
4
4
  #
5
5
  # Instantiates agentculture/culture-agent-template (or a caller-supplied
6
6
  # --template) for a new sibling agent, renames identifiers, writes a self-init
7
- # CLAUDE.md seed, configures the GitHub repo, pushes the genesis commit, and
7
+ # seed into the selected harness's prompt file, configures the GitHub repo,
8
+ # pushes the genesis commit, and
8
9
  # registers the agent in docs/skill-sources.md.
9
10
  #
10
11
  # Dry-run by default; --apply executes.
11
12
  #
12
13
  # Usage:
13
- # create.sh --agent OWNER/REPO --desc TEXT [--backend claude|acp]
14
+ # create.sh --agent OWNER/REPO --desc TEXT
15
+ # [--harness claude|colleague|associate|qwen|acp]
16
+ # [--backend claude|colleague|acp] [--model NAME]
17
+ # [--acp-command ARGV]
14
18
  # [--workspace-root DIR] [--template OWNER/REPO]
15
19
  # [--org agentculture] [--command NAME] [--pkg NAME]
16
20
  # [--dist NAME] [--apply] [--json]
17
21
  #
22
+ # --harness picks the agent harness the clone is provisioned for, and with it
23
+ # the prompt file that gets the seed: claude -> CLAUDE.md, colleague ->
24
+ # AGENTS.colleague.md, associate -> .pi/SYSTEM.md, qwen -> QWEN.md, acp ->
25
+ # AGENTS.md. A harness is NOT a backend: associate is backend colleague +
26
+ # model associate, and qwen is backend acp + acp_command [qwen, --acp], so
27
+ # --backend / --model / --acp-command are separate override fields.
28
+ #
18
29
  # The repo name is the repo/agent identity (README, culture.yaml suffix,
19
30
  # CLAUDE.md seed, repo URL). --command / --pkg / --dist each retarget one facet
20
31
  # independently and default to the repo name (or, for --pkg, the underscore form
@@ -0,0 +1 @@
1
+ template-supports-four-harnesses
@@ -0,0 +1 @@
1
+ template-supports-four-harnesses
@@ -0,0 +1,275 @@
1
+ {
2
+ "plan_slug": "template-supports-four-harnesses",
3
+ "schema_version": 2,
4
+ "created": "2026-09-06T15:31:30Z",
5
+ "updated": "2026-09-06T16:07:56Z",
6
+ "deviations": [
7
+ {
8
+ "id": "d1",
9
+ "what": "narrow h27 from 'portability-lint.sh --all passes' to 'portability-lint introduces no NEW hits vs main'",
10
+ "task_ref": "t4",
11
+ "reason": "portability-lint --all was ALREADY red on main: 5 pre-existing hits, all '~/.eidetic/memory' references in the vendored .claude/skills/recall/SKILL.md and remember/SKILL.md. Verified by extracting main into a clean tree and re-running (identical 5 failures); t4 independently confirmed by stashing. Patching them locally would violate the cite-don't-import policy (vendored-copy findings go upstream, they are not patched downstream), and guildmaster's own canonical copy carries the same references. The template's CI never runs portability-lint at all, so h27's third clause asserted something no gate enforced and which was already false when confirmed. Our arc DID add a 6th hit (AGENTS.override.md:5 referenced ~/.pi/agent/ literally) \u2014 that one was ours, is fixed and committed, and lint is back to exactly the 5 pre-existing. Operator chose the narrowed criterion over adding a ~/.eidetic/ carve-out upstream.",
12
+ "affects": [
13
+ "c36",
14
+ "h27"
15
+ ],
16
+ "origin": "user",
17
+ "status": "approved",
18
+ "classification": "acceptable",
19
+ "seq": 1
20
+ },
21
+ {
22
+ "id": "d2",
23
+ "what": "track .pi/settings.json with a repo-relative skills path instead of shipping only a byte-identical .example",
24
+ "task_ref": "t4",
25
+ "reason": "h25 (byte-identical to associate/.pi/settings.json) and h8 (each harness resolves the skills the template ships) are in direct conflict. Byte-identity forces {'skills':['~/.claude/skills']}, which breaks Pi twice in a fresh clone: /.pi/settings.json is gitignored and Pi reads .pi/settings.json not .example (Pi README:290-291 lists only ~/.pi/agent/settings.json and .pi/settings.json), and even hand-copied the path points at the OPERATOR's home skills rather than the repo's .claude/skills. t3 proved it empirically: plain 'pi -p list your loaded skills' returned only the operator's personal skills while 'pi --skill .claude/skills' returned all 19 vendored ones. Operator chose h8 over h25: track .pi/settings.json with the repo-relative path '.claude/skills', which also passes portability lint since it carries no ~/ prefix.",
26
+ "affects": [
27
+ "c33",
28
+ "h25",
29
+ "c4",
30
+ "h8"
31
+ ],
32
+ "origin": "user",
33
+ "status": "approved",
34
+ "classification": "acceptable",
35
+ "seq": 2
36
+ },
37
+ {
38
+ "id": "d3",
39
+ "what": "narrow c43/h6's 'steward doctor --scope self with 0 findings' to '0 HARNESS-RELATED findings' \u2014 same root cause as d1",
40
+ "task_ref": "t14",
41
+ "reason": "Ran steward doctor --scope self against a genuinely fresh clone of the template integration branch. It returns exactly ONE finding, and it is the 'portability' check reporting the same 5 pre-existing ~/.eidetic/memory references in the vendored recall/remember SKILL.md that deviation d1 already scoped out. Crucially there is NO backend-consistency finding and NO prompt-file-present finding \u2014 so the four-prompt-file clone declaring backend: claude passes both harness checks cleanly, which is what these criteria were actually written to test. The literal '0 findings' wording is unachievable for exactly the reason d1 established, but d1 was scoped to h27 so this needs its own record. Proposed, not self-approved.",
42
+ "affects": [
43
+ "c43",
44
+ "h6",
45
+ "c1",
46
+ "h1"
47
+ ],
48
+ "origin": "llm",
49
+ "status": "proposed",
50
+ "classification": "acceptable",
51
+ "seq": 3
52
+ },
53
+ {
54
+ "id": "d4",
55
+ "what": "wire Pi skills via a .pi/skills relative symlink and drop the inert .pi/settings.json \u2014 supersedes d2's settings-file approach",
56
+ "task_ref": "t14",
57
+ "reason": "d2 was approved on the premise that Pi reads a 'skills' array from .pi/settings.json. Syscall instrumentation against a fresh clone disproves it: settings.json alone opens 0 SKILL.md, 'pi --skill .claude/skills' opens 19, and a .pi/skills symlink with no flag opens 19. Pi's README documents 'skills' as a package.json MANIFEST key (the 'pi' block), not a settings.json key, and names .pi/skills/ among the conventional project skill directories. The fix is the same relative-symlink pattern already proven for .qwen/skills and .colleague/skills. My earlier claim that I had verified d2 by running Pi was based on the model's self-report, not instrumentation \u2014 filed as lapse l10.",
58
+ "affects": [
59
+ "t4",
60
+ "c33",
61
+ "h25",
62
+ "c4",
63
+ "h8"
64
+ ],
65
+ "origin": "llm",
66
+ "status": "proposed",
67
+ "classification": "acceptable",
68
+ "seq": 4
69
+ }
70
+ ],
71
+ "evidence": [
72
+ {
73
+ "id": "e1",
74
+ "obligation_ref": "o3",
75
+ "test_ref": "strace -f -e trace=openat pi (fresh clone of feat/four-harness-support)",
76
+ "behavior_text": "Pi opened .pi/SYSTEM.md and AGENTS.override.md, and opened CLAUDE.md ZERO times",
77
+ "contract_text": "each harness's prompt file is the filename that harness's own loader reads",
78
+ "evidence_type": "automated",
79
+ "strength": "execution",
80
+ "strength_basis": "syscall trace of a real Pi 0.84.2 run against a genuinely fresh clone \u2014 not a model self-report; a prior self-report-based check of the same wiring reached the wrong conclusion (lapse l10)",
81
+ "outcome": "pass",
82
+ "run": {
83
+ "timestamp": "2026-09-06T19:07:19+03:00",
84
+ "commit": "68b1d45"
85
+ },
86
+ "origin": "llm",
87
+ "status": "proposed",
88
+ "superseded": false,
89
+ "seq": 5
90
+ },
91
+ {
92
+ "id": "e2",
93
+ "obligation_ref": "o3",
94
+ "test_ref": "qwen --debug session log (fresh clone)",
95
+ "behavior_text": "QWEN.md appears 3x in Qwen Code's resolved context; CLAUDE.md appears 0x",
96
+ "contract_text": "each harness's prompt file is the filename that harness's own loader reads",
97
+ "evidence_type": "automated",
98
+ "strength": "execution",
99
+ "strength_basis": "Qwen Code 0.23.0's own debug log, its instrumentation not its answer",
100
+ "outcome": "pass",
101
+ "run": {
102
+ "timestamp": "2026-09-06T19:07:19+03:00",
103
+ "commit": "68b1d45"
104
+ },
105
+ "origin": "llm",
106
+ "status": "proposed",
107
+ "superseded": false,
108
+ "seq": 6
109
+ },
110
+ {
111
+ "id": "e3",
112
+ "obligation_ref": "o2",
113
+ "test_ref": "strace openat count of SKILL.md files (fresh clone)",
114
+ "behavior_text": "Pi opens 19 SKILL.md via the .pi/skills symlink with no --skill flag",
115
+ "contract_text": "each harness resolves the skills the template ships for it, proven by running it",
116
+ "evidence_type": "automated",
117
+ "strength": "execution",
118
+ "strength_basis": "19 distinct SKILL.md opens observed; the pre-fix .pi/settings.json configuration opened 0, which is how the inert-settings defect was found",
119
+ "outcome": "pass",
120
+ "run": {
121
+ "timestamp": "2026-09-06T19:07:19+03:00",
122
+ "commit": "68b1d45"
123
+ },
124
+ "origin": "llm",
125
+ "status": "proposed",
126
+ "superseded": false,
127
+ "seq": 7
128
+ },
129
+ {
130
+ "id": "e4",
131
+ "obligation_ref": "o2",
132
+ "test_ref": "qwen --debug '[SKILL_MANAGER] Loaded N project level skills'",
133
+ "behavior_text": "Qwen Code loads 19 project-level skills through the .qwen/skills symlink",
134
+ "contract_text": "each harness resolves the skills the template ships for it, proven by running it",
135
+ "evidence_type": "automated",
136
+ "strength": "execution",
137
+ "strength_basis": "the loader's own log line, in a fresh clone",
138
+ "outcome": "pass",
139
+ "run": {
140
+ "timestamp": "2026-09-06T19:07:19+03:00",
141
+ "commit": "68b1d45"
142
+ },
143
+ "origin": "llm",
144
+ "status": "proposed",
145
+ "superseded": false,
146
+ "seq": 8
147
+ },
148
+ {
149
+ "id": "e5",
150
+ "obligation_ref": "o2",
151
+ "test_ref": "colleague skills list --model Qwen/Qwen3-32B --repo . --json (fresh clone)",
152
+ "behavior_text": "colleague loads 0 of 19 skills from .colleague/skills \u2014 returns {\"skills\": []}",
153
+ "contract_text": "each harness resolves the skills the template ships for it, proven by running it",
154
+ "evidence_type": "automated",
155
+ "strength": "execution",
156
+ "strength_basis": "reproduced against colleague 1.76.0 by the task agent and independently by the main agent. Two upstream blockers: configdir.collect_files takes only direct FILE children so a nested skill directory is skipped, and layers._within rejects any symlink target leaving a .colleague/ root. Both fail silently at exit 0. Filed as agentculture/colleague#494. Control: colleague agents list resolves AGENTS.colleague.md in the same clone, so only the skills axis is broken",
157
+ "outcome": "fail",
158
+ "run": {
159
+ "timestamp": "2026-09-06T19:07:35+03:00",
160
+ "commit": "68b1d45"
161
+ },
162
+ "origin": "llm",
163
+ "status": "proposed",
164
+ "superseded": false,
165
+ "seq": 9
166
+ },
167
+ {
168
+ "id": "e6",
169
+ "obligation_ref": "o1",
170
+ "test_ref": "steward doctor --scope self <fresh clone> (steward 0.27.0 with the widened registry)",
171
+ "behavior_text": "exactly one finding \u2014 the pre-existing portability one; NO backend-consistency and NO prompt-file-present finding despite four prompt files present",
172
+ "contract_text": "a clone carrying four prompt files and declaring one backend produces zero backend-consistency findings",
173
+ "evidence_type": "automated",
174
+ "strength": "execution",
175
+ "strength_basis": "the literal '0 findings' wording is unreachable because 5 pre-existing ~/.eidetic references live in byte-verbatim vendored skills that policy forbids patching downstream \u2014 scoped out by deviations d1 and d3. The harness-relevant half is genuinely demonstrated",
176
+ "outcome": "pass",
177
+ "run": {
178
+ "timestamp": "2026-09-06T19:07:35+03:00",
179
+ "commit": "68b1d45"
180
+ },
181
+ "origin": "llm",
182
+ "status": "proposed",
183
+ "superseded": false,
184
+ "seq": 10
185
+ },
186
+ {
187
+ "id": "e7",
188
+ "obligation_ref": "o4",
189
+ "test_ref": "ACP initialize JSON-RPC handshake against 'qwen --acp' on stdio",
190
+ "behavior_text": "qwen --acp answers with protocolVersion 1 and agentInfo qwen-code 0.23.0",
191
+ "contract_text": "a clone declaring backend acp with acp_command [qwen, --acp] actually starts and answers through the Culture mesh",
192
+ "evidence_type": "automated",
193
+ "strength": "execution",
194
+ "strength_basis": "PARTIAL: the ACP transport a mesh resident depends on is proven, but NO round-trip through a running Culture mesh was performed. Filed as fail rather than pass because the contract says 'through the Culture mesh' and that half is unverified",
195
+ "outcome": "fail",
196
+ "run": {
197
+ "timestamp": "2026-09-06T19:07:35+03:00",
198
+ "commit": "68b1d45"
199
+ },
200
+ "origin": "llm",
201
+ "status": "proposed",
202
+ "superseded": false,
203
+ "seq": 11
204
+ },
205
+ {
206
+ "id": "e8",
207
+ "obligation_ref": "o5",
208
+ "test_ref": "tests/test_create_gate.py::test_broken_transform_blocks_genesis_commit",
209
+ "behavior_text": "a transform emitting a 258-char line yields EXIT_ENV_ERROR with no git commit, no git push and no configure-repo.sh",
210
+ "contract_text": "a deliberately broken transform is caught BEFORE the genesis commit",
211
+ "evidence_type": "automated",
212
+ "strength": "execution",
213
+ "strength_basis": "a REAL flake8 run over the clone tree, not a simulated non-zero exit; written first and watched fail. CAVEAT: only flake8 of the gate's nine checks is genuinely executed \u2014 the other eight are faked green by the injectable runner and verified for argv shape, ordering and fail-fast semantics only (lapse l8)",
214
+ "outcome": "pass",
215
+ "run": {
216
+ "timestamp": "2026-09-06T19:07:46+03:00",
217
+ "commit": "5478c28"
218
+ },
219
+ "origin": "llm",
220
+ "status": "proposed",
221
+ "superseded": false,
222
+ "seq": 12
223
+ },
224
+ {
225
+ "id": "e9",
226
+ "obligation_ref": "o6",
227
+ "test_ref": "tests/test_harness_smoke.py::test_smoke_fails_when_the_{claude,pi,qwen,colleague}_config_is_broken",
228
+ "behavior_text": "breaking any one harness config fails the smoke check while the other three still PASS",
229
+ "contract_text": "the smoke check exercises ALL FOUR harness configs and fails when any one is broken, demonstrated by breaking each in turn",
230
+ "evidence_type": "automated",
231
+ "strength": "execution",
232
+ "strength_basis": "four break tests written first and watched fail; each asserts non-zero exit AND that only the broken harness reports FAIL, so the check discriminates rather than collapsing. Seven further break tests cover the skills-discovery half",
233
+ "outcome": "pass",
234
+ "run": {
235
+ "timestamp": "2026-09-06T19:07:55+03:00",
236
+ "commit": "68b1d45"
237
+ },
238
+ "origin": "llm",
239
+ "status": "proposed",
240
+ "superseded": false,
241
+ "seq": 13
242
+ }
243
+ ],
244
+ "deltas": [
245
+ {
246
+ "id": "b1",
247
+ "kind": "removed",
248
+ "behavior_text": "colleague loads none of the template's skills; the nested .colleague/skills tree is shipped but unreadable by colleague 1.76.0",
249
+ "caused_by": [
250
+ "c32"
251
+ ],
252
+ "evidence_refs": [
253
+ "e5"
254
+ ],
255
+ "origin": "llm",
256
+ "status": "proposed",
257
+ "superseded": false
258
+ },
259
+ {
260
+ "id": "b2",
261
+ "kind": "added",
262
+ "behavior_text": "guild show accepts list-valued registry prompts; it previously raised TypeError on the widened shape",
263
+ "caused_by": [
264
+ "c48"
265
+ ],
266
+ "evidence_refs": [
267
+ "e6"
268
+ ],
269
+ "origin": "llm",
270
+ "status": "proposed",
271
+ "superseded": false
272
+ }
273
+ ],
274
+ "supersessions": []
275
+ }