@mcptoolshop/shipcheck 1.0.0
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/ADOPTION.md +128 -0
- package/LICENSE +21 -0
- package/README.es.md +105 -0
- package/README.fr.md +105 -0
- package/README.hi.md +105 -0
- package/README.it.md +105 -0
- package/README.ja.md +105 -0
- package/README.md +105 -0
- package/README.pt-BR.md +105 -0
- package/README.zh.md +105 -0
- package/bin/shipcheck.mjs +245 -0
- package/contracts/error-contract.md +234 -0
- package/package.json +36 -0
- package/templates/CHANGELOG.md +18 -0
- package/templates/HANDBOOK.md +71 -0
- package/templates/SCORECARD.md +49 -0
- package/templates/SECURITY.md +37 -0
- package/templates/SHIP_GATE.md +80 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Error Contract
|
|
2
|
+
|
|
3
|
+
Structured errors across all MCP Tool Shop products.
|
|
4
|
+
|
|
5
|
+
Two tiers: the **shape** is mandatory everywhere, the **base type** is optional for larger projects.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Tier 1: Structured Error Shape (mandatory)
|
|
10
|
+
|
|
11
|
+
Every user-facing error — whether thrown, returned, or printed — must carry these fields:
|
|
12
|
+
|
|
13
|
+
| Field | Type | Required | Purpose |
|
|
14
|
+
|-------|------|----------|---------|
|
|
15
|
+
| `code` | string | yes | Machine-readable, namespaced (see registry rules below) |
|
|
16
|
+
| `message` | string | yes | What went wrong |
|
|
17
|
+
| `hint` | string | yes | What the user should do about it |
|
|
18
|
+
| `cause` | string/error | no | Original error, for chaining |
|
|
19
|
+
| `retryable` | boolean | no | Can the caller safely retry? |
|
|
20
|
+
|
|
21
|
+
**Simple scripts** don't need a class. Just emit the shape:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"code": "IO_READ_FAILED",
|
|
26
|
+
"message": "Could not read config.json",
|
|
27
|
+
"hint": "Check file permissions or run with --debug",
|
|
28
|
+
"retryable": false
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
# Minimal: return a dict
|
|
34
|
+
{"code": "IO_READ_FAILED", "message": str(e), "hint": "Check file permissions"}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The contract is the shape, not the implementation.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Tier 2: Base Error Type + Exit Codes (CLI / MCP / Desktop)
|
|
42
|
+
|
|
43
|
+
For repos with a CLI, MCP server, or desktop UI — formalize the shape into a typed error class with two output modes.
|
|
44
|
+
|
|
45
|
+
### Output modes
|
|
46
|
+
|
|
47
|
+
| Mode | Audience | Stack traces? | When |
|
|
48
|
+
|------|----------|---------------|------|
|
|
49
|
+
| **safe** | End users, LLMs, MCP | Never | Default |
|
|
50
|
+
| **debug** | Developers | Yes, if available | `--debug` flag |
|
|
51
|
+
|
|
52
|
+
### Exit codes (CLI only)
|
|
53
|
+
|
|
54
|
+
| Code | Meaning |
|
|
55
|
+
|------|---------|
|
|
56
|
+
| 0 | Success |
|
|
57
|
+
| 1 | User error (bad input, missing args, invalid config) |
|
|
58
|
+
| 2 | Runtime error (crash, IO failure, dependency missing) |
|
|
59
|
+
| 3 | Partial success (some items ok, some failed) |
|
|
60
|
+
|
|
61
|
+
### TypeScript reference
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
export class ProductError extends Error {
|
|
65
|
+
readonly code: string;
|
|
66
|
+
readonly hint: string;
|
|
67
|
+
readonly cause?: Error;
|
|
68
|
+
readonly retryable: boolean;
|
|
69
|
+
|
|
70
|
+
constructor(
|
|
71
|
+
code: string,
|
|
72
|
+
message: string,
|
|
73
|
+
hint: string,
|
|
74
|
+
opts?: { cause?: Error; retryable?: boolean },
|
|
75
|
+
) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.name = 'ProductError'; // rename per-product
|
|
78
|
+
this.code = code;
|
|
79
|
+
this.hint = hint;
|
|
80
|
+
this.cause = opts?.cause;
|
|
81
|
+
this.retryable = opts?.retryable ?? false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Safe output — no stack traces. For MCP responses + UI. */
|
|
85
|
+
toSafeText(): string {
|
|
86
|
+
const lines = [
|
|
87
|
+
`Error [${this.code}]: ${this.message}`,
|
|
88
|
+
`Hint: ${this.hint}`,
|
|
89
|
+
];
|
|
90
|
+
if (this.cause) lines.push(`Cause: ${this.cause.message}`);
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Debug output — includes stack. For CLI --debug. */
|
|
95
|
+
toDebugText(): string {
|
|
96
|
+
const lines = [
|
|
97
|
+
`[${this.code}] ${this.message}`,
|
|
98
|
+
` Hint: ${this.hint}`,
|
|
99
|
+
];
|
|
100
|
+
if (this.cause) {
|
|
101
|
+
lines.push(` Cause: ${this.cause.message}`);
|
|
102
|
+
if (this.cause.stack) lines.push(` Stack: ${this.cause.stack}`);
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function wrapError(
|
|
109
|
+
err: unknown,
|
|
110
|
+
code: string,
|
|
111
|
+
hint: string,
|
|
112
|
+
): ProductError {
|
|
113
|
+
if (err instanceof ProductError) return err;
|
|
114
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
115
|
+
return new ProductError(code, cause.message, hint, { cause });
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Python reference
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
class ProductError(Exception):
|
|
123
|
+
"""Structured error with code, hint, and optional cause."""
|
|
124
|
+
|
|
125
|
+
def __init__(
|
|
126
|
+
self,
|
|
127
|
+
code: str,
|
|
128
|
+
message: str,
|
|
129
|
+
hint: str,
|
|
130
|
+
*,
|
|
131
|
+
cause: Exception | None = None,
|
|
132
|
+
retryable: bool = False,
|
|
133
|
+
):
|
|
134
|
+
super().__init__(message)
|
|
135
|
+
self.code = code
|
|
136
|
+
self.hint = hint
|
|
137
|
+
self.__cause__ = cause
|
|
138
|
+
self.retryable = retryable
|
|
139
|
+
|
|
140
|
+
def to_safe_text(self) -> str:
|
|
141
|
+
"""Safe output — no stack traces. For MCP responses + UI."""
|
|
142
|
+
lines = [f"Error [{self.code}]: {self}", f"Hint: {self.hint}"]
|
|
143
|
+
if self.__cause__:
|
|
144
|
+
lines.append(f"Cause: {self.__cause__}")
|
|
145
|
+
return "\n".join(lines)
|
|
146
|
+
|
|
147
|
+
def to_debug_text(self) -> str:
|
|
148
|
+
"""Debug output — includes stack. For CLI --debug."""
|
|
149
|
+
import traceback
|
|
150
|
+
|
|
151
|
+
lines = [f"[{self.code}] {self}", f" Hint: {self.hint}"]
|
|
152
|
+
if self.__cause__:
|
|
153
|
+
lines.append(f" Cause: {self.__cause__}")
|
|
154
|
+
lines.append(
|
|
155
|
+
"".join(traceback.format_exception(self.__cause__))
|
|
156
|
+
)
|
|
157
|
+
return "\n".join(lines)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def wrap_error(err: Exception, code: str, hint: str) -> ProductError:
|
|
161
|
+
"""Wrap any exception into a ProductError."""
|
|
162
|
+
if isinstance(err, ProductError):
|
|
163
|
+
return err
|
|
164
|
+
return ProductError(code, str(err), hint, cause=err)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### .NET pattern
|
|
168
|
+
|
|
169
|
+
```csharp
|
|
170
|
+
public class ProductException : Exception
|
|
171
|
+
{
|
|
172
|
+
public string Code { get; }
|
|
173
|
+
public string Hint { get; }
|
|
174
|
+
public bool Retryable { get; }
|
|
175
|
+
|
|
176
|
+
public ProductException(
|
|
177
|
+
string code, string message, string hint,
|
|
178
|
+
Exception? cause = null, bool retryable = false)
|
|
179
|
+
: base(message, cause)
|
|
180
|
+
{
|
|
181
|
+
Code = code;
|
|
182
|
+
Hint = hint;
|
|
183
|
+
Retryable = retryable;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public string ToSafeText() =>
|
|
187
|
+
$"Error [{Code}]: {Message}\nHint: {Hint}"
|
|
188
|
+
+ (InnerException != null ? $"\nCause: {InnerException.Message}" : "");
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Naming convention
|
|
193
|
+
|
|
194
|
+
Each product renames the class: `GuardianError`, `AttestiaError`, `SoundboardError`, etc.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Error Code Registry Rules
|
|
199
|
+
|
|
200
|
+
Three rules.
|
|
201
|
+
|
|
202
|
+
### 1. Codes are namespaced
|
|
203
|
+
|
|
204
|
+
Use a prefix from this table (extend as needed):
|
|
205
|
+
|
|
206
|
+
| Prefix | Domain |
|
|
207
|
+
|--------|--------|
|
|
208
|
+
| `IO_` | File system, streams, paths |
|
|
209
|
+
| `CONFIG_` | Configuration, settings, env vars |
|
|
210
|
+
| `PERM_` | Permissions, access control |
|
|
211
|
+
| `DEP_` | Dependencies, external services |
|
|
212
|
+
| `RUNTIME_` | Unexpected failures, OOM, timeouts |
|
|
213
|
+
| `PARTIAL_` | Some items succeeded, some failed |
|
|
214
|
+
| `INPUT_` | Bad user input, validation failures |
|
|
215
|
+
| `STATE_` | Corrupt or stale internal state |
|
|
216
|
+
|
|
217
|
+
Examples: `IO_READ_FAILED`, `CONFIG_MISSING_KEY`, `STATE_CORRUPT`, `DEP_OLLAMA_UNREACHABLE`
|
|
218
|
+
|
|
219
|
+
### 2. Codes are stable once released
|
|
220
|
+
|
|
221
|
+
A code that appears in a shipped version is permanent. You can add new codes. You can deprecate old ones (map to a successor). You cannot change what an existing code means.
|
|
222
|
+
|
|
223
|
+
### 3. Every code maps to an exit code + default hint
|
|
224
|
+
|
|
225
|
+
Maintain a table in your repo (in the error file or a separate `ERROR_CODES.md`):
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
IO_READ_FAILED → exit 2 → "Check file exists and permissions are correct"
|
|
229
|
+
CONFIG_MISSING_KEY → exit 1 → "Add the required key to your config file"
|
|
230
|
+
STATE_CORRUPT → exit 2 → "Run --reset to rebuild state"
|
|
231
|
+
PARTIAL_BATCH → exit 3 → "Check logs for individual failures"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This table is your error contract with users. Treat it like an API.
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mcptoolshop/shipcheck",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Product standards for MCP Tool Shop — Ship Gate checklist, error contract, and adoption guides.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"shipcheck": "bin/shipcheck.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"templates",
|
|
12
|
+
"contracts",
|
|
13
|
+
"ADOPTION.md",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "mcp-tool-shop <64996768+mcp-tool-shop@users.noreply.github.com>",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/mcp-tool-shop-org/shipcheck.git"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://mcp-tool-shop-org.github.io/shipcheck/",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"shipcheck",
|
|
26
|
+
"standards",
|
|
27
|
+
"ship-gate",
|
|
28
|
+
"error-contract",
|
|
29
|
+
"checklist",
|
|
30
|
+
"quality",
|
|
31
|
+
"mcp-tool-shop"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
<!-- ## [0.1.0] - YYYY-MM-DD -->
|
|
17
|
+
<!-- ### Added -->
|
|
18
|
+
<!-- - Initial release -->
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Handbook
|
|
2
|
+
|
|
3
|
+
> Field manual for operating **<!-- product name -->**.
|
|
4
|
+
> If it says WARN, do this. If CRITICAL, do this. No fluff.
|
|
5
|
+
|
|
6
|
+
## What it does
|
|
7
|
+
|
|
8
|
+
<!-- One paragraph. What problem it solves, for whom. -->
|
|
9
|
+
|
|
10
|
+
## How it works
|
|
11
|
+
|
|
12
|
+
<!-- Brief architecture: inputs → processing → outputs. Keep it to 3–5 sentences. -->
|
|
13
|
+
|
|
14
|
+
## Daily operations
|
|
15
|
+
|
|
16
|
+
### Starting up
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Replace with your actual startup command
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Normal output
|
|
23
|
+
|
|
24
|
+
<!-- What does "healthy" look like? Example output or status. -->
|
|
25
|
+
|
|
26
|
+
### Logging levels
|
|
27
|
+
|
|
28
|
+
| Level | What you see | When to use |
|
|
29
|
+
|-------|-------------|-------------|
|
|
30
|
+
| silent | Nothing | Automation, scripts |
|
|
31
|
+
| normal | Status + warnings | Default |
|
|
32
|
+
| verbose | Above + progress | Troubleshooting |
|
|
33
|
+
| debug | Everything + stack traces | Bug reports |
|
|
34
|
+
|
|
35
|
+
## When things go wrong
|
|
36
|
+
|
|
37
|
+
### WARN conditions
|
|
38
|
+
|
|
39
|
+
<!-- List warning states and what to do about each. Example: -->
|
|
40
|
+
|
|
41
|
+
| Signal | Meaning | Action |
|
|
42
|
+
|--------|---------|--------|
|
|
43
|
+
| <!-- e.g., "State file stale" --> | <!-- meaning --> | <!-- action --> |
|
|
44
|
+
|
|
45
|
+
### CRITICAL conditions
|
|
46
|
+
|
|
47
|
+
| Signal | Meaning | Action |
|
|
48
|
+
|--------|---------|--------|
|
|
49
|
+
| <!-- e.g., "State corrupt" --> | <!-- meaning --> | <!-- action --> |
|
|
50
|
+
|
|
51
|
+
### Recovery
|
|
52
|
+
|
|
53
|
+
<!-- Step-by-step recovery procedure for the worst case. -->
|
|
54
|
+
|
|
55
|
+
1. <!-- Step 1 -->
|
|
56
|
+
2. <!-- Step 2 -->
|
|
57
|
+
3. <!-- Step 3 -->
|
|
58
|
+
|
|
59
|
+
## Where things live
|
|
60
|
+
|
|
61
|
+
| What | Path |
|
|
62
|
+
|------|------|
|
|
63
|
+
| Config | <!-- path --> |
|
|
64
|
+
| Logs | <!-- path --> |
|
|
65
|
+
| State | <!-- path --> |
|
|
66
|
+
|
|
67
|
+
## Privacy
|
|
68
|
+
|
|
69
|
+
- All data stays local
|
|
70
|
+
- No telemetry, no network unless explicitly configured
|
|
71
|
+
- Secrets are never logged or included in diagnostics
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Scorecard
|
|
2
|
+
|
|
3
|
+
> Score a repo before remediation. Fill this out first, then use SHIP_GATE.md to fix.
|
|
4
|
+
|
|
5
|
+
**Repo:** <!-- repo name -->
|
|
6
|
+
**Date:** <!-- YYYY-MM-DD -->
|
|
7
|
+
**Type tags:** <!-- [npm] [mcp] [cli] etc. -->
|
|
8
|
+
|
|
9
|
+
## Pre-Remediation Assessment
|
|
10
|
+
|
|
11
|
+
| Category | Score | Notes |
|
|
12
|
+
|----------|-------|-------|
|
|
13
|
+
| A. Security | /10 | |
|
|
14
|
+
| B. Error Handling | /10 | |
|
|
15
|
+
| C. Operator Docs | /10 | |
|
|
16
|
+
| D. Shipping Hygiene | /10 | |
|
|
17
|
+
| E. Identity (soft) | /10 | |
|
|
18
|
+
| **Overall** | **/50** | |
|
|
19
|
+
|
|
20
|
+
## Key Gaps
|
|
21
|
+
|
|
22
|
+
<!-- List the 3-5 most critical gaps that need fixing. Be specific. -->
|
|
23
|
+
|
|
24
|
+
1.
|
|
25
|
+
2.
|
|
26
|
+
3.
|
|
27
|
+
|
|
28
|
+
## Remediation Priority
|
|
29
|
+
|
|
30
|
+
<!-- What to fix first, second, third. Informed by the gaps above. -->
|
|
31
|
+
|
|
32
|
+
| Priority | Item | Estimated effort |
|
|
33
|
+
|----------|------|-----------------|
|
|
34
|
+
| 1 | | |
|
|
35
|
+
| 2 | | |
|
|
36
|
+
| 3 | | |
|
|
37
|
+
|
|
38
|
+
## Post-Remediation
|
|
39
|
+
|
|
40
|
+
<!-- Fill this out after applying SHIP_GATE.md -->
|
|
41
|
+
|
|
42
|
+
| Category | Before | After |
|
|
43
|
+
|----------|--------|-------|
|
|
44
|
+
| A. Security | /10 | /10 |
|
|
45
|
+
| B. Error Handling | /10 | /10 |
|
|
46
|
+
| C. Operator Docs | /10 | /10 |
|
|
47
|
+
| D. Shipping Hygiene | /10 | /10 |
|
|
48
|
+
| E. Identity (soft) | /10 | /10 |
|
|
49
|
+
| **Overall** | /50 | /50 |
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
<!-- Replace with your version table -->
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
|---------|-----------|
|
|
9
|
+
| latest | Yes |
|
|
10
|
+
|
|
11
|
+
## Reporting a Vulnerability
|
|
12
|
+
|
|
13
|
+
Email: **64996768+mcp-tool-shop@users.noreply.github.com**
|
|
14
|
+
|
|
15
|
+
Include:
|
|
16
|
+
- Description of the vulnerability
|
|
17
|
+
- Steps to reproduce
|
|
18
|
+
- Version affected
|
|
19
|
+
- Potential impact
|
|
20
|
+
|
|
21
|
+
### Response timeline
|
|
22
|
+
|
|
23
|
+
| Action | Target |
|
|
24
|
+
|--------|--------|
|
|
25
|
+
| Acknowledge report | 48 hours |
|
|
26
|
+
| Assess severity | 7 days |
|
|
27
|
+
| Release fix | 30 days |
|
|
28
|
+
|
|
29
|
+
## Scope
|
|
30
|
+
|
|
31
|
+
<!-- Customize per-product. Examples: -->
|
|
32
|
+
|
|
33
|
+
This tool operates **locally only**.
|
|
34
|
+
- **Data touched:** <!-- e.g., local log files, process metrics -->
|
|
35
|
+
- **No network egress** unless explicitly configured
|
|
36
|
+
- **No secrets handling** — does not read, store, or transmit credentials
|
|
37
|
+
- **No telemetry** is collected or sent
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Ship Gate
|
|
2
|
+
|
|
3
|
+
> No repo is "done" until every applicable line is checked.
|
|
4
|
+
> Copy this into your repo root. Check items off per-release.
|
|
5
|
+
|
|
6
|
+
**Tags:** `[all]` every repo · `[npm]` `[pypi]` `[vsix]` `[desktop]` `[container]` published artifacts · `[mcp]` MCP servers · `[cli]` CLI tools
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## A. Security Baseline
|
|
11
|
+
|
|
12
|
+
- [ ] `[all]` SECURITY.md exists (report email, supported versions, response timeline)
|
|
13
|
+
- [ ] `[all]` README includes threat model paragraph (data touched, data NOT touched, permissions required)
|
|
14
|
+
- [ ] `[all]` No secrets, tokens, or credentials in source or diagnostics output
|
|
15
|
+
- [ ] `[all]` No telemetry by default — state it explicitly even if obvious
|
|
16
|
+
|
|
17
|
+
### Default safety posture
|
|
18
|
+
|
|
19
|
+
- [ ] `[cli|mcp|desktop]` Dangerous actions (kill, delete, restart) require explicit `--allow-*` flag
|
|
20
|
+
- [ ] `[cli|mcp|desktop]` File operations constrained to known directories
|
|
21
|
+
- [ ] `[mcp]` Network egress off by default
|
|
22
|
+
- [ ] `[mcp]` Stack traces never exposed — structured error results only
|
|
23
|
+
|
|
24
|
+
## B. Error Handling
|
|
25
|
+
|
|
26
|
+
- [ ] `[all]` Errors follow the Structured Error Shape: `code`, `message`, `hint`, `cause?`, `retryable?`
|
|
27
|
+
- [ ] `[cli]` Exit codes: 0 ok · 1 user error · 2 runtime error · 3 partial success
|
|
28
|
+
- [ ] `[cli]` No raw stack traces without `--debug`
|
|
29
|
+
- [ ] `[mcp]` Tool errors return structured results — server never crashes on bad input
|
|
30
|
+
- [ ] `[mcp]` State/config corruption degrades gracefully (stale data over crash)
|
|
31
|
+
- [ ] `[desktop]` Errors shown as user-friendly messages — no raw exceptions in UI
|
|
32
|
+
- [ ] `[vscode]` Errors surface via VS Code notification API — no silent failures
|
|
33
|
+
|
|
34
|
+
## C. Operator Docs
|
|
35
|
+
|
|
36
|
+
- [ ] `[all]` README is current: what it does, install, usage, supported platforms + runtime versions
|
|
37
|
+
- [ ] `[all]` CHANGELOG.md (Keep a Changelog format)
|
|
38
|
+
- [ ] `[all]` LICENSE file present and repo states support status
|
|
39
|
+
- [ ] `[cli]` `--help` output accurate for all commands and flags
|
|
40
|
+
- [ ] `[cli|mcp|desktop]` Logging levels defined: silent / normal / verbose / debug — secrets redacted at all levels
|
|
41
|
+
- [ ] `[mcp]` All tools documented with description + parameters
|
|
42
|
+
- [ ] `[complex]` HANDBOOK.md: daily ops, warn/critical response, recovery procedures
|
|
43
|
+
|
|
44
|
+
## D. Shipping Hygiene
|
|
45
|
+
|
|
46
|
+
- [ ] `[all]` `verify` script exists (test + build + smoke in one command)
|
|
47
|
+
- [ ] `[all]` Version in manifest matches git tag
|
|
48
|
+
- [ ] `[all]` Dependency scanning runs in CI (ecosystem-appropriate)
|
|
49
|
+
- [ ] `[all]` Automated dependency update mechanism exists
|
|
50
|
+
- [ ] `[npm]` `npm pack --dry-run` includes: dist/, README.md, CHANGELOG.md, LICENSE
|
|
51
|
+
- [ ] `[npm]` `engines.node` set · `[pypi]` `python_requires` set
|
|
52
|
+
- [ ] `[npm]` Lockfile committed · `[pypi]` Clean wheel + sdist build
|
|
53
|
+
- [ ] `[vsix]` `vsce package` produces clean .vsix with correct metadata
|
|
54
|
+
- [ ] `[desktop]` Installer/package builds and runs on stated platforms
|
|
55
|
+
|
|
56
|
+
## E. Identity (soft gate — does not block ship)
|
|
57
|
+
|
|
58
|
+
- [ ] `[all]` Logo in README header
|
|
59
|
+
- [ ] `[all]` Translations (polyglot-mcp, 8 languages)
|
|
60
|
+
- [ ] `[org]` Landing page (@mcptoolshop/site-theme)
|
|
61
|
+
- [ ] `[all]` GitHub repo metadata: description, homepage, topics
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Gate Rules
|
|
66
|
+
|
|
67
|
+
**Hard gate (A–D):** Must pass before any version is tagged or published.
|
|
68
|
+
If a section doesn't apply, mark `SKIP:` with justification — don't leave it unchecked.
|
|
69
|
+
|
|
70
|
+
**Soft gate (E):** Should be done. Product ships without it, but isn't "whole."
|
|
71
|
+
|
|
72
|
+
**Checking off:**
|
|
73
|
+
```
|
|
74
|
+
- [x] `[all]` SECURITY.md exists (2026-02-27)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Skipping:**
|
|
78
|
+
```
|
|
79
|
+
- [ ] `[pypi]` SKIP: not a Python project
|
|
80
|
+
```
|