@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.
Files changed (102) hide show
  1. package/AGENTS.md +6 -4
  2. package/CLAUDE.md +6 -4
  3. package/README.md +1 -1
  4. package/changelog/0.13.x/0.13.4.md +65 -0
  5. package/changelog/template.md +7 -7
  6. package/dist/config/appRoot.d.ts.map +1 -1
  7. package/dist/config/appRoot.js +48 -16
  8. package/dist/config/appRoot.js.map +1 -1
  9. package/dist/core/app.d.ts +20 -0
  10. package/dist/core/app.d.ts.map +1 -1
  11. package/dist/core/app.js +1 -0
  12. package/dist/core/app.js.map +1 -1
  13. package/dist/core/index.d.ts +1 -0
  14. package/dist/core/index.d.ts.map +1 -1
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/linter/rules/schema-rules.d.ts +19 -0
  17. package/dist/linter/rules/schema-rules.d.ts.map +1 -1
  18. package/dist/linter/rules/schema-rules.js +36 -0
  19. package/dist/linter/rules/schema-rules.js.map +1 -1
  20. package/dist/linter/rules/tool-rules.d.ts +17 -0
  21. package/dist/linter/rules/tool-rules.d.ts.map +1 -1
  22. package/dist/linter/rules/tool-rules.js +97 -1
  23. package/dist/linter/rules/tool-rules.js.map +1 -1
  24. package/dist/mcp-server/handlerContext.d.ts +6 -0
  25. package/dist/mcp-server/handlerContext.d.ts.map +1 -1
  26. package/dist/mcp-server/handlerContext.js.map +1 -1
  27. package/dist/mcp-server/tools/utils/inputPrevalidation.d.ts +114 -0
  28. package/dist/mcp-server/tools/utils/inputPrevalidation.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/utils/inputPrevalidation.js +428 -0
  30. package/dist/mcp-server/tools/utils/inputPrevalidation.js.map +1 -0
  31. package/dist/mcp-server/tools/utils/strictenRecord.d.ts +42 -0
  32. package/dist/mcp-server/tools/utils/strictenRecord.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/utils/strictenRecord.js +48 -0
  34. package/dist/mcp-server/tools/utils/strictenRecord.js.map +1 -0
  35. package/dist/mcp-server/tools/utils/toolDefinition.d.ts +27 -0
  36. package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/utils/toolDefinition.js +35 -6
  38. package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
  39. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +19 -1
  40. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  41. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +53 -11
  42. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  43. package/dist/services/canvas/core/sqlGate.d.ts +14 -1
  44. package/dist/services/canvas/core/sqlGate.d.ts.map +1 -1
  45. package/dist/services/canvas/core/sqlGate.js +69 -7
  46. package/dist/services/canvas/core/sqlGate.js.map +1 -1
  47. package/dist/services/canvas/index.d.ts +1 -1
  48. package/dist/services/canvas/index.d.ts.map +1 -1
  49. package/dist/services/canvas/index.js +1 -1
  50. package/dist/services/canvas/index.js.map +1 -1
  51. package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts +20 -0
  52. package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts.map +1 -1
  53. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js +75 -25
  54. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js.map +1 -1
  55. package/dist/services/canvas/types.d.ts +6 -1
  56. package/dist/services/canvas/types.d.ts.map +1 -1
  57. package/dist/types-global/errors.d.ts.map +1 -1
  58. package/dist/types-global/errors.js +4 -3
  59. package/dist/types-global/errors.js.map +1 -1
  60. package/dist/utils/index.d.ts +3 -2
  61. package/dist/utils/index.d.ts.map +1 -1
  62. package/dist/utils/index.js +3 -2
  63. package/dist/utils/index.js.map +1 -1
  64. package/dist/utils/network/httpError.d.ts +13 -2
  65. package/dist/utils/network/httpError.d.ts.map +1 -1
  66. package/dist/utils/network/httpError.js +4 -2
  67. package/dist/utils/network/httpError.js.map +1 -1
  68. package/dist/utils/network/pacer.d.ts +117 -0
  69. package/dist/utils/network/pacer.d.ts.map +1 -0
  70. package/dist/utils/network/pacer.js +304 -0
  71. package/dist/utils/network/pacer.js.map +1 -0
  72. package/dist/utils/network/retry.d.ts +119 -3
  73. package/dist/utils/network/retry.d.ts.map +1 -1
  74. package/dist/utils/network/retry.js +176 -35
  75. package/dist/utils/network/retry.js.map +1 -1
  76. package/dist/utils/security/rateLimiter.d.ts +19 -1
  77. package/dist/utils/security/rateLimiter.d.ts.map +1 -1
  78. package/dist/utils/security/rateLimiter.js +49 -1
  79. package/dist/utils/security/rateLimiter.js.map +1 -1
  80. package/dist/utils/telemetry/attributes.d.ts +19 -0
  81. package/dist/utils/telemetry/attributes.d.ts.map +1 -1
  82. package/dist/utils/telemetry/attributes.js +30 -0
  83. package/dist/utils/telemetry/attributes.js.map +1 -1
  84. package/framework-skills/add-tool/SKILL.md +43 -2
  85. package/framework-skills/api-canvas/SKILL.md +8 -4
  86. package/framework-skills/api-config/SKILL.md +4 -4
  87. package/framework-skills/api-errors/SKILL.md +6 -2
  88. package/framework-skills/api-linter/SKILL.md +48 -3
  89. package/framework-skills/api-telemetry/SKILL.md +26 -2
  90. package/framework-skills/api-utils/SKILL.md +7 -3
  91. package/framework-skills/api-utils/references/security.md +2 -2
  92. package/framework-skills/design-mcp-server/SKILL.md +17 -2
  93. package/framework-skills/field-test/SKILL.md +3 -1
  94. package/framework-skills/git-wrapup/SKILL.md +87 -69
  95. package/framework-skills/release-and-publish/SKILL.md +5 -5
  96. package/framework-skills/release-pr-review/SKILL.md +5 -5
  97. package/framework-skills/report-issue-framework/SKILL.md +6 -35
  98. package/framework-skills/report-issue-local/SKILL.md +6 -36
  99. package/package.json +2 -2
  100. package/templates/.github/ISSUE_TEMPLATE/bug_report.yml +2 -2
  101. package/templates/.github/ISSUE_TEMPLATE/feature_request.yml +2 -2
  102. 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). Verify, commit. 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.
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.18"
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 7). 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.
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 6, but starting wrapup on a broken tree wastes the version number and creates a revert-or-amend situation.
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 7 like everything else.
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. Bump version everywhere
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
- ### 4. Author the changelog
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, and it propagates unedited to three further surfaces: the `CHANGELOG.md` rollup, the GitHub Release body, and the annotated tag (which cannot be edited once pushed). 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: the summary is the tag's theme line, and comma-stitching every change into an inventory near the 350-char cap is the failure mode.
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
- ### 5. Regenerate derived artifacts
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
- ### 6. Run the verification gate
189
+ ### 7. Run the verification gate
133
190
 
134
- The tree being committed must pass verification. Both must succeed:
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. Fix the issue first, then re-run from step 6.
199
+ **If either fails, halt.** Do not bypass verification to land the release commit.
143
200
 
144
- ### 7. Commit — group by concern, release artifacts on top
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
- **Release PR mode only — move to the release branch first, before the first commit:**
203
+ Only the version bump, the changelog entry, and the regenerated artifacts may still be uncommitted when this step goes green.
147
204
 
148
- ```bash
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
- 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.
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 <paths-for-this-concern>
164
- git commit --only <paths-for-this-concern> -m "<subject>"
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
- **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 9's clean-tree check instead of shipping silently.
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
- **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 plus the release commit; when the change and its version bump are inseparable for a tiny patch, a single commit whose subject leads with the version is fine. The failure mode to prevent is the inverse: a large, multi-layer feature crammed into one commit alongside the release artifacts.
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
- ### 8. Open the release PR (release PR mode only)
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 9.
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 same headline digest the annotated tag will carry, plus a gates record. It 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:
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 4, never written independently of it.
240
- - **`## Gates` is the one release surface that carries gate results** — the exact commands from step 6 with their outcomes. It never enters the tag.
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
- ### 9. Verify end state
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 version bump
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.18"
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 theme line as the subject, the bullets under `## Changes`, and the last line; drop `## Gates` and the headers. That digest was authored at wrapup and reviewed on the PR; re-authoring it here would publish unreviewed words. The one addition: 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 it from the changelog entry at `changelog/<major.minor>.x/<version>.md` — every claim in the tag must appear in that file, and the file's `summary:` line is the tag's theme.
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
- <theme — omit version number, GitHub prepends v<VERSION>:>
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. In release PR mode the PR body's opening paragraph is NOT the subject — write the theme fresh (the release commit's subject after the version and dash is usually it)
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.3"
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. This body becomes the tag verbatim at release, so it is reviewed to that standard: flat bullets, one grouped minor bullet, deps one line, backlinks, no closing keywords, no marketing adjectives, changelog link last.
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 7 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.
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 8) — and `release-and-publish` lifts `## Changes` plus the link into the tag verbatim. It must describe what ships *now*:
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.11"
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 scannable, concrete, and self-contained — terse and fact-dense. Default to one or two sentences per bullet; if a bullet runs long, split it or cut it. These patterns apply to both bugs and features — the guidance targets any prose block (Description, Additional context, feature proposals).
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. Everything after `Alternatives considered` is supplemental; omit what you don't need — simple requests don't require Flow / Design / Dependencies blocks.
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.9"
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 scannable, concrete, and self-contained — terse and fact-dense. Default to one or two sentences per bullet; if a bullet runs long, split it or cut it. These patterns apply to both bugs and features — the guidance targets any prose block (Description, Additional context, feature proposals).
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. Everything after `Alternatives considered` is supplemental; omit what you don't need — simple requests don't require Flow / Design / Dependencies blocks.
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",
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.7",
309
+ "hono": "^4.13.8",
310
310
  "jose": "^6.2.12",
311
311
  "pino": "^10.3.1",
312
312
  "zod": "^4.6.5"