@cyanheads/mcp-ts-core 0.13.3 → 0.13.4
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.
- package/AGENTS.md +6 -4
- package/CLAUDE.md +6 -4
- package/README.md +1 -1
- package/changelog/0.13.x/0.13.4.md +65 -0
- package/changelog/template.md +7 -7
- package/dist/config/appRoot.d.ts.map +1 -1
- package/dist/config/appRoot.js +48 -16
- package/dist/config/appRoot.js.map +1 -1
- package/dist/core/app.d.ts +20 -0
- package/dist/core/app.d.ts.map +1 -1
- package/dist/core/app.js +1 -0
- package/dist/core/app.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/linter/rules/schema-rules.d.ts +19 -0
- package/dist/linter/rules/schema-rules.d.ts.map +1 -1
- package/dist/linter/rules/schema-rules.js +36 -0
- package/dist/linter/rules/schema-rules.js.map +1 -1
- package/dist/linter/rules/tool-rules.d.ts +17 -0
- package/dist/linter/rules/tool-rules.d.ts.map +1 -1
- package/dist/linter/rules/tool-rules.js +97 -1
- package/dist/linter/rules/tool-rules.js.map +1 -1
- package/dist/mcp-server/handlerContext.d.ts +6 -0
- package/dist/mcp-server/handlerContext.d.ts.map +1 -1
- package/dist/mcp-server/handlerContext.js.map +1 -1
- package/dist/mcp-server/tools/utils/inputPrevalidation.d.ts +114 -0
- package/dist/mcp-server/tools/utils/inputPrevalidation.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/inputPrevalidation.js +428 -0
- package/dist/mcp-server/tools/utils/inputPrevalidation.js.map +1 -0
- package/dist/mcp-server/tools/utils/strictenRecord.d.ts +42 -0
- package/dist/mcp-server/tools/utils/strictenRecord.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/strictenRecord.js +48 -0
- package/dist/mcp-server/tools/utils/strictenRecord.js.map +1 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts +27 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils/toolDefinition.js +35 -6
- package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +19 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js +53 -11
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
- package/dist/services/canvas/core/sqlGate.d.ts +14 -1
- package/dist/services/canvas/core/sqlGate.d.ts.map +1 -1
- package/dist/services/canvas/core/sqlGate.js +69 -7
- package/dist/services/canvas/core/sqlGate.js.map +1 -1
- package/dist/services/canvas/index.d.ts +1 -1
- package/dist/services/canvas/index.d.ts.map +1 -1
- package/dist/services/canvas/index.js +1 -1
- package/dist/services/canvas/index.js.map +1 -1
- package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts +20 -0
- package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts.map +1 -1
- package/dist/services/canvas/providers/duckdb/DuckdbProvider.js +75 -25
- package/dist/services/canvas/providers/duckdb/DuckdbProvider.js.map +1 -1
- package/dist/services/canvas/types.d.ts +6 -1
- package/dist/services/canvas/types.d.ts.map +1 -1
- package/dist/types-global/errors.d.ts.map +1 -1
- package/dist/types-global/errors.js +4 -3
- package/dist/types-global/errors.js.map +1 -1
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/network/httpError.d.ts +13 -2
- package/dist/utils/network/httpError.d.ts.map +1 -1
- package/dist/utils/network/httpError.js +4 -2
- package/dist/utils/network/httpError.js.map +1 -1
- package/dist/utils/network/pacer.d.ts +117 -0
- package/dist/utils/network/pacer.d.ts.map +1 -0
- package/dist/utils/network/pacer.js +304 -0
- package/dist/utils/network/pacer.js.map +1 -0
- package/dist/utils/network/retry.d.ts +119 -3
- package/dist/utils/network/retry.d.ts.map +1 -1
- package/dist/utils/network/retry.js +176 -35
- package/dist/utils/network/retry.js.map +1 -1
- package/dist/utils/security/rateLimiter.d.ts +19 -1
- package/dist/utils/security/rateLimiter.d.ts.map +1 -1
- package/dist/utils/security/rateLimiter.js +49 -1
- package/dist/utils/security/rateLimiter.js.map +1 -1
- package/dist/utils/telemetry/attributes.d.ts +19 -0
- package/dist/utils/telemetry/attributes.d.ts.map +1 -1
- package/dist/utils/telemetry/attributes.js +30 -0
- package/dist/utils/telemetry/attributes.js.map +1 -1
- package/framework-skills/add-tool/SKILL.md +43 -2
- package/framework-skills/api-canvas/SKILL.md +8 -4
- package/framework-skills/api-config/SKILL.md +4 -4
- package/framework-skills/api-errors/SKILL.md +6 -2
- package/framework-skills/api-linter/SKILL.md +48 -3
- package/framework-skills/api-telemetry/SKILL.md +26 -2
- package/framework-skills/api-utils/SKILL.md +7 -3
- package/framework-skills/api-utils/references/security.md +2 -2
- package/framework-skills/design-mcp-server/SKILL.md +17 -2
- package/framework-skills/field-test/SKILL.md +3 -1
- package/framework-skills/git-wrapup/SKILL.md +87 -69
- package/framework-skills/release-and-publish/SKILL.md +5 -5
- package/framework-skills/release-pr-review/SKILL.md +5 -5
- package/framework-skills/report-issue-framework/SKILL.md +6 -35
- package/framework-skills/report-issue-local/SKILL.md +6 -36
- package/package.json +2 -2
- package/templates/.github/ISSUE_TEMPLATE/bug_report.yml +2 -2
- package/templates/.github/ISSUE_TEMPLATE/feature_request.yml +2 -2
- package/templates/changelog/template.md +7 -7
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: git-wrapup
|
|
3
3
|
description: >
|
|
4
|
-
Land working-tree changes as logical commits — the work grouped by concern, topped by a release commit (version bump, changelog, regenerated artifacts).
|
|
4
|
+
Land working-tree changes as logical commits — the work grouped by concern, topped by a release commit (version bump, changelog, regenerated artifacts). The work commits land first, then the version bump, verification, and the release commit on top. Stops at "committed locally on main" — or, when the project releases through a release PR, at "release branch pushed, PR open". No tag, no push to main, no publish: the release-and-publish skill merges, tags, and ships from here. Distilled from the git_wrapup_instructions protocol.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.19"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -28,7 +28,7 @@ A project can route every release through a pull request — one PR per version,
|
|
|
28
28
|
| **gated** | commit stack on `release/<version>`, branch pushed, PR open | a review pass on the PR (`release-pr-review` skill), then a separate `release-and-publish` run fast-forwards `main`, tags, and ships |
|
|
29
29
|
| **straight-through** | same as gated | the same agent continues straight into `release-and-publish` |
|
|
30
30
|
|
|
31
|
-
The branch is created at wrapup time, never before: work happens on `main` until the version is known, then the uncommitted tree moves to `release/<version>` in one step (step
|
|
31
|
+
The branch is created at wrapup time, never before: work happens on `main` until the version is known, then the uncommitted tree moves to `release/<version>` in one step (step 3), ahead of the first commit. The commit stack, the release commit, and the tag format are identical in every mode — the PR adds an artifact around them, it does not change them.
|
|
32
32
|
|
|
33
33
|
## Pre-wrapup gate checklist
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@ Every item must be true before starting wrapup. Committing means releasing — a
|
|
|
45
45
|
- [ ] **GH issues updated** — issues addressed by this work commented with what landed and any follow-ups needed. Concise. Backlinked as needed.
|
|
46
46
|
- [ ] **Docs updated** — surgical updates to existing docs as needed. New docs for new features. No large rewrites for documentation that's still accurate.
|
|
47
47
|
|
|
48
|
-
If any gate is red, fix it before proceeding. This skill re-verifies build + tests in step
|
|
48
|
+
If any gate is red, fix it before proceeding. This skill re-verifies build + tests in step 7, but the work is committed by then — starting wrapup on a broken tree wastes the version number and turns the fix into an extra commit on a stack that should have been green.
|
|
49
49
|
|
|
50
50
|
## Steps
|
|
51
51
|
|
|
@@ -60,7 +60,7 @@ git diff HEAD --stat # every uncommitted change, staged or
|
|
|
60
60
|
git diff HEAD # review the actual content
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Diff against `HEAD`, not the index: plain `git diff` omits staged changes entirely, so a group already staged before wrap-up began — a `git mv` from a migration step, a hook's output — shows up in `git status` as a line to scroll past and nowhere in the diff review. Whatever is staged is part of what ships and gets grouped in step
|
|
63
|
+
Diff against `HEAD`, not the index: plain `git diff` omits staged changes entirely, so a group already staged before wrap-up began — a `git mv` from a migration step, a hook's output — shows up in `git status` as a line to scroll past and nowhere in the diff review. Whatever is staged is part of what ships and gets grouped in step 3 like everything else.
|
|
64
64
|
|
|
65
65
|
If the working tree is clean AND there are no commits since the last tag, halt — nothing to wrap up.
|
|
66
66
|
|
|
@@ -76,7 +76,64 @@ Read the current version from `package.json`. Apply the intended bump:
|
|
|
76
76
|
|
|
77
77
|
Default to **patch** unless the diff clearly warrants minor or major.
|
|
78
78
|
|
|
79
|
-
### 3.
|
|
79
|
+
### 3. Commit the work — one commit per concern
|
|
80
|
+
|
|
81
|
+
**Release PR mode only — move to the release branch first, before the first commit:**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git branch --show-current # must be main
|
|
85
|
+
git switch -c release/<version> # uncommitted work rides along
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Commits never land on `main` in this mode. If a `release/*` branch already exists locally, a prior release PR was never merged — halt and report it rather than stacking a second release on top.
|
|
89
|
+
|
|
90
|
+
**The work is committed before the version is bumped.** Work concerns routinely share a file with the version — a dependency refresh edits `package.json`, a doc edit lands in a `CLAUDE.md`/`AGENTS.md` that pins a version string — and the file is the atomic boundary, so whichever commit comes first takes the file whole. Committing the work first leaves the version hunk (step 4) as the only thing those files carry into the release commit.
|
|
91
|
+
|
|
92
|
+
Do NOT `git add -A` into one commit. Group the working tree into a handful of logical commits — never one blob. A feature spanning multiple layers splits by layer: runtime/logic, linter/tooling, docs/skills. Unrelated changes (two separate fixes, an incidental doc tweak) are their own commits. A dependency refresh is its own commit — `chore(deps): …` carrying `package.json`, the lockfile, and any pins it moved elsewhere. Work commits do not carry the version.
|
|
93
|
+
|
|
94
|
+
Stage each group explicitly, commit it by pathspec, then move to the next:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
git add <paths-for-this-concern>
|
|
98
|
+
git commit --only <paths-for-this-concern> -m "<subject>" -m "<body>"
|
|
99
|
+
# repeat per concern
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Commit by pathspec, never the bare index.** A bare `git commit` commits everything staged, not the paths just added, so anything staged before wrap-up began — a `git mv` left by a migration step, a concurrent stage from a second session or a hook — rides into the first concern's commit. `--only` takes the named paths' working-tree content and disregards the rest of the index, so a pre-staged group never rides along; it stays staged, to be committed as its own concern (`chore(skills): move the skill tree to framework-skills/`) or reported. Anything still staged when the release commit lands then fails step 10's clean-tree check instead of shipping silently.
|
|
103
|
+
|
|
104
|
+
**The file is the atomic boundary:** NEVER split a single file's working-tree changes across commits, regardless of mechanism — not `git add -p`, not an index-only patch (`git apply --cached`), not editing the file between commits to remove-then-re-add a hunk. When one file serves two concerns, it ships whole in the commit of its dominant concern; a later commit may touch the file again only for changes made AFTER the first commit (the version bump applied in step 4).
|
|
105
|
+
|
|
106
|
+
**Subject format:** Conventional Commits, no version in the subject — `feat: hosted server endpoint`, `fix: handle empty SPARQL result sets`, `feat(linter): enrichment contract rules`, `docs: document the enrichment block`, `chore(deps): refresh dev dependencies`.
|
|
107
|
+
|
|
108
|
+
**Body: every commit has one, and it is one or two lines.** Uniform across the stack — no commit ships subject-only, none ships a paragraph. One sentence stating the *why* or the load-bearing constraint, a second only if the first genuinely cannot carry it. Two lines is the hard ceiling.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
fix: handle empty SPARQL result sets
|
|
112
|
+
|
|
113
|
+
Upstream returns 200 with an empty bindings array rather than 404.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Never put a closing keyword in a commit body.** `Fixes #N`, `Closes #N`, `Resolves #N` and friends close the issue the moment the commit is pushed — before the close-out comment recording what shipped, so the issue closes with no account of the fix. Reference issues as bare `(#N)` backlinks in the subject or body; closing is a deliberate later step.
|
|
117
|
+
|
|
118
|
+
A body is too long the moment it:
|
|
119
|
+
- enumerates the files, subsystems, or symbols touched — that is `git show --stat`
|
|
120
|
+
- walks through how the implementation works — that is the code
|
|
121
|
+
- narrates a fix's mechanism across multiple sentences — that is the changelog entry
|
|
122
|
+
- runs to a second paragraph, ever
|
|
123
|
+
|
|
124
|
+
The changelog carries the depth, the tag carries the headline, the commit carries one line of why. When the body wants to grow, that pressure is telling you the content belongs in the changelog entry.
|
|
125
|
+
|
|
126
|
+
**Rules:**
|
|
127
|
+
- Plain `-m` flag only — no heredoc, no command substitution
|
|
128
|
+
- No `Co-authored-by` or `Generated with` trailers
|
|
129
|
+
- No marketing adjectives ("comprehensive", "robust", "enhanced", "seamless", "improved")
|
|
130
|
+
- Each commit message stands alone for someone reading `git log` — no chat context, option numbers, or "as discussed"
|
|
131
|
+
|
|
132
|
+
**Right-size it.** "Group by concern" is not "always split." A genuinely single-concern change — one fix, a dependency bump, a small doc edit — is one work commit, with step 8's release commit on top of it. Only when the version bump *is* the whole change — a republish, a metadata-only patch with nothing else in the tree — is there no work commit to make, and step 8's release commit becomes the entire stack. The failure mode to prevent is the inverse: a large, multi-layer feature crammed into one commit alongside the release artifacts.
|
|
133
|
+
|
|
134
|
+
When every concern is committed, `git status` is clean. That clean tree is what makes everything steps 4–6 touch a release artifact and nothing else — confirm it before moving on.
|
|
135
|
+
|
|
136
|
+
### 4. Bump version everywhere
|
|
80
137
|
|
|
81
138
|
Every file that declares a version must be updated. Skip any file that doesn't exist in the project. For `@cyanheads/mcp-ts-core` projects:
|
|
82
139
|
|
|
@@ -96,7 +153,7 @@ grep -rn "0.9.7" . --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=c
|
|
|
96
153
|
|
|
97
154
|
Resolve hits case by case — historical changelog entries are correct as-is; everything else should match the new version.
|
|
98
155
|
|
|
99
|
-
###
|
|
156
|
+
### 5. Author the changelog
|
|
100
157
|
|
|
101
158
|
Create `changelog/<major.minor>.x/<version>.md`. Use `changelog/template.md` as the format reference — never edit, rename, or move that file.
|
|
102
159
|
|
|
@@ -110,7 +167,7 @@ security: false # true ONLY for a security fix in this server's own source
|
|
|
110
167
|
---
|
|
111
168
|
```
|
|
112
169
|
|
|
113
|
-
**Write `summary:` LAST, derived from the body you just wrote — never independently.** It is the line most readers see
|
|
170
|
+
**Write `summary:` LAST, derived from the body you just wrote — never independently.** It is the line most readers see: `changelog:build` copies it verbatim into the `CHANGELOG.md` rollup, which ships inside the npm tarball, and in release PR mode it opens the PR body. Written from recollection rather than from the body, it reliably names a mechanism that was never built or a target that was never fixed, while the body beside it stays correct. After writing it, re-read the body and confirm every claim in the summary appears there. Derived-from-the-body means the facts come from the body — not that every body item appears: it is one headline, and comma-stitching every change into an inventory near the 350-char cap is the failure mode.
|
|
114
171
|
|
|
115
172
|
**`security:` is a source-code signal — not a dependency-CVE signal.** Set `security: true` only when this release fixes a vulnerability or adds hardening in code *this server ships*. A dependency or transitive CVE bump — even one that clears an advisory (`bun audit` going 1 → 0) — is routine maintenance: record it under `## Dependencies` with the advisory ID and leave the flag `false`. The `🛡️ Security` badge answers "does the server itself have a vuln"; a dep bump must not trip it.
|
|
116
173
|
|
|
@@ -120,7 +177,7 @@ security: false # true ONLY for a security fix in this server's own source
|
|
|
120
177
|
|
|
121
178
|
**Re-read the entry file after writing it, then sweep for harness markup:** `grep -rlF -e '</invoke>' -e '</content>' changelog/` must print nothing. A stray closing tag at EOF is the authoring tool's own syntax bleeding into the file; `changelog/` is in `package.json` `files`, so it ships inside the npm tarball, and `changelog:check` cannot catch it — the rollup drops the trailing line, so a clean `CHANGELOG.md` proves nothing about the entry.
|
|
122
179
|
|
|
123
|
-
###
|
|
180
|
+
### 6. Regenerate derived artifacts
|
|
124
181
|
|
|
125
182
|
```bash
|
|
126
183
|
bun run changelog:build # rebuilds CHANGELOG.md rollup from per-version files
|
|
@@ -129,9 +186,9 @@ bun run tree # regenerates docs/tree.md — run when files were ad
|
|
|
129
186
|
|
|
130
187
|
Both scripts are idempotent — safe to run even if nothing changed.
|
|
131
188
|
|
|
132
|
-
###
|
|
189
|
+
### 7. Run the verification gate
|
|
133
190
|
|
|
134
|
-
The
|
|
191
|
+
The stack being shipped must pass verification. Both must succeed:
|
|
135
192
|
|
|
136
193
|
```bash
|
|
137
194
|
bun run devcheck
|
|
@@ -139,69 +196,28 @@ bun run test:all # or `bun run test` if no test:all script exists
|
|
|
139
196
|
bun run test:package # only if the script exists — NOT part of test:all
|
|
140
197
|
```
|
|
141
198
|
|
|
142
|
-
**If either fails, halt.** Do not bypass verification to land the commit.
|
|
199
|
+
**If either fails, halt.** Do not bypass verification to land the release commit.
|
|
143
200
|
|
|
144
|
-
|
|
201
|
+
The work is already committed by this point, so the fix is a new commit on top of the stack, under step 3's conventions — never `git commit --amend`, never a rebase, reset, or any other rewrite of a commit the stack already carries. Land the fix, then re-run this step. The same holds when the gate passes but leaves the tree dirty: `devcheck` auto-fixes as it runs, and a formatter fix to a file committed in step 3 is a follow-up commit of its own, not something to fold into the release commit.
|
|
145
202
|
|
|
146
|
-
|
|
203
|
+
Only the version bump, the changelog entry, and the regenerated artifacts may still be uncommitted when this step goes green.
|
|
147
204
|
|
|
148
|
-
|
|
149
|
-
git branch --show-current # must be main
|
|
150
|
-
git switch -c release/<version> # uncommitted work rides along
|
|
151
|
-
```
|
|
205
|
+
### 8. Commit the release artifacts
|
|
152
206
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
Do NOT `git add -A` into one commit. Group the working tree into a handful of logical commits — never one blob:
|
|
156
|
-
|
|
157
|
-
1. **The work — one commit per concern.** A feature spanning multiple layers splits by layer: runtime/logic, linter/tooling, docs/skills. Unrelated changes (two separate fixes, an incidental doc tweak) are their own commits. Work commits do not carry the version.
|
|
158
|
-
2. **The release commit — last, on top.** Version bumps (`package.json`, `server.json`, `manifest.json`, the plugin manifests, README badge, `CLAUDE.md`/`AGENTS.md`), the changelog entry, `CHANGELOG.md`, and `docs/tree.md` go in a single final commit that sits on top of the work stack — never mixed into a feature commit.
|
|
159
|
-
|
|
160
|
-
Stage each group explicitly, commit it by pathspec, then move to the next — the release commit goes last:
|
|
207
|
+
One commit, on top of the work stack from step 3, carrying only what steps 4–6 produced: the version bumps (`package.json`, `server.json`, `manifest.json`, the plugin manifests, README badge, `CLAUDE.md`/`AGENTS.md`), the changelog entry, `CHANGELOG.md`, and `docs/tree.md`.
|
|
161
208
|
|
|
162
209
|
```bash
|
|
163
|
-
git add <
|
|
164
|
-
git commit --only <
|
|
165
|
-
# repeat per concern; version + changelog + tree are the final commit
|
|
210
|
+
git add <release-artifact-paths>
|
|
211
|
+
git commit --only <release-artifact-paths> -m "chore(release): <version> — <theme>" -m "<body>"
|
|
166
212
|
```
|
|
167
213
|
|
|
168
|
-
**
|
|
169
|
-
|
|
170
|
-
**The file is the atomic boundary:** NEVER split a single file's working-tree changes across commits, regardless of mechanism — not `git add -p`, not an index-only patch (`git apply --cached`), not editing the file between commits to remove-then-re-add a hunk. When one file serves two concerns, it ships whole in the commit of its dominant concern; a later commit may touch the file again only for changes made AFTER the first commit (a version badge bumped after the fix landed).
|
|
171
|
-
|
|
172
|
-
**Subject format:** Conventional Commits.
|
|
173
|
-
- Work commits (no version): `feat: hosted server endpoint`, `fix: handle empty SPARQL result sets`, `feat(linter): enrichment contract rules`, `docs: document the enrichment block`
|
|
174
|
-
- Release commit (subject leads with the version): `chore(release): 0.2.1 — empty SPARQL result handling`
|
|
175
|
-
|
|
176
|
-
**Body: every commit has one, and it is one or two lines.** Uniform across the stack — no commit ships subject-only, none ships a paragraph. One sentence stating the *why* or the load-bearing constraint, a second only if the first genuinely cannot carry it. Two lines is the hard ceiling.
|
|
177
|
-
|
|
178
|
-
```
|
|
179
|
-
fix: handle empty SPARQL result sets
|
|
180
|
-
|
|
181
|
-
Upstream returns 200 with an empty bindings array rather than 404.
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Never put a closing keyword in a commit body.** `Fixes #N`, `Closes #N`, `Resolves #N` and friends close the issue the moment the commit is pushed — before the close-out comment recording what shipped, so the issue closes with no account of the fix. Reference issues as bare `(#N)` backlinks in the subject or body; closing is a deliberate later step.
|
|
185
|
-
|
|
186
|
-
A body is too long the moment it:
|
|
187
|
-
- enumerates the files, subsystems, or symbols touched — that is `git show --stat`
|
|
188
|
-
- walks through how the implementation works — that is the code
|
|
189
|
-
- narrates a fix's mechanism across multiple sentences — that is the changelog entry
|
|
190
|
-
- runs to a second paragraph, ever
|
|
191
|
-
|
|
192
|
-
The changelog carries the depth, the tag carries the headline, the commit carries one line of why. When the body wants to grow, that pressure is telling you the content belongs in the changelog entry.
|
|
193
|
-
|
|
194
|
-
**Rules:**
|
|
195
|
-
- Plain `-m` flag only — no heredoc, no command substitution
|
|
196
|
-
- No `Co-authored-by` or `Generated with` trailers
|
|
197
|
-
- No marketing adjectives ("comprehensive", "robust", "enhanced", "seamless", "improved")
|
|
198
|
-
- Each commit message stands alone for someone reading `git log` — no chat context, option numbers, or "as discussed"
|
|
214
|
+
**Subject leads with the version:** `chore(release): 0.2.1 — empty SPARQL result handling`. Step 3's conventions carry over unchanged — pathspec staging rather than the bare index, a one- or two-line body, no closing keywords, no trailers, no marketing adjectives.
|
|
199
215
|
|
|
200
|
-
|
|
216
|
+
Anything else still uncommitted at this point was made after step 3 — a formatter auto-fix, a gate fix. It is committed on its own first, and the release commit goes on top of it; it is never folded in.
|
|
201
217
|
|
|
202
|
-
###
|
|
218
|
+
### 9. Open the release PR (release PR mode only)
|
|
203
219
|
|
|
204
|
-
Skip this step entirely when the project has no release PR mode — go to step
|
|
220
|
+
Skip this step entirely when the project has no release PR mode — go to step 10.
|
|
205
221
|
|
|
206
222
|
```bash
|
|
207
223
|
git push -u origin release/<version>
|
|
@@ -212,10 +228,10 @@ gh pr create --base main --head release/<version> --title "<release commit subje
|
|
|
212
228
|
|
|
213
229
|
**Body — always via `--body-file`, never an inline `--body` string** (backticks inside a double-quoted argument are command substitution and silently vanish). Write the file to a scratch location, not into the repo.
|
|
214
230
|
|
|
215
|
-
The body is the release digest — the
|
|
231
|
+
The body is the release digest — the `## Changes` bullets and changelog link the annotated tag will carry, under a theme line and above a gates record that both stay on the PR. The digest is written here, reviewed on the PR, and copied into the tag at release time, so it is the one place the release notes get reviewed before they become permanent. Format:
|
|
216
232
|
|
|
217
233
|
```
|
|
218
|
-
<theme — the changelog entry's summary: line, plain prose, one line>
|
|
234
|
+
<theme — the changelog entry's summary: line, plain prose, one line. It opens the PR; the tag's subject is written fresh at release time and is not this line>
|
|
219
235
|
|
|
220
236
|
## Changes
|
|
221
237
|
|
|
@@ -236,8 +252,8 @@ The body is the release digest — the same headline digest the annotated tag wi
|
|
|
236
252
|
|
|
237
253
|
**Rules:**
|
|
238
254
|
- **`## Changes` follows the tag rules exactly** (`release-and-publish` step 4): flat bullets, never Keep-a-Changelog section headers; complete at headline granularity — notable changes get their own bullet, minor/internal items share ONE grouped bullet; deps one line max, naming only what earns it; no narrative, no marketing adjectives. Depth lives in the changelog entry, which is in this PR's diff and linked on the last line.
|
|
239
|
-
- **Every claim traces to the diff and to the changelog entry.** The body is derived from the entry you authored in step
|
|
240
|
-
- **`## Gates` is the one release surface that carries gate results** — the exact commands from step
|
|
255
|
+
- **Every claim traces to the diff and to the changelog entry.** The body is derived from the entry you authored in step 5, never written independently of it.
|
|
256
|
+
- **`## Gates` is the one release surface that carries gate results** — the exact commands from step 7 with their outcomes. It never enters the tag.
|
|
241
257
|
- **Issue references are bare `(#N)` backlinks — never a closing keyword** (`Closes #N`, `Fixes #N`); the merge would close the issue before its close-out comment lands.
|
|
242
258
|
- **Changelog link is the final line**, same form as the tag, blank line above it.
|
|
243
259
|
- Length is earned — a theme, two bullets, gates, and the link is a complete body for a small patch.
|
|
@@ -248,7 +264,7 @@ If the review pass changes what ships, `release-pr-review` updates `## Changes`
|
|
|
248
264
|
|
|
249
265
|
**Straight-through mode:** continue directly into `release-and-publish`.
|
|
250
266
|
|
|
251
|
-
###
|
|
267
|
+
### 10. Verify end state
|
|
252
268
|
|
|
253
269
|
```bash
|
|
254
270
|
git log --oneline -8 # confirm the commit stack: work commits + release commit on top
|
|
@@ -272,7 +288,8 @@ If the working tree isn't clean or the release commit isn't at HEAD, something w
|
|
|
272
288
|
|
|
273
289
|
## Checklist
|
|
274
290
|
|
|
275
|
-
- [ ] Diff reviewed end-to-end before
|
|
291
|
+
- [ ] Diff reviewed end-to-end before the first commit
|
|
292
|
+
- [ ] Work concerns committed before the version bump — a version-bearing file a work concern also touches ships whole in that concern's commit, so the release commit brings it the version hunk alone
|
|
276
293
|
- [ ] Version bumped in every declaring file (`package.json`, `server.json`, `manifest.json`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, README badge, `CLAUDE.md`/`AGENTS.md` if they pin a version) — verify by command, not by eye: `v=$(jq -r .version package.json); grep -rl "$v" package.json server.json manifest.json .claude-plugin/plugin.json .codex-plugin/plugin.json README.md | wc -l` must equal the count of files that exist, and `grep -c "Version-$v-" README.md` must print `1`. `lint:packaging` checks the README badge against `package.json`, so a stale badge now fails `devcheck` instead of shipping unnoticed — the grep still catches a badge written in a shape the check skips
|
|
277
294
|
- [ ] GH issues addressed by this work commented with what landed (if working from GH issues)
|
|
278
295
|
- [ ] Docs updated for any new or changed features
|
|
@@ -284,6 +301,7 @@ If the working tree isn't clean or the release commit isn't at HEAD, something w
|
|
|
284
301
|
- [ ] `bun run test:package` passes, when the project defines it — it guards the public-export manifest and `test:all` does not run it
|
|
285
302
|
- [ ] Release PR mode: stack committed on `release/<version>`, never on `main`
|
|
286
303
|
- [ ] Work grouped into logical commits (large features split by layer); release artifacts (version + changelog + tree) committed separately on top, subject leading with the version
|
|
304
|
+
- [ ] A gate failure after the work is committed landed as a new commit on the stack — nothing amended, rebased, or otherwise rewritten
|
|
287
305
|
- [ ] Every commit carries a body, and every body is one or two lines — none subject-only, none a paragraph
|
|
288
306
|
- [ ] Release PR mode: branch pushed, PR open — title = release commit subject; body = theme line, `## Changes` in tag rules, `## Gates`, changelog link last (via `--body-file`, no closing keywords)
|
|
289
307
|
- [ ] Working tree clean
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Ship a release end-to-end across every registry the project targets (npm, MCP Registry, GitHub Releases for `.mcpb` bundles, GHCR). Runs the final verification gate, fast-forwards `main` when the release rode a release PR, creates the annotated tag on the commit `main` now points at, pushes commits and tags, then publishes to each applicable destination. Assumes git wrapup (version bumps, changelog, commit stack — and in release PR mode, the pushed branch and open PR) is already complete — this skill is the post-wrapup merge + tag + publish workflow. Retries transient network failures on publish steps; halts with a partial-state report when retries are exhausted or the failure is terminal.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.19"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -121,14 +121,14 @@ If `v<version>` already exists and points at HEAD, a prior run created it — pr
|
|
|
121
121
|
|
|
122
122
|
Write the message to a file through a quoted-delimiter heredoc and pass it with `-F`, never inline with `-m`: the body carries backticks, which a double-quoted string runs as command substitution and silently deletes, and apostrophes, which end a single-quoted string. The tag message renders as the GitHub Release body via `--notes-from-tag`. It must be structured markdown, not a flat string.
|
|
123
123
|
|
|
124
|
-
**Release PR mode: the tag body is the PR body's `## Changes` bullets plus its final changelog link, verbatim** — `gh pr view <N> --json body -q .body` (`<N>` from step 1 — on `main` there is no branch for `gh` to infer it from), take the
|
|
124
|
+
**Release PR mode: the tag body is the PR body's `## Changes` bullets plus its final changelog link, verbatim** — `gh pr view <N> --json body -q .body` (`<N>` from step 1 — on `main` there is no branch for `gh` to infer it from), take the bullets under `## Changes` and the last line; drop the PR's opening theme line, `## Gates`, and the headers. That digest was authored at wrapup and reviewed on the PR; re-authoring it here would publish unreviewed words. The subject is the one part not lifted — write it fresh, per the rules below. The one addition to the digest: append ` · release PR #<N>` to that final line, so the GitHub Release points at its audit trail (GitHub autolinks the bare `#<N>`). Without a PR, author the bullets from the changelog entry at `changelog/<major.minor>.x/<version>.md` — every claim in the tag must appear in that file.
|
|
125
125
|
|
|
126
126
|
`--cleanup=whitespace` is load-bearing. The default cleanup (`strip`) deletes `#`-leading lines as comments, so markdown headers silently vanish from the tag body. `--cleanup=verbatim` is worse: it skips end-of-message normalization, so with tag signing enabled the signature is appended flush against the message's last character — git then can't parse its own signature (the tag reads as unsigned) and the whole `-----BEGIN SSH SIGNATURE-----` block publishes verbatim into the GitHub Release body.
|
|
127
127
|
|
|
128
128
|
Format — a **headline digest**, never a section-by-section changelog mirror:
|
|
129
129
|
|
|
130
130
|
```
|
|
131
|
-
<
|
|
131
|
+
<subject — one short theme written for this tag, ~60 chars; omit the version number, GitHub prepends v<VERSION>:>
|
|
132
132
|
|
|
133
133
|
- <notable user-facing change> (#N)
|
|
134
134
|
- <notable user-facing change> (#N)
|
|
@@ -141,7 +141,7 @@ Format — a **headline digest**, never a section-by-section changelog mirror:
|
|
|
141
141
|
(` · release PR #<N>` only in release PR mode; without a PR the line ends at the changelog link.)
|
|
142
142
|
|
|
143
143
|
**Rules:**
|
|
144
|
-
- **Subject line is ONE short theme, at most ~60 characters, no semicolons, no clauses** — it becomes the GitHub Release title after `v<VERSION>: `. The digest lives in the bullets; a subject that summarizes each change is wrong even when every word is accurate.
|
|
144
|
+
- **Subject line is ONE short theme, at most ~60 characters, no semicolons, no clauses** — it becomes the GitHub Release title after `v<VERSION>: `. The digest lives in the bullets; a subject that summarizes each change is wrong even when every word is accurate. **It is written for this tag, never lifted** — not from the changelog entry's `summary:`, which has a 350-character budget for a different surface, and not from the PR body's opening paragraph, which is that same line. The release commit's subject after the version and dash is usually the theme already
|
|
145
145
|
- Subject line omits the version number (GitHub prepends `v<VERSION>:` to the release title)
|
|
146
146
|
- **Flat bullets only — never Keep-a-Changelog section headers.** `Added:`/`Changed:`/`Fixed:`/`Dependency bumps:` belong in the changelog file; a tag that mirrors the changelog's structure is wrong even when every line is accurate
|
|
147
147
|
- **Complete at headline granularity** — every changelog-worthy change stays visible: notable changes get their own bullet, minor/internal items (build config, repo hygiene, metadata) share ONE grouped compact bullet. Nothing silently dropped, nothing expanded — the changelog carries the depth, the tag carries the existence
|
|
@@ -313,7 +313,7 @@ If any check fails, halt and report which destination is unreachable. A successf
|
|
|
313
313
|
- [ ] `bun run test:all` (or `test`) passes
|
|
314
314
|
- [ ] `bun run test:package` passes, when the project defines it
|
|
315
315
|
- [ ] Release PR mode: `git merge --ff-only` onto `main` locally — never the GitHub merge button; HEAD equals the PR's `headRefOid` afterwards
|
|
316
|
-
- [ ] Annotated tag `v<version>` created on HEAD (`main`'s tip in release PR mode) with `--cleanup=whitespace`, headline-digest body, changelog link as final line, signature parses
|
|
316
|
+
- [ ] Annotated tag `v<version>` created on HEAD (`main`'s tip in release PR mode) with `--cleanup=whitespace`, a subject written fresh at ~60 characters without the version, headline-digest body, changelog link as final line, signature parses
|
|
317
317
|
- [ ] `main` pushed, then the tag pushed
|
|
318
318
|
- [ ] Release PR mode: PR reports `MERGED`; remote and local `release/<version>` deleted
|
|
319
319
|
- [ ] `bun publish --access public` succeeds
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Review pass on an open release PR (`release/<version>` → `main`) — the step between `git-wrapup` and `release-and-publish` when a project releases in gated release PR mode. Reads the PR's commit range through the `code-simplifier` lens plus a correctness review, verifies whatever an automated reviewer left on the PR, lands fixes as ordinary commits on top of the release branch and pushes it, keeps the PR body in sync with what ships, and leaves one summary comment. The only agent role that both edits and commits — and it never rewrites pushed history, tags, merges, touches `main`, or publishes.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.4"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -53,7 +53,7 @@ Two lenses over the range. Skip a dimension that does not apply; do not run any
|
|
|
53
53
|
- **Over-engineering.** Abstractions with one caller, options nothing sets, guards for states the framework already prevents, flexibility for a hypothetical. Cut what does not earn its place.
|
|
54
54
|
- **Tests that cannot fail.** A test authored after the fix that never went red, an assertion on a mocked value, a `toBeDefined()` where a shape was meant. Tighten or replace.
|
|
55
55
|
- **Changelog vs diff.** Every claim in the changelog entry and its `summary:` line exists in the diff — a path, an identifier, a field list, a mechanism. A claim the diff does not support is fixed in the changelog, never argued for. Changes in the diff the changelog omits get a bullet.
|
|
56
|
-
- **PR body vs changelog.** The body's theme line is the entry's `summary:`; its `## Changes` bullets are the entry at headline granularity under the tag rules (`release-and-publish` step 4) — nothing in the entry silently missing, nothing in the body the entry lacks.
|
|
56
|
+
- **PR body vs changelog.** The body's theme line is the entry's `summary:`; its `## Changes` bullets are the entry at headline granularity under the tag rules (`release-and-publish` step 4) — nothing in the entry silently missing, nothing in the body the entry lacks. Those bullets and the changelog link become the tag body verbatim at release, so they are reviewed to that standard: flat bullets, one grouped minor bullet, deps one line, backlinks, no closing keywords, no marketing adjectives, changelog link last. The tag's subject is not lifted from this body — it is written fresh at release time.
|
|
57
57
|
- **Version-bearing files.** The version string is consistent across `package.json`, `server.json`, `manifest.json`, the plugin manifests, the README badge, and any doc that pins it (`grep -rn "<version>" . --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=changelog` catches stragglers).
|
|
58
58
|
- **Stack shape.** Every commit carries a one- or two-line body, no closing keywords anywhere, the release commit is on top and carries only release artifacts.
|
|
59
59
|
|
|
@@ -77,7 +77,7 @@ git add <paths>
|
|
|
77
77
|
git commit --only <paths> -m "<subject>" -m "<one- or two-line body>"
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
`--only` commits the named paths and nothing else in the index, so a stray staged change — a hook's output, a concurrent stage — cannot ride into a review commit. Group the fixes the way `git-wrapup` step
|
|
80
|
+
`--only` commits the named paths and nothing else in the index, so a stray staged change — a hook's output, a concurrent stage — cannot ride into a review commit. Group the fixes the way `git-wrapup` step 3 groups the work: one commit per concern, a Conventional Commits subject, a one- or two-line body, and the file as the atomic boundary. Name the commit for the fix itself, not for the commit it corrects.
|
|
81
81
|
|
|
82
82
|
When every fix is in, re-run the full gate — `bun run devcheck`, `bun run rebuild`, `bun run test:all` (or `test`), `bun run test:package` where defined. Then, and only then:
|
|
83
83
|
|
|
@@ -92,7 +92,7 @@ If the review changes nothing, skip this step: no commit, no push.
|
|
|
92
92
|
|
|
93
93
|
### 6. Sync the PR body
|
|
94
94
|
|
|
95
|
-
The PR body is the release digest — theme line, `## Changes`, `## Gates`, changelog link (`git-wrapup` step
|
|
95
|
+
The PR body is the release digest — theme line, `## Changes`, `## Gates`, changelog link (`git-wrapup` step 9) — and `release-and-publish` lifts `## Changes` plus the link into the tag verbatim. It must describe what ships *now*:
|
|
96
96
|
|
|
97
97
|
- What ships changed in step 5 (a fix altered behavior, a bullet was wrong or missing, the changelog entry changed) → edit `## Changes` and the theme line surgically. Fetch the body with `gh pr view --json body -q .body > <scratch-file>`, edit that file, write it back with `gh pr edit <N> --body-file <scratch-file>`. Never an inline `--body` string.
|
|
98
98
|
- Gates re-ran in step 5 → replace the `## Gates` results with the new ones.
|
|
@@ -134,7 +134,7 @@ Then report back to the caller: PR number, new head SHA, whether the body change
|
|
|
134
134
|
- [ ] Changelog entry and `summary:` reconciled to the diff; version strings consistent
|
|
135
135
|
- [ ] Fixes landed as ordinary commits by pathspec on top of the stack; nothing already pushed rewritten
|
|
136
136
|
- [ ] Full gate green before `git push origin release/<version>`
|
|
137
|
-
- [ ] PR body reviewed as the future tag (theme = `summary:`, `## Changes` in tag rules); synced only where what ships changed; `## Gates` refreshed if gates re-ran
|
|
137
|
+
- [ ] PR body reviewed as the future tag (theme = `summary:`, `## Changes` and changelog link in tag rules); synced only where what ships changed; `## Gates` refreshed if gates re-ran
|
|
138
138
|
- [ ] Out-of-scope findings filed as issues
|
|
139
139
|
- [ ] One summary comment on the PR; report to the caller with the new head SHA
|
|
140
140
|
- [ ] Nothing tagged, nothing merged, `main` untouched
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
File a bug or feature request against @cyanheads/mcp-ts-core when you hit a framework issue. Use when a builder, utility, context method, or config behaves contrary to the documented API — not for server-specific application bugs.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.12"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -42,18 +42,16 @@ gh api 'repos/cyanheads/mcp-ts-core/issues/<number>/timeline' --paginate \
|
|
|
42
42
|
|
|
43
43
|
## Writing Well-Structured Issues
|
|
44
44
|
|
|
45
|
-
Good issues are
|
|
45
|
+
Good issues are terse and fact-dense. **Budget: a bug reads in ~150 words, a feature in ~250, code and logs excluded.** Every section past the form's required fields must earn its place — a section you could delete without changing the fix is noise. One or two sentences per bullet; if a bullet runs long, split it or cut it.
|
|
46
46
|
|
|
47
|
+
- **Cut what dilutes the signal.** Mechanism walkthroughs (link the PR or doc instead), ceremonial framings ("This issue covers…"), conversation references ("as discussed", "per offline"), restated context the reader already has, and kitchen-sink Additional context blocks. If a paragraph isn't pulling weight, drop it.
|
|
47
48
|
- **Lead with specifics.** Name the tool, function, module, or symptom. "Currently `createApp()` throws `ConfigurationError` when `MCP_HTTP_PORT` is set to `0`" beats "There's a problem with the config." A reader should know what's broken or missing before the end of the first sentence.
|
|
48
49
|
- **Embed library/service links on first mention.** `[Hono](https://hono.dev/)`, `[linkedom](https://github.com/WebReflection/linkedom)`. Link to the canonical repo or homepage so readers can verify the dependency and reach docs in one click.
|
|
49
50
|
- **Use `owner/repo#N` for cross-repo issue references.** GitHub auto-renders them as linked references (e.g. `cyanheads/pubmed-mcp-server#34`). Bare `#N` only works for same-repo issues.
|
|
50
51
|
- **Add a `Related: #N` line** near the top when the issue grows from prior context (discussions, other issues, PRs). Makes provenance clickable.
|
|
51
52
|
- **Cite cross-references once per body.** Link an issue/PR in `Related:`, the description, or Additional context — not all three. The reader sees them all; redundant linking dilutes signal.
|
|
52
|
-
- **Lead design sections with a philosophy sentence.** Bold a short principle before the tradeoff details — e.g. "Philosophy: **fail fast on config errors, degrade gracefully on runtime errors.**" Establishes the lens for the rest of the section.
|
|
53
53
|
- **Prefer Markdown tables for comparisons.** When showing options, tiers, strategies, or tradeoffs — tables are the highest-density format for scanning N rows × M attributes.
|
|
54
|
-
- **Separate `### Scope` from `### Out of scope`.** The latter is as important as the former — it pre-empts scope-creep debates in comments and signals you've thought about the boundaries.
|
|
55
54
|
- **Use `Depends on: owner/repo#N`** to declare ordering explicitly when implementation is blocked on another issue landing first.
|
|
56
|
-
- **Cut what dilutes the signal.** Mechanism walkthroughs (link the PR or doc instead), ceremonial framings ("This issue covers…"), conversation references ("as discussed", "per offline"), and kitchen-sink Additional context blocks. If a paragraph isn't pulling weight, drop it.
|
|
57
55
|
- **Skip collaborator-framing sign-offs.** Lines like "Happy to open a PR", "let me know if you'd like", "willing to contribute", "if that's the preferred flow" read as noise. A PR link beats an offer; if you're the maintainer filing against your own repo, the offer is redundant. End the body at the last substantive point.
|
|
58
56
|
|
|
59
57
|
## Redact Before Posting
|
|
@@ -72,7 +70,7 @@ gh issue create -R cyanheads/mcp-ts-core --template "Bug Report" --web
|
|
|
72
70
|
|
|
73
71
|
### CLI (non-interactive)
|
|
74
72
|
|
|
75
|
-
Structure the `--body` to match the template's form fields
|
|
73
|
+
Structure the `--body` to match the template's form fields. Description is two or three sentences; the reproduction is the minimal code and the observed output, nothing else. Add `### Additional context` only when it changes the fix (a workaround, a related issue, the one log line that matters) — omitted by default.
|
|
76
74
|
|
|
77
75
|
````bash
|
|
78
76
|
gh issue create -R cyanheads/mcp-ts-core \
|
|
@@ -131,10 +129,6 @@ Error: Output validation failed: ...
|
|
|
131
129
|
### Expected behavior
|
|
132
130
|
|
|
133
131
|
Omitting an optional output field should pass validation.
|
|
134
|
-
|
|
135
|
-
### Additional context
|
|
136
|
-
|
|
137
|
-
Any workarounds, related issues, or observations.
|
|
138
132
|
ISSUE
|
|
139
133
|
)"
|
|
140
134
|
````
|
|
@@ -214,7 +208,7 @@ gh issue create -R cyanheads/mcp-ts-core --template "Feature Request" --web
|
|
|
214
208
|
|
|
215
209
|
### CLI (non-interactive)
|
|
216
210
|
|
|
217
|
-
The first three headings are the Feature Request form's own fields, in its order — `Use case` and `Proposed API` are required by the form, so a body without them does not satisfy it.
|
|
211
|
+
The first three headings are the Feature Request form's own fields, in its order — `Use case` and `Proposed API` are required by the form, so a body without them does not satisfy it. `Out of scope` is one or two lines. Nothing else by default: a `Scope`, `Flow`, `Design / Tradeoffs`, or `Depends on` block is added only when the reader cannot act without it, and each stays to a few lines.
|
|
218
212
|
|
|
219
213
|
````bash
|
|
220
214
|
gh issue create -R cyanheads/mcp-ts-core \
|
|
@@ -245,33 +239,9 @@ const result = await withRetry(() => fetchExternal(url), {
|
|
|
245
239
|
|
|
246
240
|
What you tried or evaluated instead, and why it didn't fit.
|
|
247
241
|
|
|
248
|
-
### Scope
|
|
249
|
-
|
|
250
|
-
- Files or modules touched
|
|
251
|
-
- New exports, env vars, or config keys
|
|
252
|
-
- Tier (Tier 1 core / Tier 2 standard / Tier 3 optional peer dep)
|
|
253
|
-
|
|
254
242
|
### Out of scope
|
|
255
243
|
|
|
256
|
-
- What we're deliberately not doing
|
|
257
244
|
- Adjacent work that belongs in a separate issue
|
|
258
|
-
|
|
259
|
-
### Flow (optional)
|
|
260
|
-
|
|
261
|
-
Ordered steps — e.g. `trigger → resolve → fetch → degrade`. Useful when the change spans multiple phases or fallbacks.
|
|
262
|
-
|
|
263
|
-
### Design / Tradeoffs (optional)
|
|
264
|
-
|
|
265
|
-
Philosophy: **one-line principle in bold.**
|
|
266
|
-
|
|
267
|
-
| Option | Strengths | Weaknesses |
|
|
268
|
-
|:---|:---|:---|
|
|
269
|
-
| A | ... | ... |
|
|
270
|
-
| B | ... | ... |
|
|
271
|
-
|
|
272
|
-
### Dependencies (optional)
|
|
273
|
-
|
|
274
|
-
- Depends on: owner/repo#N
|
|
275
245
|
ISSUE
|
|
276
246
|
)"
|
|
277
247
|
````
|
|
@@ -299,3 +269,4 @@ gh issue list -R cyanheads/mcp-ts-core --author @me
|
|
|
299
269
|
- [ ] Primary label assigned (`bug` / `enhancement` / `documentation`)
|
|
300
270
|
- [ ] If bug: version, runtime, repro code, actual vs expected behavior included
|
|
301
271
|
- [ ] If feature: `Use case` and `Proposed API` present (the form's required fields), `Alternatives considered` third; Out of scope defined
|
|
272
|
+
- [ ] Inside the budget — ~150 words for a bug, ~250 for a feature, code and logs excluded — and every section past the form's fields earns its place
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
File a bug or feature request against this MCP server's own repo. Use for server-specific issues — tool logic, service integrations, config problems, or domain bugs that aren't caused by the framework.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.10"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -49,18 +49,16 @@ gh api 'repos/{owner}/{repo}/issues/<number>/timeline' --paginate \
|
|
|
49
49
|
|
|
50
50
|
## Writing Well-Structured Issues
|
|
51
51
|
|
|
52
|
-
Good issues are
|
|
52
|
+
Good issues are terse and fact-dense. **Budget: a bug reads in ~150 words, a feature in ~250, code and logs excluded.** Every section past the form's required fields must earn its place — a section you could delete without changing the fix is noise. One or two sentences per bullet; if a bullet runs long, split it or cut it.
|
|
53
53
|
|
|
54
|
+
- **Cut what dilutes the signal.** Mechanism walkthroughs (link the PR or doc instead), ceremonial framings ("This issue covers…"), conversation references ("as discussed", "per offline"), restated context the reader already has, and kitchen-sink Additional context blocks. If a paragraph isn't pulling weight, drop it.
|
|
54
55
|
- **Lead with specifics.** Name the tool, service, resource, or symptom. "Currently `search_docs` returns an empty array for queries containing `&`" beats "Search is broken." A reader should know what's wrong before the end of the first sentence.
|
|
55
56
|
- **Embed library/service links on first mention.** `[Hono](https://hono.dev/)`, `[Supabase](https://supabase.com/)`. Link to the canonical repo or homepage so readers can verify the dependency and reach docs in one click.
|
|
56
57
|
- **Use `owner/repo#N` for cross-repo issue references.** GitHub auto-renders them as linked references (e.g. `cyanheads/mcp-ts-core#46`). Bare `#N` only works for same-repo issues — useful when the bug depends on or relates to a framework issue.
|
|
57
58
|
- **Add a `Related: #N` line** near the top when the issue grows from prior context (discussions, other issues, PRs). Makes provenance clickable.
|
|
58
59
|
- **Cite cross-references once per body.** Link an issue/PR in `Related:`, the description, or Additional context — not all three. The reader sees them all; redundant linking dilutes signal.
|
|
59
|
-
- **Lead design sections with a philosophy sentence.** Bold a short principle before the tradeoff details — e.g. "Philosophy: **return best-effort data, don't fail the tool call on parsing edge cases.**" Establishes the lens for the rest of the section.
|
|
60
60
|
- **Prefer Markdown tables for comparisons.** When showing options, data sources, strategies, or tradeoffs — tables are the highest-density format for scanning N rows × M attributes.
|
|
61
|
-
- **Separate `### Scope` from `### Out of scope`.** The latter is as important as the former — it pre-empts scope-creep debates in comments and signals you've thought about the boundaries.
|
|
62
61
|
- **Use `Depends on: owner/repo#N`** to declare ordering explicitly when implementation is blocked on an upstream framework change or another issue landing first.
|
|
63
|
-
- **Cut what dilutes the signal.** Mechanism walkthroughs (link the PR or doc instead), ceremonial framings ("This issue covers…"), conversation references ("as discussed", "per offline"), and kitchen-sink Additional context blocks. If a paragraph isn't pulling weight, drop it.
|
|
64
62
|
- **Skip collaborator-framing sign-offs.** Lines like "Happy to open a PR", "let me know if you'd like", "willing to contribute", "if that's the preferred flow" read as noise. A PR link beats an offer; if you're the maintainer filing against your own repo, the offer is redundant. End the body at the last substantive point.
|
|
65
63
|
|
|
66
64
|
## Redact Before Posting
|
|
@@ -79,7 +77,7 @@ gh issue create --template "Bug Report" --web
|
|
|
79
77
|
|
|
80
78
|
### CLI (non-interactive)
|
|
81
79
|
|
|
82
|
-
Structure the `--body` to match the template's form fields
|
|
80
|
+
Structure the `--body` to match the template's form fields. Description is two or three sentences; the reproduction is the exact input and the observed output, nothing else. Add `### Additional context` only when it changes the fix (a workaround, a related issue, the one log line that matters) — omitted by default.
|
|
83
81
|
|
|
84
82
|
````bash
|
|
85
83
|
gh issue create \
|
|
@@ -125,10 +123,6 @@ Error or incorrect output here
|
|
|
125
123
|
### Expected behavior
|
|
126
124
|
|
|
127
125
|
What should have happened.
|
|
128
|
-
|
|
129
|
-
### Additional context
|
|
130
|
-
|
|
131
|
-
Relevant `ctx.log` output, stack traces, or telemetry spans.
|
|
132
126
|
ISSUE
|
|
133
127
|
)"
|
|
134
128
|
````
|
|
@@ -213,7 +207,7 @@ gh issue create --template "Feature Request" --web
|
|
|
213
207
|
|
|
214
208
|
### CLI (non-interactive)
|
|
215
209
|
|
|
216
|
-
The first three headings are the Feature Request form's own fields, in its order — `Use case` and `Proposed behavior` are required by the form, so a body without them does not satisfy it.
|
|
210
|
+
The first three headings are the Feature Request form's own fields, in its order — `Use case` and `Proposed behavior` are required by the form, so a body without them does not satisfy it. `Out of scope` is one or two lines. Nothing else by default: a `Scope`, `Flow`, `Design / Tradeoffs`, or `Depends on` block is added only when the reader cannot act without it, and each stays to a few lines.
|
|
217
211
|
|
|
218
212
|
````bash
|
|
219
213
|
gh issue create \
|
|
@@ -239,34 +233,9 @@ What you want the server to do, then the new behavior or surface. For tool/resou
|
|
|
239
233
|
|
|
240
234
|
What you tried or evaluated instead, and why it didn't fit.
|
|
241
235
|
|
|
242
|
-
### Scope
|
|
243
|
-
|
|
244
|
-
- Files or modules touched
|
|
245
|
-
- New env vars, config keys, or service integrations
|
|
246
|
-
- New or modified tools / resources / prompts
|
|
247
|
-
|
|
248
236
|
### Out of scope
|
|
249
237
|
|
|
250
|
-
- What we're deliberately not doing
|
|
251
238
|
- Adjacent work that belongs in a separate issue
|
|
252
|
-
|
|
253
|
-
### Flow (optional)
|
|
254
|
-
|
|
255
|
-
Ordered steps — e.g. `request → lookup → fallback → respond`. Useful when the change spans multiple phases or fallbacks.
|
|
256
|
-
|
|
257
|
-
### Design / Tradeoffs (optional)
|
|
258
|
-
|
|
259
|
-
Philosophy: **one-line principle in bold.**
|
|
260
|
-
|
|
261
|
-
| Option | Strengths | Weaknesses |
|
|
262
|
-
|:---|:---|:---|
|
|
263
|
-
| A | ... | ... |
|
|
264
|
-
| B | ... | ... |
|
|
265
|
-
|
|
266
|
-
### Dependencies (optional)
|
|
267
|
-
|
|
268
|
-
- Depends on: cyanheads/mcp-ts-core#N (upstream framework change)
|
|
269
|
-
- Depends on: owner/repo#N (other server work)
|
|
270
239
|
ISSUE
|
|
271
240
|
)"
|
|
272
241
|
````
|
|
@@ -311,3 +280,4 @@ gh issue close <number> --reason completed --comment "Fixed in <commit or PR>"
|
|
|
311
280
|
- [ ] Primary label assigned (`bug` / `enhancement` / `documentation`)
|
|
312
281
|
- [ ] If bug: version, runtime, repro steps, actual vs expected behavior included
|
|
313
282
|
- [ ] If feature: `Use case` and `Proposed behavior` present (the form's required fields), `Alternatives considered` third; Out of scope defined
|
|
283
|
+
- [ ] Inside the budget — ~150 words for a bug, ~250 for a feature, code and logs excluded — and every section past the form's fields earns its place
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.4",
|
|
4
4
|
"mcpName": "io.github.cyanheads/mcp-ts-core",
|
|
5
5
|
"description": "Agent-native TypeScript framework for MCP servers. Includes runtime infrastructure and agent skills for building, testing, and shipping servers.",
|
|
6
6
|
"files": [
|
|
@@ -306,7 +306,7 @@
|
|
|
306
306
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
307
307
|
"@opentelemetry/api": "^1.9.1",
|
|
308
308
|
"dotenv": "^17.4.2",
|
|
309
|
-
"hono": "^4.13.
|
|
309
|
+
"hono": "^4.13.8",
|
|
310
310
|
"jose": "^6.2.12",
|
|
311
311
|
"pino": "^10.3.1",
|
|
312
312
|
"zod": "^4.6.5"
|