memento-mori-jester 0.1.87 → 0.1.89

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 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.89
8
+
9
+ - Added a report-gallery feedback issue template for public-safe reports about confusing or stale checked examples, and strengthened false-positive reports with version and redacted `doctor --json` prompts.
10
+ - Added `examples/reports/feedback-template.md` and `npm run support:check` so adopter feedback requests stay redacted, useful, and aligned with the gallery.
11
+ - Updated README, report docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and release notes for the support path.
12
+
13
+ ## 0.1.88
14
+
15
+ - Added `examples/reports`, a small checked report gallery for fresh `doctor`, destructive-command `summary`, and full blocked-command review output.
16
+ - Added `npm run reports:check`, which installs the package into a temporary consumer project and verifies every gallery command against stable output fragments.
17
+ - Updated README, getting-started docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and release notes for the report gallery.
18
+
7
19
  ## 0.1.87
8
20
 
9
21
  - Fixed `npm run consumer:quickstart:check -- --package memento-mori-jester@latest` so registry package specs install through `npm install --save-dev <spec>` in the temporary consumer project.
package/README.md CHANGED
@@ -72,6 +72,10 @@ For a first read-only CI smoke, copy [examples/ci/adoption-smoke.yml](examples/c
72
72
 
73
73
  Maintainers can prove that fresh-project path with [examples/consumer-quickstart](examples/consumer-quickstart) and `npm run consumer:quickstart:check`, which installs the package into a temporary project and runs the same quickstart commands from there.
74
74
 
75
+ For trust-building output examples, see [examples/reports](examples/reports). `npm run reports:check` installs the package into a temporary project and proves the gallery's `doctor`, `summary`, and blocked-command reports stay current.
76
+
77
+ If one of those reports is confusing or stale, use the public-safe [report gallery feedback template](examples/reports/feedback-template.md). It asks for version, nearest gallery example, sanitized command/output summaries, and redacted diagnostics without private repo code or secrets.
78
+
75
79
  Expected vibe:
76
80
 
77
81
  ```text
@@ -442,6 +446,8 @@ More setup examples:
442
446
  - [Framework CI Examples](examples/ci)
443
447
  - [Adoption Smoke CI](examples/ci/adoption-smoke.yml)
444
448
  - [Consumer Quickstart Smoke](examples/consumer-quickstart)
449
+ - [Real-World Report Gallery](examples/reports)
450
+ - [Report Gallery Feedback Template](examples/reports/feedback-template.md)
445
451
  - [Security Policy](SECURITY.md)
446
452
  - [Maintainer Triage](docs/MAINTAINER_TRIAGE.md)
447
453
  - [Changelog](CHANGELOG.md)
@@ -461,6 +467,8 @@ Framework CI examples:
461
467
 
462
468
  - [Adoption Smoke CI](examples/ci/adoption-smoke.yml)
463
469
  - [Consumer Quickstart Smoke](examples/consumer-quickstart)
470
+ - [Real-World Report Gallery](examples/reports)
471
+ - [Report Gallery Feedback Template](examples/reports/feedback-template.md)
464
472
  - [Next.js CI](examples/ci/nextjs.yml)
465
473
  - [Vite React CI](examples/ci/vite-react.yml)
466
474
  - [Express API CI](examples/ci/express-api.yml)
@@ -516,6 +524,8 @@ Use the false-positive template for noisy cautions or blocks. Include `jester su
516
524
  Maintainers can use [docs/MAINTAINER_TRIAGE.md](docs/MAINTAINER_TRIAGE.md) to turn useful false-positive reports into redacted fixtures.
517
525
  Run `npm run fixtures:check` before merging fixture changes; it catches duplicate IDs, missing rule metadata, weak descriptions, unsafe-looking content, and duplicate content.
518
526
  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.
527
+ Run `npm run reports:check` after editing [examples/reports](examples/reports); it verifies the public report gallery against an installed package in a temporary consumer project.
528
+ Run `npm run support:check` after editing issue templates, support docs, or the report gallery feedback path; it verifies the public report template asks for useful redacted context without inviting secrets or private code.
519
529
  Run `npm run promo:card` to regenerate the repo-local social preview card after changing its copy or design.
520
530
  Run `npm run promo:check` after editing promo assets; it checks the current demo video, stills, docs, and fixture evidence numbers stay in sync.
521
531
  Run `npm run site:check` after editing the repo-local landing page; it verifies the start command, demo links, social card, repo, release, and npm links.
@@ -529,6 +539,7 @@ Release checklist:
529
539
  ```powershell
530
540
  npm.cmd test
531
541
  npm.cmd run consumer:quickstart:check
542
+ npm.cmd run reports:check
532
543
  npm.cmd run promo:check
533
544
  npm.cmd run production:check
534
545
  npm.cmd run pack:dry
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
+ - Checked adopter feedback path in v0.1.89, adding a report-gallery issue template, package-shipped feedback template, and support triage guard.
10
+ - Checked report gallery in v0.1.88, proving fresh `doctor`, destructive-command `summary`, and blocked-command reports from an installed consumer project.
9
11
  - Consumer quickstart registry-mode fix in v0.1.87, proving the same smoke against `memento-mori-jester@latest` after publish.
10
12
  - Consumer quickstart smoke in v0.1.86, proving the first installed-project commands from a minimal repo before release.
11
13
  - Adoption smoke CI example in v0.1.85, giving real repos a read-only workflow for `doctor`, `summary`, and packaged framework tuning checks.
@@ -77,7 +79,7 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
77
79
  ## Product Ideas
78
80
 
79
81
  - Collect real-world reports and fold the strongest redacted cases into more framework tuning cookbook recipes.
80
- - Add a small fixture issue template checklist that asks for the nearest framework tuning cookbook recipe and redacted `jester tune <rule-id> --json` output.
82
+ - Turn repeated report-gallery feedback into clearer gallery examples or redacted fixtures.
81
83
  - Add a hosted-page option or GitHub Pages instructions once the static page has settled.
82
84
 
83
85
  ## Quality And Safety
@@ -106,7 +106,7 @@ npx -y memento-mori-jester@latest bootstrap --preset node
106
106
 
107
107
  Then tell them to open `MEMENTO_MORI.md`.
108
108
 
109
- For copy-paste agent and hook examples, see [examples](../examples). For stack-specific config examples, see [preset example packs](../examples/presets) for Next.js, Vite React, Express API, FastAPI, Terraform/Kubernetes, and AI MCP repos. For copy-paste CI workflows, see [framework CI examples](../examples/ci). For concrete pass, caution, and block cases, see [review fixtures](../examples/fixtures). For stack-shaped noisy-rule reports, see [framework tuning examples](FRAMEWORK_TUNING.md) and the checked [framework tuning cookbook](../examples/tuning).
109
+ For copy-paste agent and hook examples, see [examples](../examples). For stack-specific config examples, see [preset example packs](../examples/presets) for Next.js, Vite React, Express API, FastAPI, Terraform/Kubernetes, and AI MCP repos. For copy-paste CI workflows, see [framework CI examples](../examples/ci). For concrete pass, caution, and block cases, see [review fixtures](../examples/fixtures). For first trustworthy output examples, see the checked [report gallery](../examples/reports). For stack-shaped noisy-rule reports, see [framework tuning examples](FRAMEWORK_TUNING.md) and the checked [framework tuning cookbook](../examples/tuning).
110
110
 
111
111
  ## Need Help?
112
112
 
@@ -17,6 +17,10 @@ npx -y memento-mori-jester@latest summary --kind <command|plan|diff|final> "<min
17
17
  npx -y memento-mori-jester@latest tune <rule-id> --json
18
18
  ```
19
19
 
20
+ For users who just need to understand what a healthy report looks like, point them at the checked [report gallery](../examples/reports). Maintainers can run `npm run reports:check` to prove those examples still match the current package output.
21
+
22
+ For users who say a gallery report is confusing, stale, or hard to compare with their local output, point them at [examples/reports/feedback-template.md](../examples/reports/feedback-template.md) or the GitHub [report gallery feedback issue template](../.github/ISSUE_TEMPLATE/report_gallery_feedback.yml). It asks for the nearest checked example, sanitized command and output summaries, version, and redacted diagnostics without asking for private code.
23
+
20
24
  Do not ask users to paste secrets, private code, customer data, live credentials, complete CI logs, or unredacted SARIF. If the report involves credential exposure, command execution, unexpected network access, private code disclosure, package publishing, or MCP data exposure, route it through [SECURITY.md](../SECURITY.md).
21
25
 
22
26
  ## Triage Labels
@@ -44,6 +48,22 @@ Use a small, boring label vocabulary:
44
48
 
45
49
  If the user has a safe example that should pass, prefer adding a pass or quiet-pass fixture before loosening a rule. If the example should still caution but the wording is confusing, update the rule guidance or docs instead of changing matching behavior.
46
50
 
51
+ ## Report Gallery Feedback
52
+
53
+ Use report-gallery feedback when the issue is about understanding installed-package output, not changing a rule. Good outcomes are:
54
+
55
+ - a clearer gallery explanation,
56
+ - a new stable output fragment in `report-gallery.json`,
57
+ - a small docs update,
58
+ - or a redacted fixture only if the report exposes a reusable rule boundary.
59
+
60
+ After editing report support docs or issue templates, run:
61
+
62
+ ```powershell
63
+ npm.cmd run support:check
64
+ npm.cmd run reports:check
65
+ ```
66
+
47
67
  ## Converting Reports Into Fixtures
48
68
 
49
69
  Add a fixture when the report is minimal, redacted, realistic, and captures a rule behavior worth preserving.
@@ -46,6 +46,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
46
46
 
47
47
  - `README.md` leads with a no-write first run, project bootstrap, agent setup, and optional hooks/CI.
48
48
  - `docs/GETTING_STARTED.md`, `docs/CLI.md`, `docs/RELEASE.md`, and `docs/TRUSTED_PUBLISHING.md` cover the core adoption and release paths.
49
+ - `examples/reports` provides checked, public-safe report examples for fresh install diagnostics, summary output, blocked command reviews, and report-gallery feedback.
49
50
  - `site/index.html` gives maintainers a static one-page share surface that reuses the demo, social card, start command, and public links.
50
51
  - Every public release has matching `CHANGELOG.md` notes and `docs/RELEASE_NOTES_vX.Y.Z.md`.
51
52
 
@@ -55,7 +56,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
55
56
  - `jester doctor --json`, `jester config validate`, and `jester rules` are the first troubleshooting commands.
56
57
  - `jester tune`, `jester tune coverage`, and the fixture suite give maintainers a way to inspect noisy rules before changing defaults.
57
58
  - [FRAMEWORK_TUNING.md](FRAMEWORK_TUNING.md) maps common stack-specific false-positive reports to the relevant `jester tune <rule-id>` evidence and fixture IDs, while [examples/tuning](../examples/tuning) provides checked copy-paste recipes.
58
- - GitHub issue templates collect bug reports, false-positive reports, and feature requests with the diagnostic context maintainers need.
59
+ - GitHub issue templates collect bug reports, false-positive reports, report-gallery feedback, and feature requests with the diagnostic context maintainers need.
59
60
  - `SECURITY.md` routes vulnerability reports away from public issues and asks for redacted diagnostics.
60
61
  - `docs/MAINTAINER_TRIAGE.md` explains how to turn useful false-positive reports into fixture coverage before changing rule logic.
61
62
  - `npm run fixtures:check` validates fixture IDs, metadata, unsafe-looking content, duplicate content, and explicit expected/absent rule intent.
@@ -63,6 +64,8 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
63
64
  - `npm run framework:tuning:check` keeps the framework tuning guide, cookbook JSON, cookbook README, and fixture IDs aligned.
64
65
  - `npm run framework:tuning:doctor` runs the cookbook tune commands through the built CLI with temporary preset configs, so package consumers do not inherit stale recipes.
65
66
  - `npm run consumer:quickstart:check` installs the package into a temporary minimal project and runs `doctor`, `summary`, and packaged framework tuning checks from that consumer side.
67
+ - `npm run reports:check` installs the package into a temporary minimal project and runs the report gallery's `doctor`, `summary`, and blocked-command examples through that consumer side.
68
+ - `npm run support:check` verifies issue templates, support docs, and the report gallery feedback template stay public-safe and ask for useful redacted context.
66
69
  - `npm run promo:card` regenerates the deterministic social preview card, and `npm run promo:check` verifies current repo-local promo assets against the current fixture evidence before maintainers post or refresh the demo.
67
70
  - `npm run site:check` verifies the static landing page before maintainers post or host it.
68
71
  - npm publish has a manual workflow fallback, but the normal release path is tag-driven trusted publishing.
@@ -84,6 +87,8 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
84
87
  - framework tuning cookbook doctor checks are wired into `npm test`.
85
88
  - CI adoption example checks are wired into `npm test`.
86
89
  - consumer quickstart smoke checks are wired into `npm test`.
90
+ - report gallery checks are wired into `npm test`.
91
+ - support triage checks are wired into `npm test`.
87
92
  - promo freshness checks are wired into `npm test`.
88
93
  - site checks are wired into `npm test`.
89
94
 
@@ -92,4 +97,4 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
92
97
  ## Known Next Gaps
93
98
 
94
99
  - Continue expanding real-world preset fixtures and false-positive examples so tuning remains evidence-based.
95
- - Add more framework-specific false-positive examples as people report real noisy cases.
100
+ - Fold the strongest redacted support reports into fixture or report-gallery updates.
package/docs/RELEASE.md CHANGED
@@ -16,6 +16,8 @@ npm.cmd run framework:tuning:check
16
16
  npm.cmd run framework:tuning:doctor
17
17
  npm.cmd run ci:adoption:check
18
18
  npm.cmd run consumer:quickstart:check
19
+ npm.cmd run reports:check
20
+ npm.cmd run support:check
19
21
  npm.cmd run promo:card:check
20
22
  npm.cmd run promo:check
21
23
  npm.cmd run site:check
@@ -28,7 +30,7 @@ Move the current changelog bullets into a matching version section and add `docs
28
30
  ## 2. Tag And Push
29
31
 
30
32
  ```powershell
31
- git add package.json package-lock.json CHANGELOG.md docs/RELEASE_NOTES_v0.1.x.md docs/PRODUCTION_READINESS.md docs/MAINTAINER_TRIAGE.md docs/FRAMEWORK_TUNING.md docs/GITHUB_ACTIONS.md examples/ci examples/consumer-quickstart examples/tuning scripts/check-ci-adoption.mjs scripts/check-consumer-quickstart.mjs scripts/check-framework-tuning.mjs scripts/doctor-framework-tuning.mjs SECURITY.md .github/ISSUE_TEMPLATE
33
+ git add package.json package-lock.json CHANGELOG.md docs/RELEASE_NOTES_v0.1.x.md docs/PRODUCTION_READINESS.md docs/MAINTAINER_TRIAGE.md docs/FRAMEWORK_TUNING.md docs/GITHUB_ACTIONS.md examples/ci examples/consumer-quickstart examples/reports examples/tuning scripts/check-ci-adoption.mjs scripts/check-consumer-quickstart.mjs scripts/check-report-gallery.mjs scripts/check-support-triage.mjs scripts/check-framework-tuning.mjs scripts/doctor-framework-tuning.mjs SECURITY.md .github/ISSUE_TEMPLATE
32
34
  git commit -m "Release v0.1.x"
33
35
  git tag -a v0.1.x -m "Memento Mori Jester v0.1.x"
34
36
  git push origin main
@@ -85,6 +87,8 @@ npx.cmd -y memento-mori-jester@latest config validate --config jester-ai.config.
85
87
  npx.cmd -y memento-mori-jester@latest config init --preset security --path jester-security.config.json
86
88
  npx.cmd -y memento-mori-jester@latest config validate --config jester-security.config.json
87
89
  npm.cmd run consumer:quickstart:check -- --package memento-mori-jester@latest
90
+ npm.cmd run reports:check -- --package memento-mori-jester@latest
91
+ npm.cmd run support:check
88
92
  ```
89
93
 
90
94
  ## 4. MCP Copy-Paste
@@ -0,0 +1,62 @@
1
+ # Memento Mori Jester v0.1.88
2
+
3
+ ## Summary
4
+
5
+ This release adds a small checked report gallery. The goal is to make the project easier to trust from concrete public examples without changing rule behavior: a fresh `doctor` report, a destructive-command `summary`, and a full blocked command review.
6
+
7
+ ## What Changed
8
+
9
+ - Added `examples/reports/report-gallery.json`.
10
+ - Added `examples/reports/README.md`.
11
+ - Added `scripts/check-report-gallery.mjs`.
12
+ - Added `npm run reports:check`.
13
+ - Wired the report gallery checker into `npm test` and production-readiness checks.
14
+ - Updated README, getting-started docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and changelog.
15
+
16
+ ## Public Interface
17
+
18
+ - No CLI command changes.
19
+ - No MCP tool changes.
20
+ - No config schema changes.
21
+ - No review rule, scoring, matching, or verdict behavior changes.
22
+ - No GitHub Action input changes.
23
+ - New maintainer/package script: `npm run reports:check`.
24
+ - New checked example gallery: `examples/reports`.
25
+
26
+ ## Release Validation
27
+
28
+ ```powershell
29
+ npm.cmd test
30
+ npm.cmd run reports:check
31
+ npm.cmd run reports:check -- --package memento-mori-jester@latest
32
+ npm.cmd run demo:svg:check
33
+ npm.cmd run promo:card:check
34
+ npm.cmd run promo:check
35
+ npm.cmd run fixtures:report
36
+ npm.cmd run fixtures:report -- --json
37
+ npm.cmd run fixtures:report -- --markdown
38
+ npm.cmd run pack:dry
39
+ git diff --check
40
+ node .\dist\cli.js doctor
41
+ node .\dist\cli.js summary --kind command "git reset --hard"
42
+ node .\dist\cli.js command "git reset --hard"
43
+ git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.88 checked report gallery"
44
+ ```
45
+
46
+ Expected:
47
+
48
+ - `reports:check` installs the package into a temporary minimal project,
49
+ - `fresh-install-doctor` passes against installed `jester doctor`,
50
+ - `destructive-command-summary` passes against installed `jester summary --kind command "git reset --hard"`,
51
+ - `blocked-command-review` passes against installed `jester command "git reset --hard"`,
52
+ - fixture report still shows `Fixtures: 222`,
53
+ - GitHub Release and npm Publish complete from the `v0.1.88` tag.
54
+
55
+ After publish:
56
+
57
+ ```powershell
58
+ npm.cmd view memento-mori-jester version --silent
59
+ npx.cmd -y memento-mori-jester@latest doctor
60
+ npx.cmd -y memento-mori-jester@latest summary --kind command "git reset --hard"
61
+ npm.cmd run reports:check -- --package memento-mori-jester@latest
62
+ ```
@@ -0,0 +1,60 @@
1
+ # Memento Mori Jester v0.1.89
2
+
3
+ ## Summary
4
+
5
+ This release adds a checked adopter feedback path for real-world report-gallery results. The goal is to make support reports easier to act on without asking users to paste secrets, private code, customer data, full CI logs, or private paths.
6
+
7
+ ## What Changed
8
+
9
+ - Added `.github/ISSUE_TEMPLATE/report_gallery_feedback.yml`.
10
+ - Strengthened `.github/ISSUE_TEMPLATE/false_positive.yml` with package version and optional redacted `doctor --json` fields.
11
+ - Added `examples/reports/feedback-template.md`.
12
+ - Added `scripts/check-support-triage.mjs`.
13
+ - Added `npm run support:check` and wired it into `npm test`.
14
+ - Updated README, report gallery docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and changelog.
15
+
16
+ ## Public Interface
17
+
18
+ - No CLI command changes.
19
+ - No MCP tool changes.
20
+ - No config schema changes.
21
+ - No review rule, scoring, matching, or verdict behavior changes.
22
+ - No GitHub Action input changes.
23
+ - New maintainer/package script: `npm run support:check`.
24
+ - New public support path: report-gallery feedback template and issue form.
25
+
26
+ ## Release Validation
27
+
28
+ ```powershell
29
+ npm.cmd test
30
+ npm.cmd run support:check
31
+ npm.cmd run reports:check
32
+ npm.cmd run demo:svg:check
33
+ npm.cmd run promo:card:check
34
+ npm.cmd run promo:check
35
+ npm.cmd run fixtures:report
36
+ npm.cmd run fixtures:report -- --json
37
+ npm.cmd run fixtures:report -- --markdown
38
+ npm.cmd run pack:dry
39
+ git diff --check
40
+ node .\dist\cli.js doctor
41
+ node .\dist\cli.js summary --kind command "git reset --hard"
42
+ git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.89 checked support triage"
43
+ ```
44
+
45
+ Expected:
46
+
47
+ - `support:check` verifies report-gallery feedback docs, issue templates, and privacy prompts.
48
+ - `reports:check` still verifies the installed-package report gallery.
49
+ - fixture report still shows `Fixtures: 222`.
50
+ - GitHub Release and npm Publish complete from the `v0.1.89` tag.
51
+
52
+ After publish:
53
+
54
+ ```powershell
55
+ npm.cmd view memento-mori-jester version --silent
56
+ npx.cmd -y memento-mori-jester@latest doctor
57
+ npx.cmd -y memento-mori-jester@latest summary --kind command "git reset --hard"
58
+ npm.cmd run support:check
59
+ npm.cmd run reports:check -- --package memento-mori-jester@latest
60
+ ```
@@ -0,0 +1,37 @@
1
+ # Real-World Report Gallery
2
+
3
+ These small examples show the first reports people tend to trust when trying Memento Mori Jester in a fresh project. They are public, synthetic, and intentionally boring: no private code, no tokens, no customer data, and no full CI logs.
4
+
5
+ The machine-readable source is [report-gallery.json](report-gallery.json). It is checked by `npm run reports:check`, which installs Memento Mori Jester into a temporary consumer project and runs each command through that installed package.
6
+
7
+ | ID | Report | Command | What It Proves |
8
+ | --- | --- | --- | --- |
9
+ | `fresh-install-doctor` | Fresh install health check | `jester doctor` | The package, runtime, MCP file, review engine, config, hook, and workflow diagnostics are visible. |
10
+ | `destructive-command-summary` | Readable summary for a destructive command | `jester summary --kind command "git reset --hard"` | A compact report shows the block verdict, rule hit, and next tuning commands. |
11
+ | `blocked-command-review` | Full blocked command review | `jester command "git reset --hard"` | The full command review blocks the risky operation and explains the safer check. |
12
+
13
+ Run the checker from the repo root:
14
+
15
+ ```powershell
16
+ npm run reports:check
17
+ ```
18
+
19
+ After publishing, verify the same gallery against the public package:
20
+
21
+ ```powershell
22
+ npm run reports:check -- --package memento-mori-jester@latest
23
+ ```
24
+
25
+ When turning a real issue into a gallery entry, keep the example minimal and redacted. If the report needs private context, route it through [SECURITY.md](../../SECURITY.md) or keep it out of the public repo.
26
+
27
+ ## Reporting Surprising Output
28
+
29
+ If a report-gallery example is confusing, stale, or does not match what you see from `memento-mori-jester@latest`, use the public-safe [feedback template](feedback-template.md) or the GitHub [report gallery feedback issue template](../../.github/ISSUE_TEMPLATE/report_gallery_feedback.yml).
30
+
31
+ The useful public details are the package version, nearest gallery example, a sanitized command summary, a few relevant output lines, and redacted `doctor --json` output. Do not paste secrets, private repository code, customer data, full CI logs, unredacted SARIF, or private paths.
32
+
33
+ Maintainers can keep this support path aligned with:
34
+
35
+ ```powershell
36
+ npm run support:check
37
+ ```
@@ -0,0 +1,54 @@
1
+ # Report Gallery Feedback Template
2
+
3
+ Use this template when a report-gallery example is confusing, stale, or missing context. Keep reports public-safe and minimal so maintainers can turn useful feedback into docs, fixtures, or a narrow code change.
4
+
5
+ The checked examples are:
6
+
7
+ - `fresh-install-doctor`
8
+ - `destructive-command-summary`
9
+ - `blocked-command-review`
10
+
11
+ ## Commands To Run
12
+
13
+ ```powershell
14
+ npx -y memento-mori-jester@latest doctor --json
15
+ npx -y memento-mori-jester@latest summary --kind command "git reset --hard"
16
+ ```
17
+
18
+ For false-positive or noisy-rule reports, also run:
19
+
20
+ ```powershell
21
+ npx -y memento-mori-jester@latest tune <rule-id> --json
22
+ ```
23
+
24
+ ## Public Issue Draft
25
+
26
+ ```text
27
+ Jester version:
28
+ Install method: npx / global / local checkout / GitHub Action / git hook
29
+ Nearest report-gallery example: fresh-install-doctor / destructive-command-summary / blocked-command-review / none
30
+
31
+ Sanitized command or workflow step:
32
+
33
+ Sanitized output summary:
34
+
35
+ Expected behavior or clearer wording:
36
+
37
+ Relevant redacted doctor --json fields:
38
+
39
+ Relevant redacted tune output, if this is a noisy rule:
40
+
41
+ ```
42
+
43
+ ## Privacy Checklist
44
+
45
+ - Do not include secrets, tokens, private keys, customer data, or private repository code.
46
+ - Do not include full CI logs, unredacted SARIF, live credentials, or exploitable security details.
47
+ - Replace private paths and names with placeholders such as `<repo>`, `<path>`, `<service>`, or `<redacted>`.
48
+ - If the report involves credential exposure, command execution risk, package publishing, MCP data exposure, or private code disclosure, use [SECURITY.md](../../SECURITY.md) instead of a public issue.
49
+
50
+ Maintainers can validate this support path with:
51
+
52
+ ```powershell
53
+ npm run support:check
54
+ ```
@@ -0,0 +1,47 @@
1
+ [
2
+ {
3
+ "id": "fresh-install-doctor",
4
+ "title": "Fresh install health check",
5
+ "scenario": "A new repo wants to confirm the package, Node runtime, MCP server file, review engine, config discovery, hooks, and generated workflow checks are visible.",
6
+ "command": "jester doctor",
7
+ "args": ["doctor"],
8
+ "expected": {
9
+ "includes": [
10
+ "Memento Mori Jester doctor",
11
+ "PASS package-version",
12
+ "PASS review-engine: Dangerous git command is blocked.",
13
+ "The fool is fit for court."
14
+ ]
15
+ }
16
+ },
17
+ {
18
+ "id": "destructive-command-summary",
19
+ "title": "Readable summary for a destructive command",
20
+ "scenario": "A team wants a compact CI-friendly report showing which rule fired before enabling stricter workflow failure behavior.",
21
+ "command": "jester summary --kind command \"git reset --hard\"",
22
+ "args": ["summary", "--kind", "command", "git reset --hard"],
23
+ "expected": {
24
+ "includes": [
25
+ "Memento Mori Jester summary",
26
+ "Verdict: BLOCK",
27
+ "destructive-git-history",
28
+ "Suggested next:"
29
+ ]
30
+ }
31
+ },
32
+ {
33
+ "id": "blocked-command-review",
34
+ "title": "Full blocked command review",
35
+ "scenario": "A developer or agent is about to run a destructive git command and needs the full review text before proceeding.",
36
+ "command": "jester command \"git reset --hard\"",
37
+ "args": ["command", "git reset --hard"],
38
+ "expected": {
39
+ "includes": [
40
+ "Jester verdict: BLOCK",
41
+ "Destructive git operation",
42
+ "git reset --hard",
43
+ "Inspect `git status`"
44
+ ]
45
+ }
46
+ }
47
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memento-mori-jester",
3
- "version": "0.1.87",
3
+ "version": "0.1.89",
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": {
@@ -40,7 +40,7 @@
40
40
  "build": "tsc -p tsconfig.json",
41
41
  "start": "node dist/server.js",
42
42
  "start:mcp": "node dist/server.js",
43
- "test": "npm run build && node scripts/run-tests.mjs && npm run fixtures:check && npm run fixtures:report && npm run framework:tuning:check && npm run framework:tuning:doctor && npm run ci:adoption:check && npm run consumer:quickstart:check && npm run promo:check && npm run site:check && npm run production:check",
43
+ "test": "npm run build && node scripts/run-tests.mjs && npm run fixtures:check && npm run fixtures:report && npm run framework:tuning:check && npm run framework:tuning:doctor && npm run ci:adoption:check && npm run consumer:quickstart:check && npm run reports:check && npm run support:check && npm run promo:check && npm run site:check && npm run production:check",
44
44
  "doctor": "node dist/cli.js doctor",
45
45
  "demo:svg": "node scripts/render-demo-svg.mjs",
46
46
  "demo:svg:check": "node scripts/render-demo-svg.mjs --check",
@@ -50,6 +50,8 @@
50
50
  "framework:tuning:doctor": "node scripts/doctor-framework-tuning.mjs",
51
51
  "ci:adoption:check": "node scripts/check-ci-adoption.mjs",
52
52
  "consumer:quickstart:check": "node scripts/check-consumer-quickstart.mjs",
53
+ "reports:check": "node scripts/check-report-gallery.mjs",
54
+ "support:check": "node scripts/check-support-triage.mjs",
53
55
  "promo:card": "node scripts/render-social-card.mjs",
54
56
  "promo:card:check": "node scripts/render-social-card.mjs --check",
55
57
  "promo:check": "node scripts/check-promo-freshness.mjs",
@@ -72,10 +72,13 @@ for (const path of [
72
72
  "scripts/doctor-framework-tuning.mjs",
73
73
  "scripts/check-ci-adoption.mjs",
74
74
  "scripts/check-consumer-quickstart.mjs",
75
+ "scripts/check-report-gallery.mjs",
76
+ "scripts/check-support-triage.mjs",
75
77
  "scripts/check-fixtures.mjs",
76
78
  "scripts/report-fixtures.mjs",
77
79
  ".github/ISSUE_TEMPLATE/bug_report.yml",
78
80
  ".github/ISSUE_TEMPLATE/false_positive.yml",
81
+ ".github/ISSUE_TEMPLATE/report_gallery_feedback.yml",
79
82
  ".github/ISSUE_TEMPLATE/feature_request.yml",
80
83
  ".github/ISSUE_TEMPLATE/config.yml",
81
84
  ".github/workflows/ci.yml",
@@ -87,6 +90,9 @@ for (const path of [
87
90
  "examples/ci/adoption-smoke.yml",
88
91
  "examples/consumer-quickstart/README.md",
89
92
  "examples/consumer-quickstart/package.json",
93
+ "examples/reports/README.md",
94
+ "examples/reports/feedback-template.md",
95
+ "examples/reports/report-gallery.json",
90
96
  "examples/presets/README.md",
91
97
  "examples/tuning/README.md",
92
98
  "examples/tuning/framework-tuning-cookbook.json",
@@ -113,6 +119,9 @@ requireText("README.md", /FRAMEWORK_TUNING\.md/, "framework tuning guide link");
113
119
  requireText("README.md", /examples\/tuning/, "framework tuning cookbook link");
114
120
  requireText("README.md", /adoption-smoke\.yml/, "adoption smoke CI link");
115
121
  requireText("README.md", /consumer-quickstart/, "consumer quickstart smoke link");
122
+ requireText("README.md", /examples\/reports/, "report gallery link");
123
+ requireText("README.md", /feedback-template\.md/, "report gallery feedback template link");
124
+ requireText("README.md", /report gallery feedback/i, "report gallery feedback guidance");
116
125
  requireText("README.md", /License: PolyForm Noncommercial/, "the noncommercial license badge");
117
126
  requireText("docs/PRODUCTION_READINESS.md", /npm package/i, "npm package readiness");
118
127
  requireText("docs/PRODUCTION_READINESS.md", /GitHub Action/i, "GitHub Action readiness");
@@ -130,6 +139,8 @@ requireText("docs/PRODUCTION_READINESS.md", /framework:tuning:check/, "framework
130
139
  requireText("docs/PRODUCTION_READINESS.md", /framework:tuning:doctor/, "framework tuning cookbook doctor readiness");
131
140
  requireText("docs/PRODUCTION_READINESS.md", /adoption-smoke\.yml/, "adoption smoke CI readiness");
132
141
  requireText("docs/PRODUCTION_READINESS.md", /consumer:quickstart:check/, "consumer quickstart smoke readiness");
142
+ requireText("docs/PRODUCTION_READINESS.md", /reports:check/, "report gallery readiness");
143
+ requireText("docs/PRODUCTION_READINESS.md", /support:check/, "support triage readiness");
133
144
  requireText("docs/PRODUCTION_READINESS.md", /quiet-pass/, "quiet-pass fixture readiness");
134
145
  requireText("docs/CLI.md", /jester doctor --json/, "doctor JSON CLI docs");
135
146
  requireText("docs/CLI.md", /quiet-pass fixture/, "quiet-pass fixture CLI docs");
@@ -151,6 +162,9 @@ requireText("docs/MAINTAINER_TRIAGE.md", /tune <rule-id> --json/, "tune JSON tri
151
162
  requireText("docs/MAINTAINER_TRIAGE.md", /preset-review-cases\.json/, "fixture suite link");
152
163
  requireText("docs/MAINTAINER_TRIAGE.md", /expectedRuleIds/, "fixture expected rule guidance");
153
164
  requireText("docs/MAINTAINER_TRIAGE.md", /absentRuleIds/, "fixture absent rule guidance");
165
+ requireText("docs/MAINTAINER_TRIAGE.md", /feedback-template\.md/, "report gallery feedback template link");
166
+ requireText("docs/MAINTAINER_TRIAGE.md", /report_gallery_feedback\.yml/, "report gallery issue template link");
167
+ requireText("docs/MAINTAINER_TRIAGE.md", /support:check/, "support triage check guidance");
154
168
  requireText("examples/fixtures/README.md", /MAINTAINER_TRIAGE\.md/, "maintainer triage link");
155
169
  requireText("examples/fixtures/README.md", /Adding A Fixture From A Report/, "fixture report conversion guidance");
156
170
  requireText("examples/fixtures/README.md", /fixtures:check/, "fixture authoring check guidance");
@@ -164,6 +178,19 @@ requireText("examples/ci/adoption-smoke.yml", /framework:tuning:doctor/, "adopti
164
178
  requireText("examples/consumer-quickstart/README.md", /npm run consumer:quickstart:check/, "consumer quickstart check command");
165
179
  requireText("examples/consumer-quickstart/package.json", /jester:summary/, "consumer quickstart summary script");
166
180
  requireText("examples/consumer-quickstart/package.json", /framework:tuning:doctor/, "consumer quickstart tuning doctor script");
181
+ requireText("examples/reports/README.md", /report-gallery\.json/, "report gallery JSON link");
182
+ requireText("examples/reports/README.md", /feedback-template\.md/, "report gallery feedback template link");
183
+ requireText("examples/reports/README.md", /report_gallery_feedback\.yml/, "report gallery issue template link");
184
+ requireText("examples/reports/README.md", /npm run reports:check/, "report gallery check command");
185
+ requireText("examples/reports/README.md", /npm run support:check/, "support triage check command");
186
+ requireText("examples/reports/report-gallery.json", /fresh-install-doctor/, "fresh install doctor report");
187
+ requireText("examples/reports/report-gallery.json", /destructive-command-summary/, "destructive command summary report");
188
+ requireText("examples/reports/report-gallery.json", /blocked-command-review/, "blocked command review report");
189
+ requireText("examples/reports/feedback-template.md", /doctor --json/, "feedback template doctor diagnostics");
190
+ requireText("examples/reports/feedback-template.md", /summary --kind command "git reset --hard"/, "feedback template summary diagnostics");
191
+ requireText("examples/reports/feedback-template.md", /tune <rule-id> --json/, "feedback template tune diagnostics");
192
+ requireText("examples/reports/feedback-template.md", /Privacy Checklist/, "feedback template privacy checklist");
193
+ requireText("examples/reports/feedback-template.md", /SECURITY\.md/, "feedback template security redirect");
167
194
  requireText("examples/tuning/README.md", /framework-tuning-cookbook\.json/, "framework tuning cookbook JSON link");
168
195
  requireText("examples/tuning/README.md", /framework:tuning:doctor/, "framework tuning doctor guidance");
169
196
  requireText("examples/tuning/README.md", /jester tune <rule-id> --json|jester tune [a-z0-9-]+ --json/, "framework tuning command guidance");
@@ -191,12 +218,20 @@ requireText("scripts/check-ci-adoption.mjs", /framework:tuning:doctor/, "adoptio
191
218
  requireText("scripts/check-consumer-quickstart.mjs", /consumer-quickstart/, "consumer quickstart checker target");
192
219
  requireText("scripts/check-consumer-quickstart.mjs", /memento-mori-jester@latest/, "consumer quickstart registry verification option");
193
220
  requireText("scripts/check-consumer-quickstart.mjs", /framework:tuning:doctor/, "consumer quickstart tuning doctor guard");
221
+ requireText("scripts/check-report-gallery.mjs", /report-gallery\.json/, "report gallery checker target");
222
+ requireText("scripts/check-report-gallery.mjs", /memento-mori-jester@latest/, "report gallery registry verification option");
223
+ requireText("scripts/check-report-gallery.mjs", /destructive-command-summary/, "report gallery summary guard");
224
+ requireText("scripts/check-support-triage.mjs", /report_gallery_feedback\.yml/, "support triage issue template guard");
225
+ requireText("scripts/check-support-triage.mjs", /feedback-template\.md/, "support triage feedback template guard");
226
+ requireText("scripts/check-support-triage.mjs", /unsafeContentPatterns/, "support triage unsafe content checks");
194
227
  requireText("package.json", /"fixtures:check": "node scripts\/check-fixtures\.mjs"/, "fixture authoring check script");
195
228
  requireText("package.json", /"fixtures:report": "node scripts\/report-fixtures\.mjs"/, "fixture coverage report script");
196
229
  requireText("package.json", /"framework:tuning:check": "node scripts\/check-framework-tuning\.mjs"/, "framework tuning cookbook check script");
197
230
  requireText("package.json", /"framework:tuning:doctor": "node scripts\/doctor-framework-tuning\.mjs"/, "framework tuning cookbook doctor script");
198
231
  requireText("package.json", /"ci:adoption:check": "node scripts\/check-ci-adoption\.mjs"/, "CI adoption check script");
199
232
  requireText("package.json", /"consumer:quickstart:check": "node scripts\/check-consumer-quickstart\.mjs"/, "consumer quickstart check script");
233
+ requireText("package.json", /"reports:check": "node scripts\/check-report-gallery\.mjs"/, "report gallery check script");
234
+ requireText("package.json", /"support:check": "node scripts\/check-support-triage\.mjs"/, "support triage check script");
200
235
  requireText("package.json", /"promo:card": "node scripts\/render-social-card\.mjs"/, "social card render script");
201
236
  requireText("package.json", /"promo:card:check": "node scripts\/render-social-card\.mjs --check"/, "social card stale check script");
202
237
  requireText("package.json", /"promo:check": "node scripts\/check-promo-freshness\.mjs"/, "promo freshness check script");
@@ -207,6 +242,8 @@ requireText("package.json", /npm run framework:tuning:check/, "framework tuning
207
242
  requireText("package.json", /npm run framework:tuning:doctor/, "framework tuning cookbook doctor in npm test");
208
243
  requireText("package.json", /npm run ci:adoption:check/, "CI adoption check in npm test");
209
244
  requireText("package.json", /npm run consumer:quickstart:check/, "consumer quickstart check in npm test");
245
+ requireText("package.json", /npm run reports:check/, "report gallery check in npm test");
246
+ requireText("package.json", /npm run support:check/, "support triage check in npm test");
210
247
  requireText("package.json", /npm run promo:check/, "promo freshness check in npm test");
211
248
  requireText("package.json", /npm run site:check/, "site check in npm test");
212
249
  requireText("scripts/check-promo-freshness.mjs", /--require-package-version/, "optional strict package-version promo check");
@@ -220,6 +257,13 @@ requireText(".github/ISSUE_TEMPLATE/bug_report.yml", /doctor --json/, "doctor JS
220
257
  requireText(".github/ISSUE_TEMPLATE/bug_report.yml", /SECURITY\.md|security policy/i, "security redirect");
221
258
  requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /jester tune <rule-id> --json/, "tune JSON prompt");
222
259
  requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /false-positive|noisy rule/i, "false-positive scope");
260
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /Jester version/, "false-positive version prompt");
261
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /doctor --json/, "false-positive doctor diagnostics");
262
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /doctor --json/, "doctor JSON report gallery prompt");
263
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /summary --kind command "git reset --hard"/, "summary report gallery prompt");
264
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized command summary/, "sanitized command report gallery prompt");
265
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized output summary/, "sanitized output report gallery prompt");
266
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /SECURITY\.md/, "report gallery security redirect");
223
267
  requireText(".github/ISSUE_TEMPLATE/feature_request.yml", /local-first and deterministic/, "project constraint prompt");
224
268
  requireText(".github/ISSUE_TEMPLATE/config.yml", /security\/advisories\/new/, "security contact link");
225
269
 
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { dirname, isAbsolute, join, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawnSync } from "node:child_process";
7
+
8
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
9
+ const root = join(scriptDir, "..");
10
+ const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
11
+ const npmExecPath = process.env.npm_execpath;
12
+ const galleryPath = join(root, "examples", "reports", "report-gallery.json");
13
+ const readmePath = join(root, "examples", "reports", "README.md");
14
+ const args = process.argv.slice(2);
15
+
16
+ process.on("uncaughtException", (error) => {
17
+ console.error("Report gallery check failed:");
18
+ console.error(`- ${error instanceof Error ? error.message : String(error)}`);
19
+ process.exit(1);
20
+ });
21
+
22
+ let requestedPackageSpec = null;
23
+ let keepTemp = false;
24
+
25
+ for (let index = 0; index < args.length; index += 1) {
26
+ const arg = args[index];
27
+ if (arg === "--package" || arg === "--package-spec") {
28
+ requestedPackageSpec = args[index + 1];
29
+ index += 1;
30
+ } else if (arg === "--registry-latest") {
31
+ requestedPackageSpec = "memento-mori-jester@latest";
32
+ } else if (arg === "--keep-temp") {
33
+ keepTemp = true;
34
+ } else {
35
+ fail(`Unknown option: ${arg}`);
36
+ }
37
+ }
38
+
39
+ if (requestedPackageSpec === "") {
40
+ fail("--package requires a non-empty npm package spec.");
41
+ }
42
+
43
+ const unsafeContentPatterns = [
44
+ { name: "private key block", pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
45
+ { name: "OpenAI-looking secret key", pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/ },
46
+ { name: "Anthropic-looking secret key", pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/ },
47
+ { name: "GitHub-looking token", pattern: /\bgh[pousr]_[A-Za-z0-9_]{20,}\b/ },
48
+ { name: "AWS access key id", pattern: /\bAKIA[0-9A-Z]{16}\b/ },
49
+ { name: "Slack-looking token", pattern: /\bxox[baprs]-[A-Za-z0-9-]{20,}\b/ },
50
+ { name: "absolute Unix home path", pattern: /(?:^|[\s"'`])\/(?:Users|home)\/[A-Za-z0-9._-]+/ },
51
+ { name: "absolute Windows user path", pattern: /[A-Za-z]:\\Users\\[A-Za-z0-9._-]+\\/ }
52
+ ];
53
+
54
+ const gallery = readGallery();
55
+ checkReadme(gallery);
56
+
57
+ const tempRoot = mkdtempSync(join(tmpdir(), "jester-report-gallery-"));
58
+ let packageSpec = requestedPackageSpec;
59
+ const packageLabel = requestedPackageSpec ?? "local packed package";
60
+
61
+ try {
62
+ if (!packageSpec) {
63
+ packageSpec = packLocalPackage(tempRoot);
64
+ }
65
+ } catch (error) {
66
+ rmSync(tempRoot, { recursive: true, force: true });
67
+ throw error;
68
+ }
69
+
70
+ try {
71
+ const consumerDir = join(tempRoot, "consumer-project");
72
+ prepareConsumerProject(consumerDir, packageSpec);
73
+
74
+ const results = [];
75
+ for (const report of gallery) {
76
+ const output = runNpm(["exec", "--", "jester", ...report.args], { cwd: consumerDir });
77
+ for (const expected of report.expected.includes) {
78
+ if (!output.includes(expected)) {
79
+ fail(`${report.id} output should include ${expected}. Output was:\n${output}`);
80
+ }
81
+ }
82
+ results.push(report.id);
83
+ }
84
+
85
+ console.log("Report gallery check");
86
+ console.log(`PASS installed ${packageLabel}`);
87
+ for (const id of results) {
88
+ console.log(`PASS ${id}`);
89
+ }
90
+ } finally {
91
+ if (keepTemp) {
92
+ console.log(`Kept temp project at ${tempRoot}`);
93
+ } else {
94
+ rmSync(tempRoot, { recursive: true, force: true });
95
+ }
96
+ }
97
+
98
+ function readGallery() {
99
+ if (!existsSync(galleryPath)) {
100
+ fail("examples/reports/report-gallery.json is missing.");
101
+ }
102
+
103
+ if (!existsSync(readmePath)) {
104
+ fail("examples/reports/README.md is missing.");
105
+ }
106
+
107
+ const galleryRaw = readFileSync(galleryPath, "utf8");
108
+ const readme = readFileSync(readmePath, "utf8");
109
+
110
+ for (const [path, content] of [
111
+ ["examples/reports/report-gallery.json", galleryRaw],
112
+ ["examples/reports/README.md", readme]
113
+ ]) {
114
+ for (const unsafe of unsafeContentPatterns) {
115
+ if (unsafe.pattern.test(content)) {
116
+ fail(`${path} appears to contain ${unsafe.name}; report examples should stay public and redacted.`);
117
+ }
118
+ }
119
+ }
120
+
121
+ let parsed;
122
+ try {
123
+ parsed = JSON.parse(galleryRaw);
124
+ } catch (error) {
125
+ fail(`examples/reports/report-gallery.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
126
+ }
127
+
128
+ if (!Array.isArray(parsed) || parsed.length !== 3) {
129
+ fail("examples/reports/report-gallery.json should contain exactly three report examples.");
130
+ }
131
+
132
+ const expectedIds = ["fresh-install-doctor", "destructive-command-summary", "blocked-command-review"];
133
+ const seenIds = new Set();
134
+
135
+ for (const [index, report] of parsed.entries()) {
136
+ const expectedId = expectedIds[index];
137
+ if (report?.id !== expectedId) {
138
+ fail(`Report ${index + 1} should have id ${expectedId}.`);
139
+ }
140
+
141
+ if (seenIds.has(report.id)) {
142
+ fail(`Duplicate report id: ${report.id}.`);
143
+ }
144
+ seenIds.add(report.id);
145
+
146
+ for (const field of ["title", "scenario", "command"]) {
147
+ if (typeof report[field] !== "string" || report[field].trim().length < 10) {
148
+ fail(`${report.id}.${field} should be a useful string.`);
149
+ }
150
+ }
151
+
152
+ if (!Array.isArray(report.args) || report.args.length === 0 || report.args.some((arg) => typeof arg !== "string")) {
153
+ fail(`${report.id}.args should be a non-empty string array.`);
154
+ }
155
+
156
+ if (!Array.isArray(report.expected?.includes) || report.expected.includes.length < 3) {
157
+ fail(`${report.id}.expected.includes should contain at least three stable output fragments.`);
158
+ }
159
+ }
160
+
161
+ return parsed;
162
+ }
163
+
164
+ function checkReadme(gallery) {
165
+ const readme = readFileSync(readmePath, "utf8");
166
+
167
+ for (const report of gallery) {
168
+ for (const expected of [report.id, report.command]) {
169
+ if (!readme.includes(expected)) {
170
+ fail(`examples/reports/README.md should include ${expected}.`);
171
+ }
172
+ }
173
+ }
174
+
175
+ for (const expected of [
176
+ "npm run reports:check",
177
+ "memento-mori-jester@latest",
178
+ "SECURITY.md"
179
+ ]) {
180
+ if (!readme.includes(expected)) {
181
+ fail(`examples/reports/README.md should include ${expected}.`);
182
+ }
183
+ }
184
+ }
185
+
186
+ function packLocalPackage(destination) {
187
+ const cliPath = join(root, "dist", "cli.js");
188
+ if (!existsSync(cliPath)) {
189
+ fail(`${cliPath} is missing. Run npm run build before npm run reports:check.`);
190
+ }
191
+
192
+ const output = runNpm(["pack", "--ignore-scripts", "--pack-destination", destination, "--silent"], { cwd: root });
193
+ const filename = output.trim().split(/\r?\n/).filter(Boolean).at(-1);
194
+ if (!filename) {
195
+ fail("npm pack did not return a tarball filename.");
196
+ }
197
+
198
+ return isAbsolute(filename) ? filename : resolve(destination, filename);
199
+ }
200
+
201
+ function prepareConsumerProject(consumerDir, spec) {
202
+ rmSync(consumerDir, { recursive: true, force: true });
203
+ mkdirSync(consumerDir, { recursive: true });
204
+ writeFileSync(
205
+ join(consumerDir, "package.json"),
206
+ `${JSON.stringify({ name: "jester-report-gallery-consumer", version: "0.0.0", private: true }, null, 2)}\n`
207
+ );
208
+ runNpm(["install", "--save-dev", spec, "--ignore-scripts", "--no-audit", "--no-fund"], { cwd: consumerDir });
209
+ }
210
+
211
+ function runNpm(commandArgs, options = {}) {
212
+ if (npmExecPath) {
213
+ return run(process.execPath, [npmExecPath, ...commandArgs], options);
214
+ }
215
+
216
+ return run(npmCommand, commandArgs, options);
217
+ }
218
+
219
+ function run(command, commandArgs, options = {}) {
220
+ const result = spawnSync(command, commandArgs, {
221
+ cwd: options.cwd ?? root,
222
+ encoding: "utf8",
223
+ maxBuffer: 20 * 1024 * 1024,
224
+ env: {
225
+ ...process.env,
226
+ npm_config_audit: "false",
227
+ npm_config_fund: "false"
228
+ }
229
+ });
230
+
231
+ if (result.error) {
232
+ throw result.error;
233
+ }
234
+
235
+ if (result.status !== 0) {
236
+ const detail = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
237
+ fail(`${command} ${commandArgs.join(" ")} failed${detail ? `:\n${detail}` : "."}`);
238
+ }
239
+
240
+ return result.stdout;
241
+ }
242
+
243
+ function fail(message) {
244
+ throw new Error(message);
245
+ }
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
7
+ const root = join(scriptDir, "..");
8
+ const failures = [];
9
+
10
+ const unsafeContentPatterns = [
11
+ { name: "private key block", pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
12
+ { name: "OpenAI-looking secret key", pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/ },
13
+ { name: "Anthropic-looking secret key", pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/ },
14
+ { name: "GitHub-looking token", pattern: /\bgh[pousr]_[A-Za-z0-9_]{20,}\b/ },
15
+ { name: "AWS access key id", pattern: /\bAKIA[0-9A-Z]{16}\b/ },
16
+ { name: "Slack-looking token", pattern: /\bxox[baprs]-[A-Za-z0-9-]{20,}\b/ },
17
+ { name: "absolute Unix home path", pattern: /(?:^|[\s"'`])\/(?:Users|home)\/[A-Za-z0-9._-]+/ },
18
+ { name: "absolute Windows user path", pattern: /[A-Za-z]:\\Users\\[A-Za-z0-9._-]+\\/ }
19
+ ];
20
+
21
+ const supportFiles = [
22
+ ".github/ISSUE_TEMPLATE/report_gallery_feedback.yml",
23
+ ".github/ISSUE_TEMPLATE/bug_report.yml",
24
+ ".github/ISSUE_TEMPLATE/false_positive.yml",
25
+ ".github/ISSUE_TEMPLATE/config.yml",
26
+ "examples/reports/feedback-template.md",
27
+ "examples/reports/README.md",
28
+ "docs/MAINTAINER_TRIAGE.md",
29
+ "docs/PRODUCTION_READINESS.md",
30
+ "README.md",
31
+ "SECURITY.md"
32
+ ];
33
+
34
+ for (const path of supportFiles) {
35
+ requireFile(path);
36
+ }
37
+
38
+ for (const path of supportFiles.filter((path) => existsSync(join(root, path)))) {
39
+ const content = read(path);
40
+ for (const unsafe of unsafeContentPatterns) {
41
+ if (unsafe.pattern.test(content)) {
42
+ failures.push(`${path} appears to contain ${unsafe.name}; support examples must stay public-safe and redacted.`);
43
+ }
44
+ }
45
+ }
46
+
47
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Report gallery feedback/, "a report gallery feedback template name");
48
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /fresh-install-doctor/, "the fresh install report option");
49
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /destructive-command-summary/, "the destructive summary report option");
50
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /blocked-command-review/, "the blocked command report option");
51
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /doctor --json/, "doctor JSON diagnostics");
52
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /summary --kind command "git reset --hard"/, "the report-gallery summary smoke");
53
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized command summary/, "sanitized command prompt");
54
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized output summary/, "sanitized output prompt");
55
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /SECURITY\.md/, "security redirect");
56
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /removed secrets, tokens, private code, private paths, customer data, and full CI logs/, "privacy checkbox");
57
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /Jester version/, "false-positive version prompt");
58
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /doctor --json/, "false-positive doctor diagnostics");
59
+
60
+ requireText("examples/reports/feedback-template.md", /Report Gallery Feedback Template/, "feedback template heading");
61
+ requireText("examples/reports/feedback-template.md", /fresh-install-doctor/, "fresh install report id");
62
+ requireText("examples/reports/feedback-template.md", /destructive-command-summary/, "destructive summary report id");
63
+ requireText("examples/reports/feedback-template.md", /blocked-command-review/, "blocked command report id");
64
+ requireText("examples/reports/feedback-template.md", /doctor --json/, "doctor JSON command");
65
+ requireText("examples/reports/feedback-template.md", /summary --kind command "git reset --hard"/, "summary command");
66
+ requireText("examples/reports/feedback-template.md", /tune <rule-id> --json/, "tune JSON command");
67
+ requireText("examples/reports/feedback-template.md", /Privacy Checklist/, "privacy checklist");
68
+ requireText("examples/reports/feedback-template.md", /SECURITY\.md/, "security redirect");
69
+ requireText("examples/reports/feedback-template.md", /npm run support:check/, "support checker command");
70
+
71
+ requireText("examples/reports/README.md", /feedback-template\.md/, "feedback template link");
72
+ requireText("examples/reports/README.md", /report_gallery_feedback\.yml/, "GitHub issue template link");
73
+ requireText("examples/reports/README.md", /npm run support:check/, "support checker command");
74
+ requireText("docs/MAINTAINER_TRIAGE.md", /feedback-template\.md/, "feedback template triage link");
75
+ requireText("docs/MAINTAINER_TRIAGE.md", /report_gallery_feedback\.yml/, "report gallery issue template triage link");
76
+ requireText("docs/MAINTAINER_TRIAGE.md", /npm(?:\.cmd)? run support:check/, "support checker triage command");
77
+ requireText("docs/PRODUCTION_READINESS.md", /support:check/, "support checker readiness");
78
+ requireText("README.md", /feedback-template\.md/, "feedback template README link");
79
+ requireText("README.md", /report gallery feedback/i, "report gallery feedback guidance");
80
+
81
+ requireText("package.json", /"support:check": "node scripts\/check-support-triage\.mjs"/, "support checker script");
82
+ requireText("package.json", /npm run support:check/, "support checker in npm test");
83
+
84
+ if (failures.length > 0) {
85
+ console.error("Support triage check failed:");
86
+ for (const failure of failures) {
87
+ console.error(`- ${failure}`);
88
+ }
89
+ process.exit(1);
90
+ }
91
+
92
+ console.log("Support triage check passed.");
93
+
94
+ function read(path) {
95
+ return readFileSync(join(root, path), "utf8");
96
+ }
97
+
98
+ function requireFile(path) {
99
+ if (!existsSync(join(root, path))) {
100
+ failures.push(`${path} is missing.`);
101
+ }
102
+ }
103
+
104
+ function requireText(path, pattern, description) {
105
+ if (!existsSync(join(root, path))) {
106
+ failures.push(`${path} is missing; cannot check for ${description}.`);
107
+ return;
108
+ }
109
+
110
+ const content = read(path);
111
+ if (!pattern.test(content)) {
112
+ failures.push(`${path} should include ${description}.`);
113
+ }
114
+ }