ticketwright 4.0.2__tar.gz → 4.0.3__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 (133) hide show
  1. {ticketwright-4.0.2 → ticketwright-4.0.3}/CHANGELOG.md +14 -0
  2. {ticketwright-4.0.2 → ticketwright-4.0.3}/PKG-INFO +31 -1
  3. {ticketwright-4.0.2 → ticketwright-4.0.3}/README.md +30 -0
  4. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/selftest.sh +43 -0
  5. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/AGENTS.md.tmpl +10 -0
  6. {ticketwright-4.0.2 → ticketwright-4.0.3}/ticketwright/__init__.py +1 -1
  7. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/agents/qc-reviewer.md +0 -0
  8. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/commands/.gitkeep +0 -0
  9. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/connections.example.yaml +0 -0
  10. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.asana-bq.yaml +0 -0
  11. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.azure.yaml +0 -0
  12. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.multi-audience.yaml +0 -0
  13. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.multi-warehouse.yaml +0 -0
  14. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.no-warehouse.yaml +0 -0
  15. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.example.solo.yaml +0 -0
  16. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.schema.md +0 -0
  17. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/stack.yaml +0 -0
  18. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/config/viewer.example.yaml +0 -0
  19. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/_stack.py +0 -0
  20. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/db_write_guard.py +0 -0
  21. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/regenerate_ticket_index.py +0 -0
  22. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/session_context.py +0 -0
  23. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/source_material_guard.py +0 -0
  24. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/hooks/ticket_index_context.py +0 -0
  25. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/settings.json.tmpl +0 -0
  26. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/refresh/SKILL.md +0 -0
  27. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/refresh/context-pack.md +0 -0
  28. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/refresh/index.md +0 -0
  29. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/review/SKILL.md +0 -0
  30. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/SKILL.md +0 -0
  31. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/adopt.md +0 -0
  32. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/interview.md +0 -0
  33. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/scaffold.md +0 -0
  34. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/teammate.md +0 -0
  35. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/setup/voice.md +0 -0
  36. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/ship/SKILL.md +0 -0
  37. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/skillify/SKILL.md +0 -0
  38. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/skillify/authoring.md +0 -0
  39. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/spec-and-build/SKILL.md +0 -0
  40. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/ticket/SKILL.md +0 -0
  41. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/skills/ticket/priming.md +0 -0
  42. {ticketwright-4.0.2 → ticketwright-4.0.3}/.claude/statusline.sh +0 -0
  43. {ticketwright-4.0.2 → ticketwright-4.0.3}/.gitignore +0 -0
  44. {ticketwright-4.0.2 → ticketwright-4.0.3}/LICENSE +0 -0
  45. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/README.md +0 -0
  46. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/chat/gmail.md +0 -0
  47. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/chat/outlook.md +0 -0
  48. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/chat/slack.md +0 -0
  49. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/chat/teams.md +0 -0
  50. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/docstore/gdrive.md +0 -0
  51. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/docstore/rclone.md +0 -0
  52. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/docstore/sharepoint.md +0 -0
  53. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/meetings/fireflies.md +0 -0
  54. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/meetings/granola.md +0 -0
  55. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/meetings/notion.md +0 -0
  56. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/meetings/teams.md +0 -0
  57. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/meetings/zoom.md +0 -0
  58. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/antigravity.md +0 -0
  59. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/claude-code.md +0 -0
  60. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/cline.md +0 -0
  61. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/codex-cli.md +0 -0
  62. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/cursor.md +0 -0
  63. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/devin.md +0 -0
  64. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/runtime/opencode.md +0 -0
  65. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/asana.md +0 -0
  66. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/azure-devops.md +0 -0
  67. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/github-issues.md +0 -0
  68. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/jira.md +0 -0
  69. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/linear.md +0 -0
  70. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/local.md +0 -0
  71. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/tracker/monday.md +0 -0
  72. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/vcs/azure-repos.md +0 -0
  73. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/vcs/github.md +0 -0
  74. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/vcs/gitlab.md +0 -0
  75. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/viewer/macos-open.md +0 -0
  76. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/viewer/windows-start.md +0 -0
  77. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/viewer/xdg-open.md +0 -0
  78. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/bigquery.md +0 -0
  79. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/databricks.md +0 -0
  80. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/postgres.md +0 -0
  81. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/redshift.md +0 -0
  82. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/snowflake.md +0 -0
  83. {ticketwright-4.0.2 → ticketwright-4.0.3}/adapters/warehouse/synapse.md +0 -0
  84. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/_yamlite.py +0 -0
  85. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/build_ticket_index.py +0 -0
  86. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/bump_version.sh +0 -0
  87. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/delivery_plan.py +0 -0
  88. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/effective_config.py +0 -0
  89. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/emit_runtime.py +0 -0
  90. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/enrich_ticket.py +0 -0
  91. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/handoff.sh +0 -0
  92. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/hook_shim.py +0 -0
  93. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/ingest_index_records.py +0 -0
  94. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/install.sh +0 -0
  95. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/kit_paths.py +0 -0
  96. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/meeting_refs.py +0 -0
  97. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/opencode_tool_gate.js +0 -0
  98. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/plugin_doctor.py +0 -0
  99. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/recall.py +0 -0
  100. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/render.sh +0 -0
  101. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/render_and_validate.sh +0 -0
  102. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/resolve_user.py +0 -0
  103. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/scan_source_materials.py +0 -0
  104. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/split_and_export.sh +0 -0
  105. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/sql_scan.py +0 -0
  106. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/tw +0 -0
  107. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/update_notice.py +0 -0
  108. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/verify_stack.sh +0 -0
  109. {ticketwright-4.0.2 → ticketwright-4.0.3}/bin/whoami.py +0 -0
  110. {ticketwright-4.0.2 → ticketwright-4.0.3}/pyproject.toml +0 -0
  111. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/CLAUDE.md.tmpl +0 -0
  112. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/SKILL.md.tmpl +0 -0
  113. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/bin/drift_check.sh +0 -0
  114. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/golden/example.json +0 -0
  115. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/sql/qc.sql.tmpl +0 -0
  116. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/sql/step.sql.tmpl +0 -0
  117. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/templates/README.md.tmpl +0 -0
  118. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/generated-skill/templates/tracker_comment.txt.tmpl +0 -0
  119. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/gitignore.tmpl +0 -0
  120. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/person.yaml.tmpl +0 -0
  121. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/plan.md.tmpl +0 -0
  122. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/project-README.md.tmpl +0 -0
  123. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/roles/analyst.md +0 -0
  124. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/roles/engineer.md +0 -0
  125. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/roles/generalist.md +0 -0
  126. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/roles/scientist.md +0 -0
  127. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/spec.md.tmpl +0 -0
  128. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/ticket-README.md.tmpl +0 -0
  129. {ticketwright-4.0.2 → ticketwright-4.0.3}/templates/voice-profile.md.tmpl +0 -0
  130. {ticketwright-4.0.2 → ticketwright-4.0.3}/tests/emit/README.md +0 -0
  131. {ticketwright-4.0.2 → ticketwright-4.0.3}/tests/meeting_refs/README.md +0 -0
  132. {ticketwright-4.0.2 → ticketwright-4.0.3}/tests/source_materials/README.md +0 -0
  133. {ticketwright-4.0.2 → ticketwright-4.0.3}/ticketwright/cli.py +0 -0
@@ -4,6 +4,20 @@ All notable changes to this project are documented here. Format loosely follows
4
4
  [Keep a Changelog](https://keepachangelog.com/); this project uses semantic-ish versioning.
5
5
 
6
6
 
7
+ ## [4.0.3] — 2026-09-03
8
+
9
+ ### Added
10
+ - **A prompt you can paste, for each track.** The person who most needs Ticketwright installed has
11
+ no plugin yet, so no `/setup` and no skill to ask — and every onboarding session so far opened
12
+ with someone improvising the words. Track 1 and Track 2 now each lead with a short prompt in a
13
+ copyable block: hand it to an agent and it does the track. They stay short on purpose. The doctor
14
+ already prints each fix at the moment it applies, so a prompt that restated them would be a
15
+ second copy to drift; what they carry instead is the part no tool enforces — "this repo only, not
16
+ globally", and, for Track 1, that the `setup` interview belongs to the person rather than to an
17
+ agent guessing the stack from whatever is installed. The joiner prompt also ships in
18
+ `templates/AGENTS.md.tmpl`, so it lands in every configured repo, and selftest pins the two copies
19
+ byte-identical.
20
+
7
21
  ## [4.0.2] — 2026-09-03
8
22
 
9
23
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ticketwright
3
- Version: 4.0.2
3
+ Version: 4.0.3
4
4
  Summary: Tool-agnostic AI layer for ticket-driven work repos: prior-art recall, object reverse-index, deep QC, and a self-maintaining ticket index. Stdlib-only, no vector store.
5
5
  Project-URL: Homepage, https://github.com/kyle-chalmers/ticketwright
6
6
  Project-URL: Repository, https://github.com/kyle-chalmers/ticketwright
@@ -153,6 +153,21 @@ carries its own one-line check, so a stall is diagnosable instead of mysterious.
153
153
 
154
154
  ### Track 1 — Setting up a repo
155
155
 
156
+ **Hand it to your agent.** Paste this into a Claude Code session opened on the repo, and the
157
+ five steps below happen with you answering rather than driving:
158
+
159
+ ```text
160
+ Set up Ticketwright in this repo for my whole team. Install it at project scope
161
+ from the repo root, get me to restart so the skills load, then run
162
+ /ticketwright:setup and put its questions to me rather than answering them
163
+ yourself - it's asking about my team's tools and my identity. Show me the file
164
+ list before committing anything.
165
+ ```
166
+
167
+ The prompt keeps the interview yours on purpose: `setup` asks about your team's tools and who
168
+ you are, and an agent that infers those from whatever is installed on the machine writes a
169
+ confidently wrong `stack.yaml`. To drive it by hand instead, follow the steps:
170
+
156
171
  **1 · Install the plugin at project scope**, from inside the repo you want to work tickets in:
157
172
 
158
173
  ```bash
@@ -254,6 +269,21 @@ start, but does NOT install the plugin.** Verified live: a teammate's `installed
254
269
  stayed `{}` across restarts until the manual install in step 2. Skip step 2 and
255
270
  `/ticketwright:setup` is not a command that exists.
256
271
 
272
+ **Hand it to your agent.** Paste this into a Claude Code session opened on the repo — it works
273
+ the checklist below for you, in order:
274
+
275
+ ```text
276
+ Install the Ticketwright plugin for this repo. Start with:
277
+ python3 ~/.claude/plugins/marketplaces/ticketwright/bin/plugin_doctor.py
278
+ Follow its fixes in order. I want it installed for this repo only, not globally.
279
+ If a check fails in a way its fix doesn't cover, stop and tell me instead of
280
+ working around it. When it's clean, tell me how to restart.
281
+ ```
282
+
283
+ The prompt stays short because the doctor carries the detail: every check prints its own fix,
284
+ so there is one copy of each instruction rather than two that drift. The rest of this track is
285
+ what that prompt makes happen — read on to drive it yourself, or when an agent gets stuck.
286
+
257
287
  #### If you are the agent helping someone install — read this first
258
288
 
259
289
  One command answers most of what follows. The marketplace clone lands on disk as soon as the person
@@ -129,6 +129,21 @@ carries its own one-line check, so a stall is diagnosable instead of mysterious.
129
129
 
130
130
  ### Track 1 — Setting up a repo
131
131
 
132
+ **Hand it to your agent.** Paste this into a Claude Code session opened on the repo, and the
133
+ five steps below happen with you answering rather than driving:
134
+
135
+ ```text
136
+ Set up Ticketwright in this repo for my whole team. Install it at project scope
137
+ from the repo root, get me to restart so the skills load, then run
138
+ /ticketwright:setup and put its questions to me rather than answering them
139
+ yourself - it's asking about my team's tools and my identity. Show me the file
140
+ list before committing anything.
141
+ ```
142
+
143
+ The prompt keeps the interview yours on purpose: `setup` asks about your team's tools and who
144
+ you are, and an agent that infers those from whatever is installed on the machine writes a
145
+ confidently wrong `stack.yaml`. To drive it by hand instead, follow the steps:
146
+
132
147
  **1 · Install the plugin at project scope**, from inside the repo you want to work tickets in:
133
148
 
134
149
  ```bash
@@ -230,6 +245,21 @@ start, but does NOT install the plugin.** Verified live: a teammate's `installed
230
245
  stayed `{}` across restarts until the manual install in step 2. Skip step 2 and
231
246
  `/ticketwright:setup` is not a command that exists.
232
247
 
248
+ **Hand it to your agent.** Paste this into a Claude Code session opened on the repo — it works
249
+ the checklist below for you, in order:
250
+
251
+ ```text
252
+ Install the Ticketwright plugin for this repo. Start with:
253
+ python3 ~/.claude/plugins/marketplaces/ticketwright/bin/plugin_doctor.py
254
+ Follow its fixes in order. I want it installed for this repo only, not globally.
255
+ If a check fails in a way its fix doesn't cover, stop and tell me instead of
256
+ working around it. When it's clean, tell me how to restart.
257
+ ```
258
+
259
+ The prompt stays short because the doctor carries the detail: every check prints its own fix,
260
+ so there is one copy of each instruction rather than two that drift. The rest of this track is
261
+ what that prompt makes happen — read on to drive it yourself, or when an agent gets stuck.
262
+
233
263
  #### If you are the agent helping someone install — read this first
234
264
 
235
265
  One command answers most of what follows. The marketplace clone lands on disk as soon as the person
@@ -1259,6 +1259,49 @@ s21step "$T2" '**1 · ' '**2 · ' | grep -q 'git clone' \
1259
1259
  && ok "README Track 2 step 1 says git clone (not 'download')" \
1260
1260
  || bad "Track 2 step 1 must tell the joiner to git clone — a Download-ZIP folder has no .git"
1261
1261
 
1262
+ # (g) the paste-able install prompts. A person who has just cloned has no plugin, so no skill and no
1263
+ # /setup — the only thing that always works is text they can paste into a chat box. Both prompts
1264
+ # stay SHORT on purpose: the doctor prints each fix at the moment it applies, so a prompt that
1265
+ # restated them would be a second copy to drift. What the prompt must carry is the part no tool
1266
+ # enforces — "this repo only" (an agent that runs the bare install goes global) and, for Track 1,
1267
+ # that the interview belongs to the person (an agent inferring the stack writes it wrong).
1268
+ python3 - README.md templates/AGENTS.md.tmpl >"$TMP/s21b-prompts.out" 2>&1 <<'PYPROMPT'
1269
+ import sys
1270
+ def blocks(path):
1271
+ out, cur, infence = [], [], False
1272
+ for l in open(path, encoding="utf-8").read().splitlines():
1273
+ if l.startswith("```text"):
1274
+ infence, cur = True, []
1275
+ continue
1276
+ if infence and l.startswith("```"):
1277
+ out.append("\n".join(cur)); infence = False
1278
+ continue
1279
+ if infence: cur.append(l)
1280
+ return out
1281
+ readme, tmpl = blocks(sys.argv[1]), blocks(sys.argv[2])
1282
+ bad = []
1283
+ t1 = [b for b in readme if b.startswith("Set up Ticketwright in this repo")]
1284
+ t2 = [b for b in readme if b.startswith("Install the Ticketwright plugin for this repo")]
1285
+ if len(t1) != 1: bad.append("README has %d Track 1 prompt blocks, want 1" % len(t1))
1286
+ if len(t2) != 1: bad.append("README has %d Track 2 prompt blocks, want 1" % len(t2))
1287
+ if t1 and "put its questions to me" not in t1[0]:
1288
+ bad.append("the Track 1 prompt no longer keeps the interview with the person")
1289
+ if t2:
1290
+ if "this repo only, not globally" not in t2[0]:
1291
+ bad.append("the Track 2 prompt no longer says this repo only")
1292
+ if "plugin_doctor.py" not in t2[0]:
1293
+ bad.append("the Track 2 prompt no longer starts at the doctor")
1294
+ if not [b for b in tmpl if b.strip() == t2[0].strip()]:
1295
+ bad.append("templates/AGENTS.md.tmpl's joiner prompt is not byte-identical to README's")
1296
+ for name, b in (("Track 1", t1), ("Track 2", t2)):
1297
+ if b and len(b[0].splitlines()) > 8:
1298
+ bad.append("%s prompt is %d lines — keep it short enough to paste" % (name, len(b[0].splitlines())))
1299
+ print(" | ".join(bad))
1300
+ PYPROMPT
1301
+ [ -z "$(cat "$TMP/s21b-prompts.out")" ] \
1302
+ && ok "both paste-able install prompts are present, short, and identical across README and the AGENTS template" \
1303
+ || bad "an install prompt drifted, grew, or lost the rule no tool enforces" "$(cat "$TMP/s21b-prompts.out")"
1304
+
1262
1305
  hdr "22 · Obsidian graph config (.obsidian/graph.json)"
1263
1306
  GC="$TMP/graphcfg"; mkdir -p "$GC/.claude/config" "$GC/tickets/a/ENG-1" "$GC/tickets/a/ENG-2"
1264
1307
  printf 'project:\n key_prefix: ENG\n' > "$GC/.claude/config/stack.yaml"
@@ -49,6 +49,16 @@ The plugin ref is `ticketwright@ticketwright` and the marketplace URL is
49
49
  section. Registering the marketplace is not installing the plugin — a teammate who opens and trusts
50
50
  the repo gets the marketplace clone, then runs the install themselves (Track 2).
51
51
 
52
+ The person you are helping can hand you this and you have everything you need:
53
+
54
+ ```text
55
+ Install the Ticketwright plugin for this repo. Start with:
56
+ python3 ~/.claude/plugins/marketplaces/ticketwright/bin/plugin_doctor.py
57
+ Follow its fixes in order. I want it installed for this repo only, not globally.
58
+ If a check fails in a way its fix doesn't cover, stop and tell me instead of
59
+ working around it. When it's clean, tell me how to restart.
60
+ ```
61
+
52
62
  One command reports every check below with its fix, and runs before anything is installed, from the
53
63
  marketplace clone that lands on disk when the repo is trusted:
54
64
 
@@ -6,4 +6,4 @@ This package is the PyPI distribution: a stdlib-only CLI that scaffolds the kit
6
6
  bundled under `ticketwright/_kit/`. The Claude Code plugin and `cp -r` install paths are unchanged.
7
7
  """
8
8
 
9
- __version__ = "4.0.2"
9
+ __version__ = "4.0.3"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes