memento-mori-jester 0.1.73 → 0.1.75
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/ROADMAP.md +4 -2
- package/docs/DEMO.md +5 -5
- package/docs/MAINTAINER_TRIAGE.md +2 -1
- package/docs/PRODUCTION_READINESS.md +1 -1
- package/docs/RELEASE.md +1 -0
- package/docs/RELEASE_NOTES_v0.1.74.md +37 -0
- package/docs/RELEASE_NOTES_v0.1.75.md +42 -0
- package/examples/fixtures/README.md +3 -1
- package/examples/fixtures/preset-review-cases.json +84 -0
- package/package.json +1 -1
- package/scripts/check-production-readiness.mjs +4 -0
- package/scripts/report-fixtures.mjs +228 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to Memento Mori Jester are tracked here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.1.75
|
|
8
|
+
|
|
9
|
+
- Added `npm run fixtures:report -- --markdown` for paste-ready fixture coverage snapshots.
|
|
10
|
+
- Added Markdown tables for totals, counts, rule-family slices, preset slices, gaps, quiet-pass coverage, curation-next guidance, and next commands.
|
|
11
|
+
- Updated maintainer docs, release docs, and production-readiness checks for the Markdown fixture report export.
|
|
12
|
+
|
|
13
|
+
## 0.1.74
|
|
14
|
+
|
|
15
|
+
- Added six API quiet-pass fixtures, growing the corpus to 208 fixtures.
|
|
16
|
+
- Strengthened safe near-miss evidence for schema parsing, query-builder filters, enabled rate limiting, read-only Prisma migration diffs, signed-webhook docs, and OpenAPI schema docs.
|
|
17
|
+
- Refreshed demo, roadmap, fixture docs, and release notes for the API curation batch.
|
|
18
|
+
|
|
7
19
|
## 0.1.73
|
|
8
20
|
|
|
9
21
|
- Added six web and AI quiet-pass fixtures, growing the corpus to 202 fixtures.
|
package/README.md
CHANGED
|
@@ -501,7 +501,7 @@ Use the false-positive template for noisy cautions or blocks. Include `jester su
|
|
|
501
501
|
|
|
502
502
|
Maintainers can use [docs/MAINTAINER_TRIAGE.md](docs/MAINTAINER_TRIAGE.md) to turn useful false-positive reports into redacted fixtures.
|
|
503
503
|
Run `npm run fixtures:check` before merging fixture changes; it catches duplicate IDs, missing rule metadata, weak descriptions, unsafe-looking content, and duplicate content.
|
|
504
|
-
Run `npm run fixtures:report` to see fixture coverage by rule, rule family, preset slice, kind, verdict, quiet-pass boundaries, feasible pass-case gaps, and curation-next guidance before choosing the next fixture.
|
|
504
|
+
Run `npm run fixtures:report` to see fixture coverage by rule, rule family, preset slice, kind, verdict, quiet-pass boundaries, feasible pass-case gaps, and curation-next guidance before choosing the next fixture. Use `npm run fixtures:report -- --markdown` when you want a paste-ready summary for release notes or GitHub issues.
|
|
505
505
|
|
|
506
506
|
For vulnerabilities, private code exposure, or credential-handling concerns, follow [SECURITY.md](SECURITY.md) instead of opening a public issue with sensitive details.
|
|
507
507
|
|
package/ROADMAP.md
CHANGED
|
@@ -6,6 +6,8 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
|
|
|
6
6
|
|
|
7
7
|
## Recently Shipped
|
|
8
8
|
|
|
9
|
+
- Markdown fixture report export in v0.1.75 for paste-ready coverage snapshots in release notes, GitHub issues, and maintainer updates.
|
|
10
|
+
- API fixture curation in v0.1.74, adding six quiet-pass examples for schema parsing, query-builder filters, enabled rate limiting, read-only Prisma migration diffs, signed-webhook docs, and OpenAPI schema docs.
|
|
9
11
|
- Web/AI fixture curation in v0.1.73, adding six quiet-pass examples for safe text rendering, allowlisted target paths, public analytics IDs, model-check commands, tool allowlist checks, and public model-name config.
|
|
10
12
|
- Python/security fixture curation in v0.1.72, adding six quiet-pass examples for Bandit, pip-audit, coverage/pytest, Trivy, npm audit, and TLS verification-enabled diffs.
|
|
11
13
|
- Node preset fixture curation in v0.1.71, adding six quiet-pass examples for npm audit/outdated/ci, development-mode Node commands, package export maps, and workspace test scripts, plus a repo-local X demo video asset.
|
|
@@ -62,9 +64,9 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
|
|
|
62
64
|
|
|
63
65
|
## Product Ideas
|
|
64
66
|
|
|
65
|
-
- Collect real-world reports for the next lowest-count preset slices:
|
|
67
|
+
- Collect real-world reports for the next lowest-count preset slices: python, security, web, then AI.
|
|
66
68
|
- Add more framework-specific false-positive examples from real reports so tuning guidance keeps getting sharper.
|
|
67
|
-
- Add a
|
|
69
|
+
- Add a promo/share kit with X post copy, still images, and a simple sharing checklist.
|
|
68
70
|
|
|
69
71
|
## Quality And Safety
|
|
70
72
|
|
package/docs/DEMO.md
CHANGED
|
@@ -192,8 +192,8 @@ Project config: none loaded
|
|
|
192
192
|
Fixture tuning evidence:
|
|
193
193
|
Support: limited
|
|
194
194
|
Confidence: medium
|
|
195
|
-
Total fixtures checked:
|
|
196
|
-
Weighted fixtures checked:
|
|
195
|
+
Total fixtures checked: 208
|
|
196
|
+
Weighted fixtures checked: 399.2
|
|
197
197
|
Matching fixtures: 11
|
|
198
198
|
Weighted matches: 23
|
|
199
199
|
Expected-match weight: 18
|
|
@@ -202,7 +202,7 @@ Edge-case matches: 0
|
|
|
202
202
|
Quiet-pass fixtures: 5
|
|
203
203
|
Quiet-pass weight: 3.6
|
|
204
204
|
By kind: command 0, plan 5, diff 5, final 1
|
|
205
|
-
Fixture coverage: 11/
|
|
205
|
+
Fixture coverage: 11/208 (5.8% weighted)
|
|
206
206
|
By verdict: pass 0, caution 3, block 8
|
|
207
207
|
Matched fixture samples:
|
|
208
208
|
infra-public-ingress-block: Public ingress should block in low-risk-tolerance infra repos.
|
|
@@ -353,9 +353,9 @@ Preset packs:
|
|
|
353
353
|
|
|
354
354
|
## 13. Review Fixtures
|
|
355
355
|
|
|
356
|
-
The fixture suite in `examples/fixtures/preset-review-cases.json` captures small real-usage examples with expected `pass`, `caution`, or `block` verdicts. It also includes matched-pass examples for low-severity rules, quiet-pass `absentRuleIds` examples that prove noisy rules stay silent for safe near-misses, stack-specific coverage for every built-in preset, quiet-pass boundaries across built-in, structural, custom, and preset/config-derived rules, second firing examples for preset blocked-command rules, second examples for AI/API, framework custom, built-in, and configured sensitive-domain rules, AI tool-dispatch examples with safe allowlist/schema boundaries, and real-world low-count preset examples across node, python, web, infra, AI, and security slices. Recent quiet-pass examples cover typechecks, prebuild scripts, mypy, dataclass parsing, CodeQL, Dependabot limits, form validation, accessibility copy, read-only Kubernetes inspection, Docker disk usage, Terraform linting, public-IP hardening changes, npm audit/outdated/ci, development-mode Node commands, package export maps, workspace test scripts, Bandit, pip-audit, coverage/pytest, Trivy filesystem scans, npm audit, TLS verification-enabled diffs, safe text rendering, allowlisted target paths, public analytics IDs, model-check commands, tool allowlist checks,
|
|
356
|
+
The fixture suite in `examples/fixtures/preset-review-cases.json` captures small real-usage examples with expected `pass`, `caution`, or `block` verdicts. It also includes matched-pass examples for low-severity rules, quiet-pass `absentRuleIds` examples that prove noisy rules stay silent for safe near-misses, stack-specific coverage for every built-in preset, quiet-pass boundaries across built-in, structural, custom, and preset/config-derived rules, second firing examples for preset blocked-command rules, second examples for AI/API, framework custom, built-in, and configured sensitive-domain rules, AI tool-dispatch examples with safe allowlist/schema boundaries, and real-world low-count preset examples across node, python, web, infra, AI, and security slices. Recent quiet-pass examples cover typechecks, prebuild scripts, mypy, dataclass parsing, CodeQL, Dependabot limits, form validation, accessibility copy, read-only Kubernetes inspection, Docker disk usage, Terraform linting, public-IP hardening changes, npm audit/outdated/ci, development-mode Node commands, package export maps, workspace test scripts, Bandit, pip-audit, coverage/pytest, Trivy filesystem scans, npm audit, TLS verification-enabled diffs, safe text rendering, allowlisted target paths, public analytics IDs, model-check commands, tool allowlist checks, public model-name config, API schema parsing, query-builder filters, enabled rate limiting, read-only Prisma migration diffs, signed-webhook docs, and OpenAPI schema docs. These examples are run by `npm test`, so preset tuning changes stay visible.
|
|
357
357
|
|
|
358
|
-
Maintainers can run `npm run fixtures:report` to see coverage by verdict, kind, preset, rule family, and preset slice. The report also includes a `Curation next` section that points at the next useful fixture batch, such as thin rules, feasible pass-case evidence, rule-family gaps, or lower-count presets.
|
|
358
|
+
Maintainers can run `npm run fixtures:report` to see coverage by verdict, kind, preset, rule family, and preset slice. The report also includes a `Curation next` section that points at the next useful fixture batch, such as thin rules, feasible pass-case evidence, rule-family gaps, or lower-count presets. Use `npm run fixtures:report -- --markdown` for a paste-ready version of the same snapshot.
|
|
359
359
|
|
|
360
360
|
Maintainers can use `docs/MAINTAINER_TRIAGE.md` to turn useful false-positive reports into redacted fixture cases.
|
|
361
361
|
|
|
@@ -77,13 +77,14 @@ npm.cmd test
|
|
|
77
77
|
npm.cmd run fixtures:check
|
|
78
78
|
npm.cmd run fixtures:report
|
|
79
79
|
npm.cmd run fixtures:report -- --json
|
|
80
|
+
npm.cmd run fixtures:report -- --markdown
|
|
80
81
|
node .\dist\cli.js tune <rule-id>
|
|
81
82
|
node .\dist\cli.js tune <rule-id> --json
|
|
82
83
|
node .\dist\cli.js tune coverage
|
|
83
84
|
```
|
|
84
85
|
|
|
85
86
|
5. Fix any duplicate IDs, missing expected rule metadata, weak descriptions, unsafe content, or duplicate content reported by `fixtures:check`.
|
|
86
|
-
6. Use `fixtures:report` to check whether the change improves feasible pass-case, quiet-pass, preset, kind, rule-family, or verdict coverage. Start with the report's `Curation next` section when deciding which fixture batch to add first.
|
|
87
|
+
6. Use `fixtures:report` to check whether the change improves feasible pass-case, quiet-pass, preset, kind, rule-family, or verdict coverage. Start with the report's `Curation next` section when deciding which fixture batch to add first, and use `fixtures:report -- --markdown` when you need a paste-ready snapshot for an issue or release note.
|
|
87
88
|
7. Check whether support/confidence changed in the expected direction.
|
|
88
89
|
8. If the fixture changes verdict behavior, mention the exact rule impact in `CHANGELOG.md`.
|
|
89
90
|
|
|
@@ -53,7 +53,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
|
|
|
53
53
|
- `SECURITY.md` routes vulnerability reports away from public issues and asks for redacted diagnostics.
|
|
54
54
|
- `docs/MAINTAINER_TRIAGE.md` explains how to turn useful false-positive reports into fixture coverage before changing rule logic.
|
|
55
55
|
- `npm run fixtures:check` validates fixture IDs, metadata, unsafe-looking content, duplicate content, and explicit expected/absent rule intent.
|
|
56
|
-
- `npm run fixtures:report` shows fixture coverage by rule, rule family, preset slice, kind, verdict, quiet-pass rule boundaries, and feasible pass-case gaps so maintainers can pick the next fixture target.
|
|
56
|
+
- `npm run fixtures:report` shows fixture coverage by rule, rule family, preset slice, kind, verdict, quiet-pass rule boundaries, and feasible pass-case gaps so maintainers can pick the next fixture target; `npm run fixtures:report -- --markdown` produces a paste-ready maintainer snapshot.
|
|
57
57
|
- npm publish has a manual workflow fallback, but the normal release path is tag-driven trusted publishing.
|
|
58
58
|
|
|
59
59
|
## Static Guard
|
package/docs/RELEASE.md
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Memento Mori Jester v0.1.74
|
|
2
|
+
|
|
3
|
+
This release follows the fixture report's API curation guidance. It adds practical quiet-pass examples only; review behavior is unchanged.
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
- Added 6 fixture cases, growing the corpus from 202 to 208 fixtures.
|
|
8
|
+
- Added API quiet-pass examples for:
|
|
9
|
+
- schema parsing request bodies.
|
|
10
|
+
- query-builder filters with validated IDs.
|
|
11
|
+
- enabled rate limiting.
|
|
12
|
+
- read-only Prisma migration diffs.
|
|
13
|
+
- signed-webhook documentation.
|
|
14
|
+
- OpenAPI schema documentation.
|
|
15
|
+
- Raised the API preset slice from 16 to 22 fixtures.
|
|
16
|
+
- Kept thin rule coverage, quiet-pass gaps, feasible pass-case gaps, and preset/kind gaps at zero.
|
|
17
|
+
|
|
18
|
+
## Public Interface
|
|
19
|
+
|
|
20
|
+
- No CLI command changes.
|
|
21
|
+
- No config schema changes.
|
|
22
|
+
- No rule matching, scoring, or verdict behavior changes.
|
|
23
|
+
- No MCP, playground, GitHub Action, or npm publishing changes.
|
|
24
|
+
|
|
25
|
+
## Release Validation
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
npm.cmd test
|
|
29
|
+
npm.cmd run demo:svg:check
|
|
30
|
+
npm.cmd run fixtures:report
|
|
31
|
+
npm.cmd run fixtures:report -- --json
|
|
32
|
+
npm.cmd run pack:dry
|
|
33
|
+
git diff --check
|
|
34
|
+
node .\dist\cli.js tune coverage --no-config
|
|
35
|
+
node .\dist\cli.js tune risky-domain --json --no-config
|
|
36
|
+
git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.74 API quiet-pass curation"
|
|
37
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Memento Mori Jester v0.1.75
|
|
2
|
+
|
|
3
|
+
This release adds a Markdown export for the fixture coverage report so maintainers can paste stable quality snapshots into release notes, GitHub issues, and project updates. Review behavior is unchanged.
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
- Added `npm run fixtures:report -- --markdown`.
|
|
8
|
+
- Added Markdown sections for:
|
|
9
|
+
- summary totals.
|
|
10
|
+
- verdict, kind, and preset counts.
|
|
11
|
+
- rule-family slices.
|
|
12
|
+
- preset slices.
|
|
13
|
+
- gap sections.
|
|
14
|
+
- quiet-pass rule coverage.
|
|
15
|
+
- quiet-pass fixture samples.
|
|
16
|
+
- curation-next guidance.
|
|
17
|
+
- next commands.
|
|
18
|
+
- Added a guard that rejects combining `--json` and `--markdown`.
|
|
19
|
+
- Updated maintainer docs, release docs, demo docs, README support notes, and production-readiness checks.
|
|
20
|
+
|
|
21
|
+
## Public Interface
|
|
22
|
+
|
|
23
|
+
- New maintainer script mode: `npm run fixtures:report -- --markdown`.
|
|
24
|
+
- No CLI command changes.
|
|
25
|
+
- No config schema changes.
|
|
26
|
+
- No rule matching, scoring, or verdict behavior changes.
|
|
27
|
+
- No MCP, playground, GitHub Action, or npm publishing changes.
|
|
28
|
+
|
|
29
|
+
## Release Validation
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
npm.cmd test
|
|
33
|
+
npm.cmd run demo:svg:check
|
|
34
|
+
npm.cmd run fixtures:report
|
|
35
|
+
npm.cmd run fixtures:report -- --json
|
|
36
|
+
npm.cmd run fixtures:report -- --markdown
|
|
37
|
+
npm.cmd run pack:dry
|
|
38
|
+
git diff --check
|
|
39
|
+
node .\dist\cli.js tune coverage --no-config
|
|
40
|
+
node .\dist\cli.js tune risky-domain --json --no-config
|
|
41
|
+
git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.75 markdown fixture report export"
|
|
42
|
+
```
|
|
@@ -28,6 +28,7 @@ Maintainer triage guidance lives in [docs/MAINTAINER_TRIAGE.md](../../docs/MAINT
|
|
|
28
28
|
- Quiet-pass examples for npm audit/outdated/ci, development-mode Node commands, package export maps, and workspace test scripts.
|
|
29
29
|
- Quiet-pass examples for Bandit, pip-audit, coverage/pytest, Trivy filesystem scans, npm audit, and TLS verification-enabled diffs.
|
|
30
30
|
- Quiet-pass examples for safe text rendering, allowlisted target paths, public analytics IDs, model-check commands, tool allowlist checks, and public model-name config.
|
|
31
|
+
- Quiet-pass examples for API schema parsing, query-builder filters, enabled rate limiting, read-only Prisma migration diffs, signed-webhook docs, and OpenAPI schema docs.
|
|
31
32
|
- Fixture metadata like `weight` and `edgeCase` to support precision-weighted tuning evidence.
|
|
32
33
|
|
|
33
34
|
## Local Check
|
|
@@ -37,6 +38,7 @@ npm.cmd test
|
|
|
37
38
|
npm.cmd run fixtures:check
|
|
38
39
|
npm.cmd run fixtures:report
|
|
39
40
|
npm.cmd run fixtures:report -- --json
|
|
41
|
+
npm.cmd run fixtures:report -- --markdown
|
|
40
42
|
```
|
|
41
43
|
|
|
42
44
|
For one-off manual review, paste a fixture `content` value into:
|
|
@@ -62,4 +64,4 @@ Do not add secrets, private code, customer data, complete logs, or machine-speci
|
|
|
62
64
|
|
|
63
65
|
`npm run fixtures:report` summarizes coverage by rule, rule family, preset slice, review kind, verdict, and quiet-pass rule boundaries. Use it to find rules without pass-case coverage, pass-eligible rules without pass-case coverage, rules without quiet-pass coverage, thin rule coverage, preset/kind gaps, quiet pass fixtures, and the next curation target.
|
|
64
66
|
|
|
65
|
-
The `Curation next` section is a maintainer shortcut: start there when deciding whether the next fixture batch should focus on thin rules, feasible pass-case evidence, a specific rule family, or lower-count presets. The `--json` output includes the same `ruleFamilySlices`, `presetSlices`, `passEligibleRulesWithoutPassCases`, and `curationNext` fields for scripts.
|
|
67
|
+
The `Curation next` section is a maintainer shortcut: start there when deciding whether the next fixture batch should focus on thin rules, feasible pass-case evidence, a specific rule family, or lower-count presets. The `--json` output includes the same `ruleFamilySlices`, `presetSlices`, `passEligibleRulesWithoutPassCases`, and `curationNext` fields for scripts. The `--markdown` output renders the same snapshot as paste-ready Markdown tables for release notes, GitHub issues, or maintainer updates.
|
|
@@ -2653,5 +2653,89 @@
|
|
|
2653
2653
|
"custom-ai-public-provider-key",
|
|
2654
2654
|
"secret-material"
|
|
2655
2655
|
]
|
|
2656
|
+
},
|
|
2657
|
+
{
|
|
2658
|
+
"id": "api-schema-parse-diff-pass",
|
|
2659
|
+
"preset": "api",
|
|
2660
|
+
"kind": "diff",
|
|
2661
|
+
"description": "Schema parsing request bodies should stay quiet around raw SQL and auth-bypass checks.",
|
|
2662
|
+
"content": "diff --git a/src/routes/users.ts b/src/routes/users.ts\n--- a/src/routes/users.ts\n+++ b/src/routes/users.ts\n@@ -1 +1,2 @@\n+const input = CreateUserSchema.parse(req.body);\n",
|
|
2663
|
+
"expectedVerdict": "pass",
|
|
2664
|
+
"weight": 2,
|
|
2665
|
+
"expectedRuleIds": [],
|
|
2666
|
+
"absentRuleIds": [
|
|
2667
|
+
"custom-api-auth-bypass",
|
|
2668
|
+
"custom-api-raw-sql-user-input"
|
|
2669
|
+
]
|
|
2670
|
+
},
|
|
2671
|
+
{
|
|
2672
|
+
"id": "api-query-builder-diff-pass",
|
|
2673
|
+
"preset": "api",
|
|
2674
|
+
"kind": "diff",
|
|
2675
|
+
"description": "Query-builder filters with validated identifiers should not trip raw request SQL checks.",
|
|
2676
|
+
"content": "diff --git a/src/routes/users.ts b/src/routes/users.ts\n--- a/src/routes/users.ts\n+++ b/src/routes/users.ts\n@@ -1 +1,2 @@\n+const user = await db.user.findUnique({ where: { id: validatedUserId } });\n",
|
|
2677
|
+
"expectedVerdict": "pass",
|
|
2678
|
+
"weight": 2,
|
|
2679
|
+
"expectedRuleIds": [],
|
|
2680
|
+
"absentRuleIds": [
|
|
2681
|
+
"custom-api-raw-sql-user-input"
|
|
2682
|
+
]
|
|
2683
|
+
},
|
|
2684
|
+
{
|
|
2685
|
+
"id": "api-rate-limit-enabled-diff-pass",
|
|
2686
|
+
"preset": "api",
|
|
2687
|
+
"kind": "diff",
|
|
2688
|
+
"description": "Enabled API throttles should not look like rate-limit disabling.",
|
|
2689
|
+
"content": "diff --git a/src/middleware/limits.ts b/src/middleware/limits.ts\n--- a/src/middleware/limits.ts\n+++ b/src/middleware/limits.ts\n@@ -1 +1,2 @@\n+export const apiLimiter = rateLimit({ windowMs: 60000, max: 100 });\n",
|
|
2690
|
+
"expectedVerdict": "pass",
|
|
2691
|
+
"weight": 2,
|
|
2692
|
+
"expectedRuleIds": [],
|
|
2693
|
+
"absentRuleIds": [
|
|
2694
|
+
"custom-api-rate-limit-disabled",
|
|
2695
|
+
"configured-sensitive-domain-rate-limit"
|
|
2696
|
+
]
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
"id": "api-prisma-migrate-diff-command-pass",
|
|
2700
|
+
"preset": "api",
|
|
2701
|
+
"kind": "command",
|
|
2702
|
+
"description": "Read-only Prisma migration diff commands should not be mistaken for destructive resets.",
|
|
2703
|
+
"content": "prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script",
|
|
2704
|
+
"expectedVerdict": "pass",
|
|
2705
|
+
"weight": 2,
|
|
2706
|
+
"expectedRuleIds": [],
|
|
2707
|
+
"absentRuleIds": [
|
|
2708
|
+
"blocked-command-prisma-migrate-reset-force",
|
|
2709
|
+
"custom-api-destructive-migration"
|
|
2710
|
+
]
|
|
2711
|
+
},
|
|
2712
|
+
{
|
|
2713
|
+
"id": "api-webhook-signature-docs-pass",
|
|
2714
|
+
"preset": "api",
|
|
2715
|
+
"kind": "diff",
|
|
2716
|
+
"description": "Docs about requiring signed webhooks should stay quiet around disabled-webhook checks.",
|
|
2717
|
+
"content": "diff --git a/docs/WEBHOOKS.md b/docs/WEBHOOKS.md\n--- a/docs/WEBHOOKS.md\n+++ b/docs/WEBHOOKS.md\n@@ -1 +1,2 @@\n+Require provider webhook signature verification before accepting event payloads.\n",
|
|
2718
|
+
"expectedVerdict": "pass",
|
|
2719
|
+
"edgeCase": true,
|
|
2720
|
+
"weight": 1,
|
|
2721
|
+
"expectedRuleIds": [],
|
|
2722
|
+
"absentRuleIds": [
|
|
2723
|
+
"custom-api-webhook-signature-disabled",
|
|
2724
|
+
"configured-sensitive-domain-webhook"
|
|
2725
|
+
]
|
|
2726
|
+
},
|
|
2727
|
+
{
|
|
2728
|
+
"id": "api-openapi-schema-docs-pass",
|
|
2729
|
+
"preset": "api",
|
|
2730
|
+
"kind": "diff",
|
|
2731
|
+
"description": "Docs about OpenAPI schema validation should not trip broad API sensitive-domain noise.",
|
|
2732
|
+
"content": "diff --git a/docs/API_SCHEMA.md b/docs/API_SCHEMA.md\n--- a/docs/API_SCHEMA.md\n+++ b/docs/API_SCHEMA.md\n@@ -1 +1,2 @@\n+Document OpenAPI request schemas and validation examples for client integrations.\n",
|
|
2733
|
+
"expectedVerdict": "pass",
|
|
2734
|
+
"edgeCase": true,
|
|
2735
|
+
"weight": 1,
|
|
2736
|
+
"expectedRuleIds": [],
|
|
2737
|
+
"absentRuleIds": [
|
|
2738
|
+
"configured-sensitive-domain-openapi"
|
|
2739
|
+
]
|
|
2656
2740
|
}
|
|
2657
2741
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memento-mori-jester",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.75",
|
|
4
4
|
"description": "A local court-jester sidecar for AI coding agents: review plans, commands, diffs, and final claims before they get too pleased with themselves.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -94,6 +94,7 @@ requireText("README.md", /false-positive/i, "false-positive support guidance");
|
|
|
94
94
|
requireText("README.md", /MAINTAINER_TRIAGE\.md/, "maintainer triage guide link");
|
|
95
95
|
requireText("README.md", /fixtures:check/, "fixture authoring check guidance");
|
|
96
96
|
requireText("README.md", /fixtures:report/, "fixture coverage report guidance");
|
|
97
|
+
requireText("README.md", /fixtures:report -- --markdown/, "Markdown fixture report guidance");
|
|
97
98
|
requireText("README.md", /License: PolyForm Noncommercial/, "the noncommercial license badge");
|
|
98
99
|
requireText("docs/PRODUCTION_READINESS.md", /npm package/i, "npm package readiness");
|
|
99
100
|
requireText("docs/PRODUCTION_READINESS.md", /GitHub Action/i, "GitHub Action readiness");
|
|
@@ -106,6 +107,7 @@ requireText("docs/PRODUCTION_READINESS.md", /issue templates/i, "issue template
|
|
|
106
107
|
requireText("docs/PRODUCTION_READINESS.md", /MAINTAINER_TRIAGE\.md/, "maintainer triage readiness");
|
|
107
108
|
requireText("docs/PRODUCTION_READINESS.md", /fixtures:check/, "fixture authoring check readiness");
|
|
108
109
|
requireText("docs/PRODUCTION_READINESS.md", /fixtures:report/, "fixture coverage report readiness");
|
|
110
|
+
requireText("docs/PRODUCTION_READINESS.md", /fixtures:report -- --markdown/, "Markdown fixture report readiness");
|
|
109
111
|
requireText("docs/PRODUCTION_READINESS.md", /quiet-pass/, "quiet-pass fixture readiness");
|
|
110
112
|
requireText("docs/CLI.md", /jester doctor --json/, "doctor JSON CLI docs");
|
|
111
113
|
requireText("docs/CLI.md", /quiet-pass fixture/, "quiet-pass fixture CLI docs");
|
|
@@ -118,6 +120,7 @@ requireText("examples/fixtures/README.md", /MAINTAINER_TRIAGE\.md/, "maintainer
|
|
|
118
120
|
requireText("examples/fixtures/README.md", /Adding A Fixture From A Report/, "fixture report conversion guidance");
|
|
119
121
|
requireText("examples/fixtures/README.md", /fixtures:check/, "fixture authoring check guidance");
|
|
120
122
|
requireText("examples/fixtures/README.md", /fixtures:report/, "fixture coverage report guidance");
|
|
123
|
+
requireText("examples/fixtures/README.md", /fixtures:report -- --markdown/, "Markdown fixture report guidance");
|
|
121
124
|
requireText("scripts/check-fixtures.mjs", /duplicated/, "duplicate fixture id check");
|
|
122
125
|
requireText("scripts/check-fixtures.mjs", /unsafeContentPatterns/, "unsafe fixture content checks");
|
|
123
126
|
forbidText("scripts/check-fixtures.mjs", /src\/config\.ts|src\/types\.ts/, "source-only fixture validator dependencies");
|
|
@@ -125,6 +128,7 @@ requireText("scripts/report-fixtures.mjs", /rulesWithoutPassCases/, "rules witho
|
|
|
125
128
|
requireText("scripts/report-fixtures.mjs", /rulesWithoutQuietPassCoverage/, "rules without quiet-pass coverage report");
|
|
126
129
|
requireText("scripts/report-fixtures.mjs", /quietPassRuleCoverage/, "quiet-pass rule coverage report");
|
|
127
130
|
requireText("scripts/report-fixtures.mjs", /presetKindGaps/, "preset and kind gap report");
|
|
131
|
+
requireText("scripts/report-fixtures.mjs", /--markdown/, "Markdown fixture report output");
|
|
128
132
|
forbidText("scripts/report-fixtures.mjs", /src\/config\.ts|src\/types\.ts/, "source-only fixture report dependencies");
|
|
129
133
|
requireText("package.json", /"fixtures:check": "node scripts\/check-fixtures\.mjs"/, "fixture authoring check script");
|
|
130
134
|
requireText("package.json", /"fixtures:report": "node scripts\/report-fixtures\.mjs"/, "fixture coverage report script");
|
|
@@ -33,6 +33,12 @@ const ruleFamilyOrder = [
|
|
|
33
33
|
|
|
34
34
|
const args = new Set(process.argv.slice(2));
|
|
35
35
|
const json = args.has("--json");
|
|
36
|
+
const markdown = args.has("--markdown");
|
|
37
|
+
|
|
38
|
+
if (json && markdown) {
|
|
39
|
+
process.stderr.write("Use only one output format: --json or --markdown.\n");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
36
42
|
|
|
37
43
|
function read(path) {
|
|
38
44
|
return readFileSync(join(root, path), "utf8");
|
|
@@ -55,6 +61,8 @@ const report = buildFixtureReport(fixtures);
|
|
|
55
61
|
|
|
56
62
|
if (json) {
|
|
57
63
|
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
64
|
+
} else if (markdown) {
|
|
65
|
+
process.stdout.write(renderFixtureReportMarkdown(report));
|
|
58
66
|
} else {
|
|
59
67
|
process.stdout.write(renderFixtureReport(report));
|
|
60
68
|
}
|
|
@@ -271,6 +279,91 @@ function renderFixtureReport(report) {
|
|
|
271
279
|
return `${lines.join("\n")}\n`;
|
|
272
280
|
}
|
|
273
281
|
|
|
282
|
+
function renderFixtureReportMarkdown(report) {
|
|
283
|
+
const lines = [
|
|
284
|
+
"# Fixture Coverage Report",
|
|
285
|
+
"",
|
|
286
|
+
"Generated from `examples/fixtures/preset-review-cases.json`.",
|
|
287
|
+
"",
|
|
288
|
+
"## Summary",
|
|
289
|
+
"",
|
|
290
|
+
"| Metric | Value |",
|
|
291
|
+
"| --- | ---: |",
|
|
292
|
+
`| Fixtures | ${report.totalFixtures} |`,
|
|
293
|
+
`| Weighted fixtures | ${report.totalWeight} |`,
|
|
294
|
+
`| Edge-case fixtures | ${report.edgeCaseFixtures} |`,
|
|
295
|
+
`| Rules covered by expectedRuleIds | ${report.rules.length} |`,
|
|
296
|
+
"",
|
|
297
|
+
"## Counts",
|
|
298
|
+
"",
|
|
299
|
+
"### By Verdict",
|
|
300
|
+
"",
|
|
301
|
+
...formatMarkdownCountTable("Verdict", report.byVerdict),
|
|
302
|
+
"",
|
|
303
|
+
"### By Kind",
|
|
304
|
+
"",
|
|
305
|
+
...formatMarkdownCountTable("Kind", report.byKind),
|
|
306
|
+
"",
|
|
307
|
+
"### By Preset",
|
|
308
|
+
"",
|
|
309
|
+
...formatMarkdownCountTable("Preset", report.byPreset),
|
|
310
|
+
"",
|
|
311
|
+
"## Rule Family Slices",
|
|
312
|
+
"",
|
|
313
|
+
...formatMarkdownRuleFamilyTable(report.ruleFamilySlices),
|
|
314
|
+
"",
|
|
315
|
+
"## Preset Slices",
|
|
316
|
+
"",
|
|
317
|
+
...formatMarkdownPresetTable(report.presetSlices),
|
|
318
|
+
"",
|
|
319
|
+
"## Gaps",
|
|
320
|
+
"",
|
|
321
|
+
"### Rules Without Pass-Case Coverage",
|
|
322
|
+
"",
|
|
323
|
+
...formatMarkdownRuleGapList(report.gaps.rulesWithoutPassCases),
|
|
324
|
+
"",
|
|
325
|
+
"### Pass-Eligible Rules Without Pass-Case Coverage",
|
|
326
|
+
"",
|
|
327
|
+
...formatMarkdownRuleGapList(report.gaps.passEligibleRulesWithoutPassCases),
|
|
328
|
+
"",
|
|
329
|
+
"### Rules Without Quiet-Pass Coverage",
|
|
330
|
+
"",
|
|
331
|
+
...formatMarkdownRuleGapList(report.gaps.rulesWithoutQuietPassCoverage),
|
|
332
|
+
"",
|
|
333
|
+
"### Thin Rule Coverage",
|
|
334
|
+
"",
|
|
335
|
+
...formatMarkdownRuleGapList(report.gaps.thinRuleCoverage),
|
|
336
|
+
"",
|
|
337
|
+
"### Preset/Kind Gaps",
|
|
338
|
+
"",
|
|
339
|
+
...formatMarkdownPresetKindGaps(report.gaps.presetKindGaps),
|
|
340
|
+
"",
|
|
341
|
+
"## Quiet-Pass Rule Coverage",
|
|
342
|
+
"",
|
|
343
|
+
...formatMarkdownQuietPassTable(report.gaps.quietPassRuleCoverage),
|
|
344
|
+
"",
|
|
345
|
+
"## Quiet-Pass Fixture Samples",
|
|
346
|
+
"",
|
|
347
|
+
...formatMarkdownFixtureSamples(report.gaps.quietPassFixtures),
|
|
348
|
+
"",
|
|
349
|
+
"## Curation Next",
|
|
350
|
+
"",
|
|
351
|
+
...formatMarkdownCurationNext(report.curationNext),
|
|
352
|
+
"",
|
|
353
|
+
"## Next Commands",
|
|
354
|
+
"",
|
|
355
|
+
"```powershell",
|
|
356
|
+
"npm run fixtures:check",
|
|
357
|
+
"npm run fixtures:report",
|
|
358
|
+
"npm run fixtures:report -- --json",
|
|
359
|
+
"npm run fixtures:report -- --markdown",
|
|
360
|
+
"node .\\dist\\cli.js tune coverage",
|
|
361
|
+
"```"
|
|
362
|
+
];
|
|
363
|
+
|
|
364
|
+
return `${lines.join("\n")}\n`;
|
|
365
|
+
}
|
|
366
|
+
|
|
274
367
|
function createRuleEntry(ruleId) {
|
|
275
368
|
return {
|
|
276
369
|
ruleId,
|
|
@@ -575,6 +668,141 @@ function formatCounts(counts) {
|
|
|
575
668
|
.join(", ");
|
|
576
669
|
}
|
|
577
670
|
|
|
671
|
+
function formatMarkdownCountTable(label, counts) {
|
|
672
|
+
return [
|
|
673
|
+
`| ${label} | Count |`,
|
|
674
|
+
"| --- | ---: |",
|
|
675
|
+
...Object.entries(counts).map(([key, value]) => `| ${markdownCell(key)} | ${value} |`)
|
|
676
|
+
];
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function formatMarkdownRuleFamilyTable(entries) {
|
|
680
|
+
if (entries.length === 0) {
|
|
681
|
+
return ["None."];
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
return [
|
|
685
|
+
"| Family | Rules | Fixture Refs | Pass | Caution | Block | Quiet Pass | Thin |",
|
|
686
|
+
"| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |",
|
|
687
|
+
...entries.map((entry) =>
|
|
688
|
+
[
|
|
689
|
+
markdownCell(entry.family),
|
|
690
|
+
entry.ruleCount,
|
|
691
|
+
entry.fixtureReferences,
|
|
692
|
+
entry.passCases,
|
|
693
|
+
entry.cautionCases,
|
|
694
|
+
entry.blockCases,
|
|
695
|
+
entry.quietPassCases,
|
|
696
|
+
entry.thinRules.length
|
|
697
|
+
].join(" | ")
|
|
698
|
+
).map((row) => `| ${row} |`)
|
|
699
|
+
];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
function formatMarkdownPresetTable(entries) {
|
|
703
|
+
if (entries.length === 0) {
|
|
704
|
+
return ["None."];
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return [
|
|
708
|
+
"| Preset | Fixtures | Weight | Pass | Caution | Block | Quiet Pass | Rule Refs | Absent Refs |",
|
|
709
|
+
"| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |",
|
|
710
|
+
...entries.map((entry) =>
|
|
711
|
+
[
|
|
712
|
+
markdownCell(entry.preset),
|
|
713
|
+
entry.total,
|
|
714
|
+
entry.weight,
|
|
715
|
+
entry.byVerdict.pass ?? 0,
|
|
716
|
+
entry.byVerdict.caution ?? 0,
|
|
717
|
+
entry.byVerdict.block ?? 0,
|
|
718
|
+
entry.quietPassFixtures,
|
|
719
|
+
entry.expectedRuleReferences,
|
|
720
|
+
entry.quietPassRuleReferences
|
|
721
|
+
].join(" | ")
|
|
722
|
+
).map((row) => `| ${row} |`)
|
|
723
|
+
];
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function formatMarkdownRuleGapList(entries) {
|
|
727
|
+
if (entries.length === 0) {
|
|
728
|
+
return ["None."];
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return entries
|
|
732
|
+
.slice(0, 12)
|
|
733
|
+
.map((entry) => `- \`${entry.ruleId}\`: ${entry.total} fixture(s), pass ${entry.passCases}, caution ${entry.cautionCases}, block ${entry.blockCases}, quiet-pass ${entry.quietPassCases}`);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function formatMarkdownPresetKindGaps(entries) {
|
|
737
|
+
if (entries.length === 0) {
|
|
738
|
+
return ["None."];
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return entries.map((entry) => `- \`${entry.preset}\`: ${entry.missingKinds.map((kind) => `\`${kind}\``).join(", ")}`);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function formatMarkdownQuietPassTable(entries) {
|
|
745
|
+
if (entries.length === 0) {
|
|
746
|
+
return ["None."];
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return [
|
|
750
|
+
"| Rule | Quiet-Pass Fixtures | Weight |",
|
|
751
|
+
"| --- | ---: | ---: |",
|
|
752
|
+
...entries
|
|
753
|
+
.slice(0, 12)
|
|
754
|
+
.map((entry) => `| \`${markdownCell(entry.ruleId)}\` | ${entry.total} | ${entry.weight} |`)
|
|
755
|
+
];
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function formatMarkdownFixtureSamples(entries) {
|
|
759
|
+
if (entries.length === 0) {
|
|
760
|
+
return ["None."];
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
return entries
|
|
764
|
+
.slice(0, 8)
|
|
765
|
+
.map((entry) => `- \`${entry.id}\`: ${markdownCell(entry.description)}`);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function formatMarkdownCurationNext(entries) {
|
|
769
|
+
if (entries.length === 0) {
|
|
770
|
+
return ["None."];
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return [
|
|
774
|
+
"| Priority | Area | Count | Details |",
|
|
775
|
+
"| --- | --- | ---: | --- |",
|
|
776
|
+
...entries.map((entry) =>
|
|
777
|
+
`| ${markdownCell(entry.priority)} | ${markdownCell(entry.area)} | ${entry.count} | ${markdownCell(markdownCurationDetails(entry))} |`
|
|
778
|
+
)
|
|
779
|
+
];
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function markdownCurationDetails(entry) {
|
|
783
|
+
if (Array.isArray(entry.ruleIds) && entry.ruleIds.length > 0) {
|
|
784
|
+
return entry.ruleIds.join(", ");
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (Array.isArray(entry.details) && entry.details.length > 0) {
|
|
788
|
+
return entry.details.join("; ");
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (Array.isArray(entry.families) && entry.families.length > 0) {
|
|
792
|
+
return entry.families.map((family) => `${family.family} ${family.thinRules}`).join(", ");
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
if (Array.isArray(entry.presets) && entry.presets.length > 0) {
|
|
796
|
+
return entry.presets.map((preset) => `${preset.preset} ${preset.total}`).join(", ");
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
return "";
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function markdownCell(value) {
|
|
803
|
+
return String(value).replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
804
|
+
}
|
|
805
|
+
|
|
578
806
|
function formatRuleGaps(entries) {
|
|
579
807
|
if (entries.length === 0) {
|
|
580
808
|
return ["- none"];
|