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.
- ticketwright/__init__.py +9 -0
- ticketwright/_kit/.claude/agents/qc-reviewer.md +50 -0
- ticketwright/_kit/.claude/commands/build-context-pack.md +8 -0
- ticketwright/_kit/.claude/commands/build-ticket-index.md +8 -0
- ticketwright/_kit/.claude/commands/configure-workspace.md +8 -0
- ticketwright/_kit/.claude/commands/deliver-ticket.md +8 -0
- ticketwright/_kit/.claude/commands/onboard-teammate.md +8 -0
- ticketwright/_kit/.claude/commands/prime-domain.md +8 -0
- ticketwright/_kit/.claude/commands/prime-ticket.md +8 -0
- ticketwright/_kit/.claude/commands/prime-warehouse.md +8 -0
- ticketwright/_kit/.claude/commands/productize-workflow.md +8 -0
- ticketwright/_kit/.claude/commands/qc-review.md +8 -0
- ticketwright/_kit/.claude/commands/recall.md +8 -0
- ticketwright/_kit/.claude/commands/start-ticket.md +8 -0
- ticketwright/_kit/.claude/config/stack.example.asana-bq.yaml +67 -0
- ticketwright/_kit/.claude/config/stack.example.azure.yaml +73 -0
- ticketwright/_kit/.claude/config/stack.schema.md +76 -0
- ticketwright/_kit/.claude/config/stack.yaml +76 -0
- ticketwright/_kit/.claude/hooks/db_write_guard.py +145 -0
- ticketwright/_kit/.claude/hooks/regenerate_ticket_index.py +74 -0
- ticketwright/_kit/.claude/hooks/session_context.py +78 -0
- ticketwright/_kit/.claude/hooks/ticket_index_context.py +99 -0
- ticketwright/_kit/.claude/settings.json.tmpl +59 -0
- ticketwright/_kit/.claude/skills/productize/SKILL.md +58 -0
- ticketwright/_kit/.claude/skills/productize/authoring.md +36 -0
- ticketwright/_kit/.claude/skills/refresh/SKILL.md +40 -0
- ticketwright/_kit/.claude/skills/refresh/context-pack.md +34 -0
- ticketwright/_kit/.claude/skills/refresh/index.md +45 -0
- ticketwright/_kit/.claude/skills/review/SKILL.md +76 -0
- ticketwright/_kit/.claude/skills/setup/SKILL.md +59 -0
- ticketwright/_kit/.claude/skills/setup/adopt.md +43 -0
- ticketwright/_kit/.claude/skills/setup/scaffold.md +38 -0
- ticketwright/_kit/.claude/skills/setup/teammate.md +33 -0
- ticketwright/_kit/.claude/skills/ship/SKILL.md +53 -0
- ticketwright/_kit/.claude/skills/spec-and-build/SKILL.md +54 -0
- ticketwright/_kit/.claude/skills/ticket/SKILL.md +59 -0
- ticketwright/_kit/.claude/skills/ticket/priming.md +47 -0
- ticketwright/_kit/.claude/statusline.sh +22 -0
- ticketwright/_kit/adapters/README.md +103 -0
- ticketwright/_kit/adapters/chat/slack.md +46 -0
- ticketwright/_kit/adapters/chat/teams.md +38 -0
- ticketwright/_kit/adapters/docstore/gdrive.md +39 -0
- ticketwright/_kit/adapters/docstore/sharepoint.md +41 -0
- ticketwright/_kit/adapters/tracker/asana.md +55 -0
- ticketwright/_kit/adapters/tracker/azure-devops.md +68 -0
- ticketwright/_kit/adapters/tracker/github-issues.md +59 -0
- ticketwright/_kit/adapters/tracker/jira.md +71 -0
- ticketwright/_kit/adapters/tracker/linear.md +56 -0
- ticketwright/_kit/adapters/tracker/monday.md +62 -0
- ticketwright/_kit/adapters/vcs/azure-repos.md +58 -0
- ticketwright/_kit/adapters/vcs/github.md +55 -0
- ticketwright/_kit/adapters/vcs/gitlab.md +52 -0
- ticketwright/_kit/adapters/warehouse/bigquery.md +44 -0
- ticketwright/_kit/adapters/warehouse/databricks.md +58 -0
- ticketwright/_kit/adapters/warehouse/postgres.md +44 -0
- ticketwright/_kit/adapters/warehouse/redshift.md +49 -0
- ticketwright/_kit/adapters/warehouse/snowflake.md +54 -0
- ticketwright/_kit/adapters/warehouse/synapse.md +52 -0
- ticketwright/_kit/bin/build_ticket_index.py +498 -0
- ticketwright/_kit/bin/enrich_ticket.py +138 -0
- ticketwright/_kit/bin/ingest_index_records.py +149 -0
- ticketwright/_kit/bin/recall.py +268 -0
- ticketwright/_kit/bin/render.sh +54 -0
- ticketwright/_kit/bin/render_and_validate.sh +139 -0
- ticketwright/_kit/bin/selftest.sh +408 -0
- ticketwright/_kit/bin/split_and_export.sh +138 -0
- ticketwright/_kit/bin/verify_stack.sh +74 -0
- ticketwright/_kit/templates/AGENTS.md.tmpl +74 -0
- ticketwright/_kit/templates/gitignore.tmpl +35 -0
- ticketwright/_kit/templates/plan.md.tmpl +22 -0
- ticketwright/_kit/templates/productized-skill/SKILL.md.tmpl +67 -0
- ticketwright/_kit/templates/productized-skill/bin/drift_check.sh +30 -0
- ticketwright/_kit/templates/productized-skill/golden/example.json +13 -0
- ticketwright/_kit/templates/productized-skill/sql/qc.sql.tmpl +21 -0
- ticketwright/_kit/templates/productized-skill/sql/step.sql.tmpl +20 -0
- ticketwright/_kit/templates/productized-skill/templates/README.md.tmpl +20 -0
- ticketwright/_kit/templates/productized-skill/templates/tracker_comment.txt.tmpl +14 -0
- ticketwright/_kit/templates/roles/analyst.md +6 -0
- ticketwright/_kit/templates/roles/engineer.md +6 -0
- ticketwright/_kit/templates/roles/generalist.md +3 -0
- ticketwright/_kit/templates/roles/scientist.md +5 -0
- ticketwright/_kit/templates/spec.md.tmpl +34 -0
- ticketwright/_kit/templates/ticket-README.md.tmpl +29 -0
- ticketwright/cli.py +115 -0
- ticketwright-2.0.0.dist-info/METADATA +139 -0
- ticketwright-2.0.0.dist-info/RECORD +89 -0
- ticketwright-2.0.0.dist-info/WHEEL +4 -0
- ticketwright-2.0.0.dist-info/entry_points.txt +2 -0
- 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).
|