ticketwright 2.0.0__py3-none-any.whl

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 (89) hide show
  1. ticketwright/__init__.py +9 -0
  2. ticketwright/_kit/.claude/agents/qc-reviewer.md +50 -0
  3. ticketwright/_kit/.claude/commands/build-context-pack.md +8 -0
  4. ticketwright/_kit/.claude/commands/build-ticket-index.md +8 -0
  5. ticketwright/_kit/.claude/commands/configure-workspace.md +8 -0
  6. ticketwright/_kit/.claude/commands/deliver-ticket.md +8 -0
  7. ticketwright/_kit/.claude/commands/onboard-teammate.md +8 -0
  8. ticketwright/_kit/.claude/commands/prime-domain.md +8 -0
  9. ticketwright/_kit/.claude/commands/prime-ticket.md +8 -0
  10. ticketwright/_kit/.claude/commands/prime-warehouse.md +8 -0
  11. ticketwright/_kit/.claude/commands/productize-workflow.md +8 -0
  12. ticketwright/_kit/.claude/commands/qc-review.md +8 -0
  13. ticketwright/_kit/.claude/commands/recall.md +8 -0
  14. ticketwright/_kit/.claude/commands/start-ticket.md +8 -0
  15. ticketwright/_kit/.claude/config/stack.example.asana-bq.yaml +67 -0
  16. ticketwright/_kit/.claude/config/stack.example.azure.yaml +73 -0
  17. ticketwright/_kit/.claude/config/stack.schema.md +76 -0
  18. ticketwright/_kit/.claude/config/stack.yaml +76 -0
  19. ticketwright/_kit/.claude/hooks/db_write_guard.py +145 -0
  20. ticketwright/_kit/.claude/hooks/regenerate_ticket_index.py +74 -0
  21. ticketwright/_kit/.claude/hooks/session_context.py +78 -0
  22. ticketwright/_kit/.claude/hooks/ticket_index_context.py +99 -0
  23. ticketwright/_kit/.claude/settings.json.tmpl +59 -0
  24. ticketwright/_kit/.claude/skills/productize/SKILL.md +58 -0
  25. ticketwright/_kit/.claude/skills/productize/authoring.md +36 -0
  26. ticketwright/_kit/.claude/skills/refresh/SKILL.md +40 -0
  27. ticketwright/_kit/.claude/skills/refresh/context-pack.md +34 -0
  28. ticketwright/_kit/.claude/skills/refresh/index.md +45 -0
  29. ticketwright/_kit/.claude/skills/review/SKILL.md +76 -0
  30. ticketwright/_kit/.claude/skills/setup/SKILL.md +59 -0
  31. ticketwright/_kit/.claude/skills/setup/adopt.md +43 -0
  32. ticketwright/_kit/.claude/skills/setup/scaffold.md +38 -0
  33. ticketwright/_kit/.claude/skills/setup/teammate.md +33 -0
  34. ticketwright/_kit/.claude/skills/ship/SKILL.md +53 -0
  35. ticketwright/_kit/.claude/skills/spec-and-build/SKILL.md +54 -0
  36. ticketwright/_kit/.claude/skills/ticket/SKILL.md +59 -0
  37. ticketwright/_kit/.claude/skills/ticket/priming.md +47 -0
  38. ticketwright/_kit/.claude/statusline.sh +22 -0
  39. ticketwright/_kit/adapters/README.md +103 -0
  40. ticketwright/_kit/adapters/chat/slack.md +46 -0
  41. ticketwright/_kit/adapters/chat/teams.md +38 -0
  42. ticketwright/_kit/adapters/docstore/gdrive.md +39 -0
  43. ticketwright/_kit/adapters/docstore/sharepoint.md +41 -0
  44. ticketwright/_kit/adapters/tracker/asana.md +55 -0
  45. ticketwright/_kit/adapters/tracker/azure-devops.md +68 -0
  46. ticketwright/_kit/adapters/tracker/github-issues.md +59 -0
  47. ticketwright/_kit/adapters/tracker/jira.md +71 -0
  48. ticketwright/_kit/adapters/tracker/linear.md +56 -0
  49. ticketwright/_kit/adapters/tracker/monday.md +62 -0
  50. ticketwright/_kit/adapters/vcs/azure-repos.md +58 -0
  51. ticketwright/_kit/adapters/vcs/github.md +55 -0
  52. ticketwright/_kit/adapters/vcs/gitlab.md +52 -0
  53. ticketwright/_kit/adapters/warehouse/bigquery.md +44 -0
  54. ticketwright/_kit/adapters/warehouse/databricks.md +58 -0
  55. ticketwright/_kit/adapters/warehouse/postgres.md +44 -0
  56. ticketwright/_kit/adapters/warehouse/redshift.md +49 -0
  57. ticketwright/_kit/adapters/warehouse/snowflake.md +54 -0
  58. ticketwright/_kit/adapters/warehouse/synapse.md +52 -0
  59. ticketwright/_kit/bin/build_ticket_index.py +498 -0
  60. ticketwright/_kit/bin/enrich_ticket.py +138 -0
  61. ticketwright/_kit/bin/ingest_index_records.py +149 -0
  62. ticketwright/_kit/bin/recall.py +268 -0
  63. ticketwright/_kit/bin/render.sh +54 -0
  64. ticketwright/_kit/bin/render_and_validate.sh +139 -0
  65. ticketwright/_kit/bin/selftest.sh +408 -0
  66. ticketwright/_kit/bin/split_and_export.sh +138 -0
  67. ticketwright/_kit/bin/verify_stack.sh +74 -0
  68. ticketwright/_kit/templates/AGENTS.md.tmpl +74 -0
  69. ticketwright/_kit/templates/gitignore.tmpl +35 -0
  70. ticketwright/_kit/templates/plan.md.tmpl +22 -0
  71. ticketwright/_kit/templates/productized-skill/SKILL.md.tmpl +67 -0
  72. ticketwright/_kit/templates/productized-skill/bin/drift_check.sh +30 -0
  73. ticketwright/_kit/templates/productized-skill/golden/example.json +13 -0
  74. ticketwright/_kit/templates/productized-skill/sql/qc.sql.tmpl +21 -0
  75. ticketwright/_kit/templates/productized-skill/sql/step.sql.tmpl +20 -0
  76. ticketwright/_kit/templates/productized-skill/templates/README.md.tmpl +20 -0
  77. ticketwright/_kit/templates/productized-skill/templates/tracker_comment.txt.tmpl +14 -0
  78. ticketwright/_kit/templates/roles/analyst.md +6 -0
  79. ticketwright/_kit/templates/roles/engineer.md +6 -0
  80. ticketwright/_kit/templates/roles/generalist.md +3 -0
  81. ticketwright/_kit/templates/roles/scientist.md +5 -0
  82. ticketwright/_kit/templates/spec.md.tmpl +34 -0
  83. ticketwright/_kit/templates/ticket-README.md.tmpl +29 -0
  84. ticketwright/cli.py +115 -0
  85. ticketwright-2.0.0.dist-info/METADATA +139 -0
  86. ticketwright-2.0.0.dist-info/RECORD +89 -0
  87. ticketwright-2.0.0.dist-info/WHEEL +4 -0
  88. ticketwright-2.0.0.dist-info/entry_points.txt +2 -0
  89. ticketwright-2.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: setup
3
+ description: Set up Ticketwright in a repo — detect your tools, ask at most 5 questions, write the config, scaffold folders. Also onboards a teammate (--teammate) and adopts existing repos.
4
+ argument-hint: "(none) | --teammate [name] | <seam-to-add: chat|docstore|warehouse>"
5
+ allowed-tools: [Read, Write, Edit, Bash, Glob, AskUserQuestion]
6
+ disable-model-invocation: true
7
+ ---
8
+
9
+ # /setup
10
+
11
+ One skill, three jobs: **configure a repo** (run once), **add a tool later** (`/setup chat`), and
12
+ **onboard a person** (`/setup --teammate`). Detect first, ask last: the goal is a working setup
13
+ after **at most 5 questions**.
14
+
15
+ ## Mode: `--teammate` — onboard a person to an already-configured repo
16
+ Follow [teammate.md](teammate.md): install checklist → per-tool auth walk-through → verify →
17
+ read-the-map → guided first-ticket dry run. Requires an existing `stack.yaml`.
18
+
19
+ ## Mode: `<seam>` — add one tool to an existing config
20
+ E.g. `/setup chat`. Detect candidates for just that seam, ask one question, add the seam block to
21
+ `stack.yaml`, verify it, and re-render `AGENTS.md`. Nothing else changes.
22
+
23
+ ## Default mode — configure the repo
24
+
25
+ ### Phase 1 — Detect (no questions yet)
26
+ 1. **CLIs:** `!for c in snow acli gh glab bq databricks yq jq git; do command -v $c >/dev/null && echo "✓ $c" || echo "– $c"; done`
27
+ 2. **MCP servers** connected this session (tracker / chat / warehouse servers).
28
+ 3. **Existing state:** if `.claude/config/stack.yaml` exists → offer to edit, don't overwrite.
29
+ If the repo already has ticket folders, an index, or custom `.claude/commands` → this is an
30
+ **existing repo**: switch to [adopt.md](adopt.md) (map onto what's there; write MIGRATION.md).
31
+
32
+ ### Phase 2 — Ask (≤ 5 questions, detected options pre-selected, defaults visible)
33
+ One AskUserQuestion round covering only:
34
+ 1. **Tracker** (detected options first);
35
+ 2. **Warehouse** (or *none* — non-data repos are fine);
36
+ 3. **VCS**;
37
+ 4. **Ticket key prefix** (e.g. `ENG`) — and accept the tracker's project key as the default;
38
+ 5. **Assignee folder name** (default: the user's short name).
39
+ Everything else ships as a **commented default** the user can edit later: chat + docstore seams
40
+ (add via `/setup chat` / `/setup docstore`), `default_epic`, `terminal_status` (default `Done`),
41
+ word limits, role (`generalist`), and all 9 policies at their defaults. Each chosen tool's required
42
+ keys (per its adapter's `requires:` frontmatter): take the detected value where possible; otherwise
43
+ include the key commented with a `# TODO` and keep going — `verify` will point at it.
44
+
45
+ ### Phase 3 — Write & scaffold
46
+ 4. Compose `.claude/config/stack.yaml` per `stack.schema.md` (chosen seams live; optional seams as
47
+ commented blocks; the 9 policies with a one-line "when to change this" comment each). Warn if a
48
+ chosen adapter is `status: stub`.
49
+ 5. Scaffold the repo per [scaffold.md](scaffold.md): render `AGENTS.md` (+ role focus),
50
+ `.claude/settings.json` (hooks + read-only CLI allows), folders, `.gitignore` (with the
51
+ anchored `**/final_deliverables/*.csv` export guard), the AI-layer index, and the seeded ticket
52
+ index.
53
+
54
+ ### Phase 4 — Verify & hand off
55
+ 6. Run `!bash "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/selftest.sh"` (kit integrity — a failure here is fatal) and
56
+ `!bash "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/verify_stack.sh"` (per-seam reachability — an unreachable seam is
57
+ **not** fatal at setup time; print its adapter's auth notes as the fix).
58
+ 7. **Report:** the chosen stack, files written, any `# TODO` keys or stub adapters, and the next
59
+ step — `/ticket <id>` to start work, or `/setup --teammate` for a new person.
@@ -0,0 +1,43 @@
1
+ # Adopt mode — set up Ticketwright on a repo that already has ticket work
2
+
3
+ Triggered automatically when Phase 1 detection finds an existing repo: ticket-looking folders
4
+ (`tickets/**` or similar), an existing `INDEX.md`, an `AGENTS.md`/`CLAUDE.md`, or custom
5
+ `.claude/commands` / `.claude/skills`. The rule: **map onto what exists — never scaffold over it,
6
+ never demand a rewrite.**
7
+
8
+ ## 1 · Inventory what's there (read-only)
9
+ - **Ticket layout:** find the ticket folders and infer `project.ticket_path` from the observed
10
+ structure (e.g. `tickets/{assignee}/{id}`), the key prefix(es) from folder names, and the
11
+ assignee dirs. Confirm the inference with the user in ONE question.
12
+ - **Tools in use:** infer seams from evidence — CI configs, helper scripts, MCP servers, CLIs on
13
+ PATH, existing docs. Pre-select these in the (still ≤5-question) interview.
14
+ - **Custom commands/skills:** list everything in `.claude/commands/` and `.claude/skills/` and
15
+ classify each against the plugin's skills: **shadows** (does what a plugin skill does),
16
+ **extends** (domain-specific variant — e.g. a warehouse-specific spec/build flow), or
17
+ **unrelated** (keep as-is).
18
+ - **Existing rules file:** if `AGENTS.md`/`CLAUDE.md` exists, do NOT overwrite it.
19
+
20
+ ## 2 · Write config from observed reality
21
+ Compose `stack.yaml` from the inventory + interview answers. Point `project.*` at the *existing*
22
+ layout. Skip any scaffold step whose target already exists (folders, `.gitignore` — merge new rules
23
+ in, never replace).
24
+
25
+ ## 3 · Non-destructive scaffold
26
+ - `AGENTS.md` exists → render the template to `AGENTS.ticketwright.md` instead and note the diff
27
+ worth merging (the stack table, the policies, the lifecycle line). The human merges.
28
+ - Ticket index: seed `index_data.json` only if absent; then `/refresh index --all` to bootstrap
29
+ the catalog over the existing backlog (deterministic render first, curated enrichment after).
30
+
31
+ ## 4 · Write `MIGRATION.md` (the adoption checklist)
32
+ One row per finding, with a recommendation:
33
+ | Item | Classification | Recommendation |
34
+ |---|---|---|
35
+ | custom `start-work.md` command | shadows `/ticket` | **replace** — plugin covers it; delete after a trial ticket |
36
+ | custom warehouse-specific spec/build flow | extends `/spec-and-build` | **keep** — domain-optimized; note it in AGENTS.md |
37
+ | hand-maintained rules file | overlaps rendered AGENTS.md | **merge** — adopt the stack table + policies block |
38
+ Include: what was auto-configured, what needs a human decision, and the suggested trial — run ONE
39
+ real ticket through `/ticket → /review → /ship` before deleting anything custom.
40
+
41
+ ## 5 · Verify & report
42
+ Same as Phase 4 of the default mode (selftest + verify_stack). The report leads with the
43
+ MIGRATION.md path and the trial-ticket suggestion — adoption is incremental by design.
@@ -0,0 +1,38 @@
1
+ # Scaffold details — what `/setup` writes into a fresh repo
2
+
3
+ ## Global rules (`AGENTS.md`)
4
+ Render `templates/AGENTS.md.tmpl` → `AGENTS.md` (tokens from `stack.yaml`: tool names, key_prefix,
5
+ terminal_status, word limits, policies). Fill `{{role_focus}}` from `templates/roles/<role>.md`
6
+ using `project.role` (`generalist` unless the user changed it). This is the always-loaded tier —
7
+ keep it the rendered template; repo-specific rules get added by humans over time.
8
+
9
+ ## Hooks + settings (`.claude/settings.json`)
10
+ Render `.claude/settings.json.tmpl` → `.claude/settings.json`, keeping the `hooks` block:
11
+ - **PreToolUse** `db_write_guard.py` — makes `db_write_requires_approval` mechanical: asks before
12
+ any destructive warehouse statement, even one hidden in a `-f` file;
13
+ - **SessionStart** `session_context.py` + `ticket_index_context.py` — primes each session with the
14
+ stack + the ticket catalog;
15
+ - **PostToolUse** `regenerate_ticket_index.py` — keeps `tickets/INDEX.md` fresh on folder changes;
16
+ plus the statusline. Then append the chosen warehouse/tracker/vcs **read-only** CLI allows to
17
+ `permissions.allow` (e.g. `Bash(<warehouse_cli> …:*)`). Confirm `.claude/hooks/` and
18
+ `.claude/statusline.sh` are present (plugin installs run them from `${CLAUDE_PLUGIN_ROOT}`).
19
+
20
+ ## Folders + `.gitignore`
21
+ Create `tickets/{assignee_dir}/`, `documentation/`, `resources/`, `specs/` (and `ci/` if wanted).
22
+ Render `templates/gitignore.tmpl` → `.gitignore` (merge if one exists). It ships the **anchored**
23
+ `**/final_deliverables/*.csv` rule so ticket exports (customer data) can't be silently committed at
24
+ any depth — *exports go to the docstore, not git*. If the tracker adapter ships an
25
+ attachment-download helper, copy it into `resources/`.
26
+
27
+ ## AI-layer index (`documentation/AI_LAYER_INDEX.md`)
28
+ A one-line-each inventory of the installed skills (`setup`, `ticket`, `spec-and-build`, `review`,
29
+ `ship`, `productize`, `refresh`), the `qc-reviewer` agent, the hooks, and the adapters in use — so
30
+ humans and agents can find what exists.
31
+
32
+ ## Ticket index
33
+ Seed an empty curated store — `tickets/index_data.json` with
34
+ `{"schema_version": 1, "tickets": []}` — then run
35
+ `python3 "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/build_ticket_index.py"` to write the
36
+ initial `tickets/INDEX.md`. From here it self-maintains (PostToolUse regen on folder changes,
37
+ SessionStart surfacing, curated summaries at ship time). An existing backlog gets bootstrapped with
38
+ `/refresh index --all`.
@@ -0,0 +1,33 @@
1
+ # `--teammate` mode — onboard a person to an already-configured repo
2
+
3
+ Reads `.claude/config/stack.yaml` and the adapters to produce a **personalized, tool-specific
4
+ checklist** and walk it with them. If `stack.yaml` is absent, stop — run plain `/setup` first.
5
+
6
+ ## 1 · Install prerequisites
7
+ Check what's present: `for c in <the CLIs named in stack.yaml seams> yq jq git; do command -v $c
8
+ >/dev/null && echo "✓ $c" || echo "✗ $c (install)"; done`. For each missing tool give the install
9
+ command (Homebrew / winget / apt as appropriate).
10
+
11
+ ## 2 · Authenticate each configured tool
12
+ For every seam, open its adapter's `auth:` notes and walk the person through signing in — tracker
13
+ CLI/MCP auth, warehouse connection (`config.toml`/ADC), chat MCP connect, docstore mount, vcs auth
14
+ login. Pure instructions — the person runs the auth themselves.
15
+
16
+ ## 3 · Verify connectivity
17
+ Run `bash "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/selftest.sh"` first (the kit itself),
18
+ then `bash "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/verify_stack.sh"`. Walk any ✗/⚠ with
19
+ the relevant adapter's auth notes until green (MCP-only seams: confirm the server is connected this
20
+ session). Mention the `db_write_guard` hook so they know destructive warehouse statements prompt
21
+ for confirmation **by design**.
22
+
23
+ ## 4 · Read the map
24
+ Point them at, in order: `AGENTS.md` (the rules — read end to end),
25
+ `documentation/AI_LAYER_INDEX.md` (what exists), and the `documentation/` knowledge pack (built by
26
+ `/refresh context`) for domain grounding. Summarize the lifecycle: **`/ticket` → `/spec-and-build`
27
+ → `/review` → `/ship`** — context loads automatically inside `/ticket`.
28
+
29
+ ## 5 · Guided first-ticket dry run
30
+ Pick a real, small ticket (or have them name one) and run `/ticket <id>` in **dry-run spirit** —
31
+ set up the workspace and prime context, but stop before any external action so they see the flow
32
+ end to end safely. Explain the hard-halt gates and the DB-write approval protocol as you go.
33
+ Finish with a checklist of done vs outstanding, and hand them their first real ticket.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: ship
3
+ description: Finalize and deliver a reviewed ticket — backup, tracker comment, chat draft, commit + PR — with a hard halt before any external post. Run after /review approves.
4
+ argument-hint: <ticket-id> [--go] (--go authorizes the external Phase B after review)
5
+ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep]
6
+ disable-model-invocation: true
7
+ ---
8
+
9
+ # /ship
10
+
11
+ Ships a ticket that has **passed `/review`**. Split into a safe Phase A (local, no approval) and a
12
+ gated Phase B (every external side effect), honoring `hard_halt_before_external_posts`. Reads
13
+ `.claude/config/stack.yaml`; routes through the docstore / tracker / chat / vcs adapters, so it
14
+ works regardless of the underlying tools.
15
+
16
+ ## Phase A — Finalize (no approval needed; internal to repo)
17
+ 1. Read `stack.yaml` + the ticket README + the `/review` verdict. If the verdict isn't APPROVE,
18
+ **stop** and send the user back to `/review`.
19
+ 2. Re-run the final deliverable queries once more; confirm **byte-identical** output to the
20
+ committed files (`deterministic_outputs` — explicit `ORDER BY`).
21
+ 3. Tidy: remove redundant/version-sprawl files (overwrite, don't duplicate); confirm filenames
22
+ carry record counts; confirm the README tells the full business + methodology + QC story. Then
23
+ **refresh this ticket's index entry** so its `tickets/INDEX.md` row gets a curated one-line
24
+ summary: `python3 "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/enrich_ticket.py" <id>` (or
25
+ `/refresh index <id>`). The PostToolUse hook already keeps the row present; this upgrades it
26
+ from auto-derived (`▱`) to curated.
27
+ 4. **Draft the comms artifacts** (don't post yet): render the tracker comment and the chat message
28
+ from the ticket facts. Tracker comment ≤ `word_limits.tracker_comment`; business-first;
29
+ segmented with counts/%/$. Chat ≤ `word_limits.chat`; includes `seams.chat.always_include`;
30
+ **hyperlink everything** (`hyperlink_everything`). If chat/docstore aren't configured, skip
31
+ those artifacts and note `/setup chat` / `/setup docstore` as the enabler — don't block.
32
+
33
+ ## Phase B — External delivery (HARD HALT → requires `--go` or explicit "go ahead")
34
+ Print a summary of exactly what will happen, then **stop and wait** for the user. Only on explicit
35
+ authorization, execute in order:
36
+ 5. **docstore.backup** the ticket folder (full-title dest name); then `docstore.link_for` each
37
+ delivered file to get shareable URLs.
38
+ 6. **tracker.comment** — post via the adapter's rich path (smart-link cards for the docstore
39
+ files). Never before this point (no tracker comments without human review).
40
+ 7. **chat.draft** to `seams.chat.default_channel` (policy `chat_default_draft` — the human clicks
41
+ send unless they said "send it", in which case `chat.send`). Smart links for ticket id(s),
42
+ files, PR.
43
+ 8. **vcs.commit** (stage this ticket's paths **plus `tickets/INDEX.md` + `tickets/OBJECTS.md` +
44
+ `tickets/index_data.json`** — all three, or `--check` flags drift in CI; semantic message +
45
+ Co-Authored-By) then **vcs.open_pr** (semantic title; body = Business Impact / Deliverables /
46
+ Technical Notes / QC).
47
+ 9. **transition** the ticket toward `project.terminal_status` if appropriate.
48
+
49
+ ## Phase C — System-evolution retro (always, even on success)
50
+ 10. Reflect briefly: did anything go wrong or get re-done this ticket? If so, **which layer was
51
+ insufficient** — a global rule, the context pack, a skill, or an adapter? Propose the concrete
52
+ fix to *that* artifact (policy `system_evolution`) and note it. A repeated manual step is a
53
+ signal to `/productize` it. Fixing the layer, not just the ticket, is what compounds.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: spec-and-build
3
+ description: Research-rich spec then execute it. `spec` mode writes a PRP-style blueprint (committed before building); `build` mode implements it in fresh context with independent validation. The IMPLEMENT phase.
4
+ argument-hint: spec <ticket-id> "<what to build>" | build <ticket-id> [spec-path]
5
+ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, Agent]
6
+ ---
7
+
8
+ # /spec-and-build
9
+
10
+ The **build** step of the lifecycle, split into two committed steps so planning and execution use
11
+ separate context (context-reset discipline). Generalizes the PRP (product-requirement-prompt) pattern
12
+ (`generate-data-object-prp` → `prp-data-object-execute`) to any warehouse via the adapter.
13
+
14
+ Reads `.claude/config/stack.yaml`. Front-loads decisions into a spec **before** any code — the
15
+ context-engineering core idea: AI fails from missing context, not weak models.
16
+
17
+ ---
18
+
19
+ ## Mode: `spec` — author the blueprint (this is still PLAN-adjacent; no production writes)
20
+
21
+ 1. **Preflight** the warehouse seam (verify; halt with auth notes if unreachable). If no warehouse
22
+ configured, the spec is code/analysis-only — proceed without warehouse steps.
23
+ 2. **Research in parallel, never implement.** Spawn read-only research (Agent/Explore, or re-run
24
+ the priming slices from `/ticket` — see `skills/ticket/priming.md`):
25
+ - explore the objects via `warehouse.describe` + samples; map dependencies + grain;
26
+ - read the 2–4 closest prior tickets (from `/ticket`'s reuse brief, or
27
+ `bin/recall.py --for <id>`) and reuse their SQL/QC where it fits;
28
+ - pull the business rules from the `documentation/` glossary (the domain slice).
29
+ Research agents return findings only; **they do not write code.**
30
+ 3. **Write the spec** from `templates/spec.md.tmpl` into the ticket's folder
31
+ (`specs/<id>-<slug>.md` or `final_deliverables/`): operation type (new/alter), data grain,
32
+ sources + join/cast rules, transformation logic, **validation gates** (the exact QC the build must
33
+ pass), downstream impact, dev-env target (`seams.warehouse.dev_db`), and a **confidence score
34
+ (1–10)**.
35
+ 4. **Reduce assumptions:** before finalizing, list open questions and **ask the user** (don't guess).
36
+ 5. **Commit the spec** via vcs `commit` (`docs: <id> spec for <thing>`) — policy
37
+ `commit_plan_before_implement` enables blame-free retry if the build later reveals a gap.
38
+
39
+ ## Mode: `build` — execute the committed spec (fresh context)
40
+
41
+ 6. **Load** the committed spec (path arg or newest in the ticket's `specs/`). Treat it as the source
42
+ of truth, but **validate each step independently** — don't blindly follow; the spec can be wrong.
43
+ 7. **Implement in small build-and-check sub-loops:** one object/step at a time. Develop against
44
+ `seams.warehouse.dev_db` first; parameterize values at the top; explicit `ORDER BY` on any export
45
+ (deterministic outputs).
46
+ 8. **Embed validation between steps** — after each, run the relevant gate from the spec; self-correct.
47
+ 9. **Any non-SELECT / DDL** ⇒ policy `db_write_requires_approval`: show the exact SQL, explain the
48
+ change, wait for explicit `yes`. Dev-env objects still get shown but are lower-risk.
49
+ 10. **Hand off to the check step:** when the build passes its own gates, stop and recommend
50
+ `/review <id>` for the independent pass. Do not ship from here.
51
+
52
+ ## Generalizes
53
+ `generate-data-object-prp` + `prp-data-object-execute` + `PRPs/templates/data-object-initial.md`,
54
+ warehouse-agnostic via `seams.warehouse`.
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: ticket
3
+ description: The front door — open or resume a ticket, auto-load its context and prior art, and route to the next step (spec, build, review, or ship). Start every ticket here.
4
+ argument-hint: <ticket-id> | --create "<summary>" [--type T] [--worktree] | --recall "<topic>" | --recall --object <NAME>
5
+ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, Agent]
6
+ ---
7
+
8
+ # /ticket
9
+
10
+ One command owns the ticket lifecycle: it opens (or creates) the ticket, sets up the workspace,
11
+ loads exactly the context this ticket needs, surfaces the closest prior work, and then tells you the
12
+ right next step — **plan → build → check → ship**. Reads `.claude/config/stack.yaml`; everything
13
+ tool-specific resolves through the adapters, so it works with any configured tracker/warehouse/vcs.
14
+
15
+ ## Mode: `--recall` (standalone prior-art lookup, no workspace setup)
16
+ `/ticket --recall "<topic>"` or `--recall --object <NAME>` — rank prior tickets and write a reuse
17
+ brief, nothing else. Follow [priming.md](priming.md) § Recall. Useful mid-session ("have we built
18
+ this before?", "which tickets touched VW_X?").
19
+
20
+ ## Phase 0 — Resolve & preflight (halt-on-fail)
21
+ 1. Read `.claude/config/stack.yaml`: `project.*`, `seams.tracker`, `seams.vcs`. If the file is
22
+ missing, say so and offer `/setup` — don't scaffold blind.
23
+ 2. **Verify** the tracker + vcs seams (run their `verify` commands). If one is unreachable, print
24
+ that adapter's `auth` notes and offer to continue **local-only** (workspace + context still work;
25
+ tracker fetch is skipped) — degrade, don't die.
26
+ 3. Determine the ticket id: `$ARGUMENTS` id, or (for `--create`) create it first via the tracker
27
+ adapter's `create_ticket` verb (`project.default_epic` as parent if set), then use the new id.
28
+
29
+ ## Phase 1 — Resume, don't restart
30
+ 4. Render `project.ticket_path` → the ticket dir. If it exists: read its `README.md`, list
31
+ `final_deliverables/`, check `git log --oneline -10` + `git status`, summarize what's done and
32
+ what remains, re-fetch the ticket for new comments, then **skip to Phase 3**.
33
+
34
+ ## Phase 2 — Workspace (new ticket)
35
+ 5. **Branch** via the vcs adapter, named `<id>`, off `seams.vcs.default_branch` — or a **worktree**
36
+ when `--worktree` is passed (isolates this ticket from other in-flight work; recommended when you
37
+ run several tickets in parallel).
38
+ 6. **Scaffold** `project.ticket_path` with `project.ticket_subdirs`; tracker adapter
39
+ `download_attachments` → `source_materials/` (silent if none); render
40
+ `templates/ticket-README.md.tmpl` → the ticket dir.
41
+
42
+ ## Phase 3 — Prime context automatically (the part you never have to ask for)
43
+ 7. Follow [priming.md](priming.md), in order:
44
+ - **Ticket slice** — the ticket body + folder + related prior tickets;
45
+ - **Recall** — rank prior art (`bin/recall.py`), read the top 2–4, note what to **reuse**;
46
+ - **Domain slice** — glossary/rules for the ticket's topic (from `documentation/`);
47
+ - **Warehouse slice** — schemas/samples/lineage for the specific objects in play (skip cleanly
48
+ if no warehouse is configured).
49
+ Keep the whole brief tight (≤ ~300 words) — slices, not the whole knowledge base.
50
+
51
+ ## Phase 4 — Route
52
+ 8. Report the context brief (including the reuse brief) and the recommended next step:
53
+ - non-trivial work → `/spec-and-build spec <id>` (blueprint first, build second);
54
+ - small change → build directly, then `/review <id>`;
55
+ - after review passes → `/ship <id>`.
56
+
57
+ ## Stops here
58
+ No SQL, no analysis, no external posts. If the request is ambiguous, state your interpretation and
59
+ ask before scaffolding heavy structure (`reduce_assumptions`).
@@ -0,0 +1,47 @@
1
+ # Context priming — the four slices `/ticket` loads
2
+
3
+ Small, scoped priming keeps the build phase focused and cheap. Load *slices*, never the whole
4
+ knowledge base. Each slice below was a separate command in v1 (`/prime-ticket`, `/recall`,
5
+ `/prime-domain`, `/prime-warehouse`); `/ticket` now runs them as one pass.
6
+
7
+ ## 1 · Ticket slice
8
+
9
+ - **Fetch the ticket** via the tracker adapter's `fetch_ticket` verb (title, description, type,
10
+ status, links). If the tracker seam is down, fall back to the local `README.md`.
11
+ - **Read the ticket folder** at the rendered `project.ticket_path` if it exists: `README.md` +
12
+ a listing of `final_deliverables/` — summarize prior progress (resume, don't restart).
13
+ - Note the ticket's key nouns (objects, stakeholders, report names) — they drive the other slices.
14
+
15
+ ## 2 · Recall (prior art — never rebuild what's built)
16
+
17
+ - **Rank candidates** (deterministic, instant — no vector store):
18
+ ```
19
+ python3 "${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/bin/recall.py" --for <id>
20
+ # or: --query "<topic>" | --tags a,b | --object <NAME> (add --json for structured)
21
+ ```
22
+ Scoring is transparent: object match ×4, tag ×3, cross-ref link +5, keyword overlap ×1; recency
23
+ is a tiebreak. The seed ticket is excluded.
24
+ - **Read the top 2–4** candidate READMEs (+ their `final_deliverables/` and `qc_queries/`
25
+ listings). Many candidates → spawn read-only Explore agents in parallel (findings only).
26
+ - **Write the reuse brief** (≤ ~200 words): the closest prior work, **what to copy** (which SQL/QC
27
+ artifact + path), known **gotchas** those tickets carried, and **what's different** this time.
28
+
29
+ ## 3 · Domain slice (business meaning)
30
+
31
+ - `grep -ril "<topic>" documentation/` and read only the matching sections — the definitions,
32
+ status taxonomies, calculation/eligibility rules, exclusions, and documented data-quality
33
+ gotchas for this topic.
34
+ - Scan `AGENTS.md` for any hard rule mentioning the topic (e.g. "as-of date is month-end").
35
+ - If `documentation/` is empty, note that `/refresh context` would build the knowledge pack —
36
+ don't block on it.
37
+
38
+ ## 4 · Warehouse slice (only the objects in play)
39
+
40
+ - Skip cleanly if `seams.warehouse` is absent/null ("no warehouse configured").
41
+ - **Preflight** the warehouse seam (`seams.warehouse.verify`); if it fails, halt this slice with
42
+ the adapter's auth notes — don't guess at schemas.
43
+ - **Resolve object names** (topic → real names via the local pack and the adapter's discovery
44
+ query), then per object: `describe` (columns/types/DDL), a 5-row sample via `query`, and
45
+ dependencies per the adapter's `dialect_notes` lineage approach.
46
+ - Brief per object: key columns, join keys (+ cast/filter rules from `dialect_notes`), grain, and
47
+ the safest source layer to read from.
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ # statusline.sh — compact Ticketwright status line for Claude Code.
3
+ # Shows: <key_prefix> · <git branch/ticket> · tracker→warehouse tools.
4
+ # Claude Code pipes session JSON on stdin; we only need cwd/branch + stack.yaml.
5
+ set -uo pipefail
6
+
7
+ # Read (and ignore) the stdin payload so the pipe doesn't block.
8
+ cat >/dev/null 2>&1 || true
9
+
10
+ root="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
11
+ stack="$root/.claude/config/stack.yaml"
12
+
13
+ prefix="?"; tracker="—"; warehouse="—"
14
+ if [[ -f "$stack" ]]; then
15
+ prefix=$(grep -m1 -E '^\s*key_prefix:' "$stack" | sed -E 's/.*key_prefix:[[:space:]]*//; s/[[:space:]#].*//')
16
+ tracker=$(awk '/^ tracker:/{f=1} f&&/tool:/{print $2; exit}' "$stack")
17
+ warehouse=$(awk '/^ warehouse:/{f=1} f&&/tool:/{print $2; exit}' "$stack")
18
+ fi
19
+
20
+ branch=$(git -C "$root" branch --show-current 2>/dev/null || echo "-")
21
+
22
+ printf "⛭ %s · ⎇ %s · %s→%s" "${prefix:-?}" "${branch:--}" "${tracker:-—}" "${warehouse:-—}"
@@ -0,0 +1,103 @@
1
+ # Adapters — the verb contract
2
+
3
+ Skills are written **once** against abstract *verbs*. An **adapter** is a small markdown playbook
4
+ that translates those verbs into one concrete tool's commands. To support a new tool (Asana, BigQuery,
5
+ Teams, …) you write **one adapter** — you never touch a skill.
6
+
7
+ ```
8
+ skill ──calls──▶ verb (e.g. tracker.fetch_ticket)
9
+ │
10
+ stack.yaml ──picks──▶ adapter (tracker/jira.md)
11
+ │
12
+ ▼
13
+ concrete command (acli jira workitem view DI-123)
14
+ ```
15
+
16
+ A skill resolves a verb like this:
17
+ 1. Read `stack.yaml` → `seams.<seam>.adapter`.
18
+ 2. Open that adapter, find the verb's section.
19
+ 3. Run the command shown there, substituting `{tokens}` from `stack.yaml` + skill args.
20
+ 4. If `seams.<seam>.verify` fails first (hybrid preflight), **halt** with the adapter's auth notes.
21
+
22
+ Every adapter file has the same shape: a **frontmatter** block (seam, tool, transport, required
23
+ config keys, auth/setup notes) followed by one `## verb: <name>` section per verb in that seam's
24
+ contract. A verb section gives the command(s), inputs, the expected output shape, and any gotchas.
25
+
26
+ ---
27
+
28
+ ## The contract (verbs by seam)
29
+
30
+ ### `tracker` — the ticket system
31
+ | Verb | Inputs | Returns |
32
+ |---|---|---|
33
+ | `fetch_ticket` | `id` | title, description, status, type, assignee, links, attachments list |
34
+ | `create_ticket` | type, summary, description, assignee, parent/epic | new `id` + URL |
35
+ | `transition` | `id`, `status` | ok/fail |
36
+ | `comment` | `id`, body, optional smart-link cards | ok/fail (rendered, not plain text) |
37
+ | `search` | query (JQL/equivalent), limit | list of `{id, summary, status}` |
38
+ | `download_attachments` | `id`, dest dir | files written (silent if none) |
39
+
40
+ ### `warehouse` — the data/work backend
41
+ | Verb | Inputs | Returns |
42
+ |---|---|---|
43
+ | `query` | SQL, optional `--format csv` | rows / CSV (header row 1, no preamble) |
44
+ | `describe` | object name | columns + types (and DDL when supported) |
45
+ | `dialect_notes` | — | *static section*: function names, sizing model, dedup idiom, type-cast rules, the warehouse-specific anti-patterns the `review` skill checks |
46
+
47
+ ### `chat` — team messaging
48
+ | Verb | Inputs | Returns |
49
+ |---|---|---|
50
+ | `draft` | channel, body, mentions | a saved draft (human clicks send) |
51
+ | `send` | channel, body, mentions | posted message (only on explicit "send it") |
52
+ | `lookup_user` | name/email | user ID for mentions |
53
+ | `lookup_channel` | name | channel ID |
54
+
55
+ ### `docstore` — durable backup + shareable links
56
+ | Verb | Inputs | Returns |
57
+ |---|---|---|
58
+ | `backup` | local ticket dir, dest name | files copied to the store |
59
+ | `link_for` | a backed-up file | a shareable URL (for tracker/chat smart links) |
60
+
61
+ ### `vcs` — version control + PRs
62
+ | Verb | Inputs | Returns |
63
+ |---|---|---|
64
+ | `branch` | name (`{key_prefix}-NNNN`) | branch created/checked out |
65
+ | `worktree` | branch | isolated worktree path (the Plan→Implement context reset) |
66
+ | `commit` | paths, message (semantic) | commit sha |
67
+ | `open_pr` | title (semantic), body | PR URL |
68
+
69
+ ---
70
+
71
+ ## Adapters shipped
72
+
73
+ Pick the one matching your stack (or copy the closest as a starting point). All implement the full
74
+ verb contract for their seam:
75
+
76
+ - **tracker:** `jira`, `azure-devops` (Azure Boards), `linear`, `asana`, `monday`, `github-issues`
77
+ - **warehouse:** `snowflake`, `bigquery`, `databricks`, `postgres`, `redshift`, `synapse` (also Azure SQL / SQL Server / Fabric)
78
+ - **chat:** `slack`, `teams`
79
+ - **docstore:** `gdrive`, `sharepoint`
80
+ - **vcs:** `github`, `gitlab`, `azure-repos`
81
+
82
+ Don't see your tool? Adding one is a single file — see "Writing a new adapter" below. Three worked
83
+ `stack.yaml` configs ship (Jira/Snowflake/Slack/Drive/GitHub, Asana/BigQuery/Teams/SharePoint/GitLab,
84
+ and Azure DevOps/Synapse/Teams/SharePoint/Azure Repos) — the same skills run against all three.
85
+
86
+ > **MCP-transport adapters** (Asana, Linear, Monday, Teams, Slack) reference each operation with a
87
+ > server-namespaced placeholder like `mcp__<server>__<op>`. The exact tool name + parameters depend on
88
+ > your connected MCP server — confirm them once and adjust the adapter (never the skills).
89
+
90
+ ## Writing a new adapter
91
+
92
+ 1. Copy the closest reference adapter in the same seam.
93
+ 2. Keep the frontmatter keys (`seam`, `tool`, `transport`, `requires`, `auth`).
94
+ 3. Implement **every** verb section for that seam — if the tool can't do one, say so and give the
95
+ manual fallback (skills will surface it rather than silently skipping).
96
+ 4. Add a `verify` command to your `stack.yaml` seam entry (read-only, exits non-zero when unreachable).
97
+ 5. Run `bash bin/verify_stack.sh` — it confirms each seam's adapter file exists and runs the seam's
98
+ read-only `verify` to check reachability. (`bash bin/selftest.sh` checks verb coverage vs. this contract.)
99
+
100
+ **Rule:** adapters may name concrete tools/CLIs/IDs freely. **Skills may not.** `bin/selftest.sh`
101
+ (section 3) enforces this: it greps `.claude/skills/**` + `.claude/commands/**` for tool names, with
102
+ two sanctioned exceptions (the CLI-detection probe in `setup` and the self-lint line in
103
+ `productize`).
@@ -0,0 +1,46 @@
1
+ ---
2
+ seam: chat
3
+ tool: slack
4
+ transport: mcp # mcp__slack__* tools only
5
+ requires: [mcp] # stack.yaml seams.chat.{mcp, default_channel, default_mode, always_include}
6
+ auth: |
7
+ The `slack` MCP server must be connected. Verify with a read-only search.
8
+ Verify: a `mcp__slack__slack_search_channels` call returns without error.
9
+ note: |
10
+ MCP cannot create a brand-new multi-person DM — create it once in the Slack UI, then reuse it.
11
+ ---
12
+
13
+ # Slack adapter
14
+
15
+ Maps the `chat` verb contract to Slack via the `mcp__slack__*` tools. **Two hard rules from saved
16
+ memory:** (1) default to *draft*, not send — the human clicks send unless they say "send it";
17
+ (2) never solo-DM a stakeholder — every message includes `{always_include}` (e.g. Alice).
18
+
19
+ ## verb: draft (the default — policy chat_default_draft)
20
+ ```
21
+ mcp__slack__slack_send_message_draft(channel_id=<id or {default_channel}>, message=<body>, thread_ts=<optional>)
22
+ ```
23
+ Body rules: standard Markdown (the MCP tools accept markdown); **hyperlink everything** with
24
+ `[text](URL)` — ticket IDs (`[ENG-123](https://<site>/browse/ENG-123)`), doc files, PRs. Honor `word_limits.chat` (<100).
25
+ Include `{always_include}` mentions. Resolve mentions/channels via the lookups below.
26
+
27
+ ## verb: send (ONLY on explicit "send it"/"post it")
28
+ ```
29
+ mcp__slack__slack_send_message(channel_id=<id>, message=<body>)
30
+ ```
31
+
32
+ ## verb: lookup_user
33
+ ```
34
+ mcp__slack__slack_search_users(query=<name or email>) # → user ID for <@ID> mentions
35
+ ```
36
+
37
+ ## verb: lookup_channel
38
+ ```
39
+ mcp__slack__slack_search_channels(query=<name>) # → channel ID
40
+ ```
41
+ Existing group DMs can be reused by searching; new multi-person DMs must be created in the UI first.
42
+
43
+ ## gotchas
44
+ - The `mcp__slack__*` tools take **standard Markdown** — use `[text](URL)` links, not Slack `<URL|text>` mrkdwn.
45
+ - Exact parameter names vary by Slack MCP server; this adapter targets one exposing `channel_id` + `message`. If yours differs, adjust here (not in the skills).
46
+ - Tag the stakeholders the channel context calls for, but `{always_include}` is non-negotiable.
@@ -0,0 +1,38 @@
1
+ ---
2
+ seam: chat
3
+ tool: teams
4
+ transport: mcp # a Microsoft Teams / Graph MCP, or incoming-webhook fallback
5
+ requires: [channel, default_mode, always_include]
6
+ auth: |
7
+ A Teams MCP server (Graph) connected, OR an incoming-webhook URL per channel.
8
+ Verify: a read-only "list channels"/"list teams" MCP call returns without error.
9
+ ---
10
+
11
+ # Microsoft Teams adapter (reference for the abstraction proof)
12
+
13
+ Maps the `chat` verb contract to Teams. Same two rules as Slack: default to **draft**, and always
14
+ include `{always_include}`. Teams uses Adaptive Cards / HTML rather than Slack mrkdwn.
15
+
16
+ ## verb: draft
17
+ Compose the message and **hold it for the human** (Teams has no native "draft to a channel" — stage
18
+ the Adaptive Card JSON / message text in the ticket folder as `chat_draft.json` for the human to send).
19
+
20
+ ## verb: send (ONLY on explicit "send it")
21
+ ```
22
+ <teams mcp> post-message(channel={channel}, body=<HTML/Adaptive Card>) # or POST to webhook URL
23
+ ```
24
+ Hyperlink everything: `<a href="URL">text</a>` (Teams renders HTML), ticket IDs, files, PRs.
25
+ Honor `word_limits.chat`.
26
+
27
+ ## verb: lookup_user
28
+ ```
29
+ <teams mcp> search-users(query=<name/email>) # → user id for the mention
30
+ ```
31
+
32
+ ## verb: lookup_channel
33
+ ```
34
+ <teams mcp> list-channels(team=<team>) # → channel id
35
+ ```
36
+
37
+ ## gotchas
38
+ - Incoming-webhook transport can post but can't @mention reliably — prefer the Graph MCP when mentions matter.
@@ -0,0 +1,39 @@
1
+ ---
2
+ seam: docstore
3
+ tool: gdrive
4
+ transport: cli # filesystem copy into the mounted Google Drive (CloudStorage)
5
+ requires: [base_path] # stack.yaml seams.docstore.base_path
6
+ auth: |
7
+ Google Drive for Desktop must be mounted at the CloudStorage path.
8
+ Verify: `test -d "{base_path}"`.
9
+ ---
10
+
11
+ # Google Drive adapter
12
+
13
+ Maps the `docstore` verb contract to a mounted Google Drive shared drive. Backups are plain
14
+ filesystem copies; shareable links come from the file's macOS extended attribute.
15
+
16
+ ## verb: backup
17
+ **In:** local ticket dir, dest name (**always full title, not just the ID** — saved memory).
18
+ ```bash
19
+ dest="{base_path}/<TICKET-ID> <Full Ticket Title>"
20
+ rm -rf "$dest" # remove ONLY this exact destination (never a wildcard like <ID>*)
21
+ cp -r "<local ticket dir>" "$dest"
22
+ ls -la "$dest" # verify
23
+ ```
24
+ Requires explicit approval (external side effect) — policy `hard_halt_before_external_posts`.
25
+ **Never** `rm -rf "<ID>"*` — a prefix glob also matches `<ID>0`, `<ID>1234`, etc. If a prior backup
26
+ used a different title, `ls "{base_path}"` and remove that one exact path by name.
27
+ Note: clean `rm`+`cp` mints **new** Drive item-ids, so any previously shared links go stale — repost.
28
+
29
+ ## verb: link_for
30
+ **In:** a backed-up file path. **Out:** a shareable Drive URL (for tracker/chat smart links).
31
+ ```bash
32
+ xattr -l "<gdrive file path>" | grep item-id # NOT xattr -p (zsh eats the #S suffix)
33
+ # → build: https://drive.google.com/file/d/<ITEM_ID>
34
+ ```
35
+ Item-id is blank for a few minutes after an in-place copy — wait, or use the clean rm+cp path.
36
+
37
+ ## gotchas
38
+ - Stakeholder CSV *inputs/provenance* are committed to git; large *exports* go here, linked from Drive — never committed.
39
+ - Jira/Slack must link the **specific Drive file**, never a PR or folder link (saved memory).