memento-mori-jester 0.1.88 → 0.1.90

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.90
8
+
9
+ - Added `examples/support`, a checked maintainer triage playbook for sanitized report-gallery and false-positive reports.
10
+ - Extended `npm run support:check` and production-readiness checks so the playbook keeps public-safe examples, first responses, classifications, and follow-up outcomes aligned.
11
+ - Updated README, report docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and release notes for deterministic support handling.
12
+
13
+ ## 0.1.89
14
+
15
+ - 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.
16
+ - Added `examples/reports/feedback-template.md` and `npm run support:check` so adopter feedback requests stay redacted, useful, and aligned with the gallery.
17
+ - Updated README, report docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and release notes for the support path.
18
+
7
19
  ## 0.1.88
8
20
 
9
21
  - Added `examples/reports`, a small checked report gallery for fresh `doctor`, destructive-command `summary`, and full blocked-command review output.
package/README.md CHANGED
@@ -74,6 +74,10 @@ Maintainers can prove that fresh-project path with [examples/consumer-quickstart
74
74
 
75
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
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
+
79
+ Maintainers can use the checked [support triage playbook](examples/support) to turn sanitized reports into a docs example, fixture backlog item, or rule-review candidate without changing behavior first.
80
+
77
81
  Expected vibe:
78
82
 
79
83
  ```text
@@ -445,6 +449,8 @@ More setup examples:
445
449
  - [Adoption Smoke CI](examples/ci/adoption-smoke.yml)
446
450
  - [Consumer Quickstart Smoke](examples/consumer-quickstart)
447
451
  - [Real-World Report Gallery](examples/reports)
452
+ - [Report Gallery Feedback Template](examples/reports/feedback-template.md)
453
+ - [Support Triage Playbook](examples/support)
448
454
  - [Security Policy](SECURITY.md)
449
455
  - [Maintainer Triage](docs/MAINTAINER_TRIAGE.md)
450
456
  - [Changelog](CHANGELOG.md)
@@ -465,6 +471,8 @@ Framework CI examples:
465
471
  - [Adoption Smoke CI](examples/ci/adoption-smoke.yml)
466
472
  - [Consumer Quickstart Smoke](examples/consumer-quickstart)
467
473
  - [Real-World Report Gallery](examples/reports)
474
+ - [Report Gallery Feedback Template](examples/reports/feedback-template.md)
475
+ - [Support Triage Playbook](examples/support)
468
476
  - [Next.js CI](examples/ci/nextjs.yml)
469
477
  - [Vite React CI](examples/ci/vite-react.yml)
470
478
  - [Express API CI](examples/ci/express-api.yml)
@@ -521,6 +529,7 @@ Maintainers can use [docs/MAINTAINER_TRIAGE.md](docs/MAINTAINER_TRIAGE.md) to tu
521
529
  Run `npm run fixtures:check` before merging fixture changes; it catches duplicate IDs, missing rule metadata, weak descriptions, unsafe-looking content, and duplicate content.
522
530
  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.
523
531
  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.
532
+ Run `npm run support:check` after editing issue templates, support docs, the report gallery feedback path, or the [support triage playbook](examples/support); it verifies the public templates ask for useful redacted context without inviting secrets or private code.
524
533
  Run `npm run promo:card` to regenerate the repo-local social preview card after changing its copy or design.
525
534
  Run `npm run promo:check` after editing promo assets; it checks the current demo video, stills, docs, and fixture evidence numbers stay in sync.
526
535
  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.
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 maintainer triage playbook in v0.1.90, showing how sanitized reports become docs examples, fixture backlog items, or rule-review candidates.
10
+ - Checked adopter feedback path in v0.1.89, adding a report-gallery issue template, package-shipped feedback template, and support triage guard.
9
11
  - Checked report gallery in v0.1.88, proving fresh `doctor`, destructive-command `summary`, and blocked-command reports from an installed consumer project.
10
12
  - Consumer quickstart registry-mode fix in v0.1.87, proving the same smoke against `memento-mori-jester@latest` after publish.
11
13
  - Consumer quickstart smoke in v0.1.86, proving the first installed-project commands from a minimal repo before release.
@@ -78,7 +80,7 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
78
80
  ## Product Ideas
79
81
 
80
82
  - Collect real-world reports and fold the strongest redacted cases into more framework tuning cookbook recipes.
81
- - Add a small fixture issue template checklist that asks for the nearest framework tuning cookbook recipe and redacted `jester tune <rule-id> --json` output.
83
+ - Use repeated playbook outcomes to prioritize the next redacted fixture or report-gallery update.
82
84
  - Add a hosted-page option or GitHub Pages instructions once the static page has settled.
83
85
 
84
86
  ## Quality And Safety
@@ -19,6 +19,10 @@ npx -y memento-mori-jester@latest tune <rule-id> --json
19
19
 
20
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
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
+
24
+ When a report has enough public-safe detail to triage, compare it with the checked [support triage playbook](../examples/support). The playbook walks sanitized report-gallery and false-positive reports through first response, classification, and a follow-up outcome.
25
+
22
26
  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).
23
27
 
24
28
  ## Triage Labels
@@ -46,6 +50,28 @@ Use a small, boring label vocabulary:
46
50
 
47
51
  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.
48
52
 
53
+ ## Report Gallery Feedback
54
+
55
+ Use report-gallery feedback when the issue is about understanding installed-package output, not changing a rule. Good outcomes are:
56
+
57
+ - a clearer gallery explanation,
58
+ - a new stable output fragment in `report-gallery.json`,
59
+ - a small docs update,
60
+ - or a redacted fixture only if the report exposes a reusable rule boundary.
61
+
62
+ Use the playbook outcomes consistently:
63
+
64
+ - `docs-example`: the behavior is expected but the report or wording is unclear.
65
+ - `fixture-backlog`: the reduced report looks safe and should become a pass or quiet-pass fixture.
66
+ - `rule-review-candidate`: repeated sanitized reports suggest guidance or matching may need review, but not from a single report.
67
+
68
+ After editing report support docs or issue templates, run:
69
+
70
+ ```powershell
71
+ npm.cmd run support:check
72
+ npm.cmd run reports:check
73
+ ```
74
+
49
75
  ## Converting Reports Into Fixtures
50
76
 
51
77
  Add a fixture when the report is minimal, redacted, realistic, and captures a rule behavior worth preserving.
@@ -46,7 +46,8 @@ 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, and blocked command reviews.
49
+ - `examples/reports` provides checked, public-safe report examples for fresh install diagnostics, summary output, blocked command reviews, and report-gallery feedback.
50
+ - `examples/support` provides a checked maintainer triage playbook for first response, classification, and follow-up outcomes from sanitized support reports.
50
51
  - `site/index.html` gives maintainers a static one-page share surface that reuses the demo, social card, start command, and public links.
51
52
  - Every public release has matching `CHANGELOG.md` notes and `docs/RELEASE_NOTES_vX.Y.Z.md`.
52
53
 
@@ -56,15 +57,17 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
56
57
  - `jester doctor --json`, `jester config validate`, and `jester rules` are the first troubleshooting commands.
57
58
  - `jester tune`, `jester tune coverage`, and the fixture suite give maintainers a way to inspect noisy rules before changing defaults.
58
59
  - [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.
59
- - GitHub issue templates collect bug reports, false-positive reports, and feature requests with the diagnostic context maintainers need.
60
+ - GitHub issue templates collect bug reports, false-positive reports, report-gallery feedback, and feature requests with the diagnostic context maintainers need.
60
61
  - `SECURITY.md` routes vulnerability reports away from public issues and asks for redacted diagnostics.
61
62
  - `docs/MAINTAINER_TRIAGE.md` explains how to turn useful false-positive reports into fixture coverage before changing rule logic.
63
+ - `examples/support` shows maintainers how to classify sanitized reports as a docs example, fixture backlog item, or rule-review candidate before changing behavior.
62
64
  - `npm run fixtures:check` validates fixture IDs, metadata, unsafe-looking content, duplicate content, and explicit expected/absent rule intent.
63
65
  - `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.
64
66
  - `npm run framework:tuning:check` keeps the framework tuning guide, cookbook JSON, cookbook README, and fixture IDs aligned.
65
67
  - `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.
66
68
  - `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
69
  - `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.
70
+ - `npm run support:check` verifies issue templates, support docs, the report gallery feedback template, and the maintainer triage playbook stay public-safe and ask for useful redacted context.
68
71
  - `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.
69
72
  - `npm run site:check` verifies the static landing page before maintainers post or host it.
70
73
  - npm publish has a manual workflow fallback, but the normal release path is tag-driven trusted publishing.
@@ -87,6 +90,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
87
90
  - CI adoption example checks are wired into `npm test`.
88
91
  - consumer quickstart smoke checks are wired into `npm test`.
89
92
  - report gallery checks are wired into `npm test`.
93
+ - support triage checks are wired into `npm test`.
90
94
  - promo freshness checks are wired into `npm test`.
91
95
  - site checks are wired into `npm test`.
92
96
 
@@ -95,4 +99,4 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
95
99
  ## Known Next Gaps
96
100
 
97
101
  - Continue expanding real-world preset fixtures and false-positive examples so tuning remains evidence-based.
98
- - Add more framework-specific false-positive examples as people report real noisy cases.
102
+ - Fold the strongest redacted support reports into fixture, playbook, or report-gallery updates.
package/docs/RELEASE.md CHANGED
@@ -17,6 +17,7 @@ npm.cmd run framework:tuning:doctor
17
17
  npm.cmd run ci:adoption:check
18
18
  npm.cmd run consumer:quickstart:check
19
19
  npm.cmd run reports:check
20
+ npm.cmd run support:check
20
21
  npm.cmd run promo:card:check
21
22
  npm.cmd run promo:check
22
23
  npm.cmd run site:check
@@ -29,7 +30,7 @@ Move the current changelog bullets into a matching version section and add `docs
29
30
  ## 2. Tag And Push
30
31
 
31
32
  ```powershell
32
- 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-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/support 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
33
34
  git commit -m "Release v0.1.x"
34
35
  git tag -a v0.1.x -m "Memento Mori Jester v0.1.x"
35
36
  git push origin main
@@ -87,6 +88,7 @@ npx.cmd -y memento-mori-jester@latest config init --preset security --path jeste
87
88
  npx.cmd -y memento-mori-jester@latest config validate --config jester-security.config.json
88
89
  npm.cmd run consumer:quickstart:check -- --package memento-mori-jester@latest
89
90
  npm.cmd run reports:check -- --package memento-mori-jester@latest
91
+ npm.cmd run support:check
90
92
  ```
91
93
 
92
94
  ## 4. MCP Copy-Paste
@@ -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,58 @@
1
+ # Memento Mori Jester v0.1.90
2
+
3
+ ## Summary
4
+
5
+ This release adds a checked maintainer triage playbook for sanitized support reports. The goal is to make report handling deterministic after users submit public-safe report-gallery feedback or false-positive reports: first response, classification, and follow-up outcome are now documented and checked.
6
+
7
+ ## What Changed
8
+
9
+ - Added `examples/support/README.md`.
10
+ - Added `examples/support/triage-playbook.json`.
11
+ - Extended `scripts/check-support-triage.mjs` to validate the playbook.
12
+ - Extended production-readiness checks for the playbook.
13
+ - Updated README, report gallery docs, maintainer triage docs, release docs, production-readiness docs, roadmap, and changelog.
14
+
15
+ ## Public Interface
16
+
17
+ - No CLI command changes.
18
+ - No MCP tool changes.
19
+ - No config schema changes.
20
+ - No review rule, scoring, matching, or verdict behavior changes.
21
+ - No GitHub Action input changes.
22
+ - Support docs and package examples now include a checked maintainer playbook.
23
+
24
+ ## Release Validation
25
+
26
+ ```powershell
27
+ npm.cmd test
28
+ npm.cmd run support:check
29
+ npm.cmd run reports:check
30
+ npm.cmd run demo:svg:check
31
+ npm.cmd run promo:card:check
32
+ npm.cmd run promo:check
33
+ npm.cmd run fixtures:report
34
+ npm.cmd run fixtures:report -- --json
35
+ npm.cmd run fixtures:report -- --markdown
36
+ npm.cmd run pack:dry
37
+ git diff --check
38
+ node .\dist\cli.js doctor
39
+ node .\dist\cli.js summary --kind command "git reset --hard"
40
+ git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.90 checked maintainer triage playbook"
41
+ ```
42
+
43
+ Expected:
44
+
45
+ - `support:check` verifies issue templates, feedback templates, and the maintainer triage playbook.
46
+ - `reports:check` still verifies the installed-package report gallery.
47
+ - fixture report still shows `Fixtures: 222`.
48
+ - GitHub Release and npm Publish complete from the `v0.1.90` tag.
49
+
50
+ After publish:
51
+
52
+ ```powershell
53
+ npm.cmd view memento-mori-jester version --silent
54
+ npx.cmd -y memento-mori-jester@latest doctor
55
+ npx.cmd -y memento-mori-jester@latest summary --kind command "git reset --hard"
56
+ npm.cmd run support:check
57
+ npm.cmd run reports:check -- --package memento-mori-jester@latest
58
+ ```
@@ -23,3 +23,17 @@ npm run reports:check -- --package memento-mori-jester@latest
23
23
  ```
24
24
 
25
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 should handle those reports with the checked [Maintainer Triage Playbook](../support), which shows first responses, classifications, and follow-up outcomes for docs examples, fixture backlog items, and rule-review candidates.
34
+
35
+ Maintainers can keep this support path aligned with:
36
+
37
+ ```powershell
38
+ npm run support:check
39
+ ```
@@ -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,41 @@
1
+ # Maintainer Triage Playbook
2
+
3
+ This playbook shows how to handle sanitized adopter reports without turning every surprise into an immediate rule change. It pairs with [docs/MAINTAINER_TRIAGE.md](../../docs/MAINTAINER_TRIAGE.md), the [report gallery feedback template](../reports/feedback-template.md), and the GitHub issue templates.
4
+
5
+ The checked source is [triage-playbook.json](triage-playbook.json). It covers three common support outcomes:
6
+
7
+ | ID | Source | Classification | Follow-up |
8
+ | --- | --- | --- | --- |
9
+ | `gallery-expected-block-docs` | report-gallery feedback | expected docs clarification | docs example |
10
+ | `false-positive-fixture-backlog` | false-positive report | plausible safe boundary | fixture backlog |
11
+ | `repeated-risky-domain-rule-review` | false-positive report | repeated surprise pattern | rule-review candidate |
12
+
13
+ ## Maintainer Flow
14
+
15
+ 1. Confirm the report is public-safe. If it includes secrets, private code, full CI logs, exploitable details, package publishing concerns, MCP data exposure, or credential handling, route it through [SECURITY.md](../../SECURITY.md).
16
+ 2. Ask for the smallest redacted reproduction plus `jester doctor --json`.
17
+ 3. For noisy rules, ask for `jester tune <rule-id> --json`.
18
+ 4. Classify the report as `docs`, `false-positive`, `rules`, `bug`, or `security`.
19
+ 5. Choose one follow-up outcome:
20
+ - `docs-example`: improve wording or a checked report example.
21
+ - `fixture-backlog`: add a pass or quiet-pass fixture before changing behavior.
22
+ - `rule-review-candidate`: collect repeated sanitized reports before changing guidance or matching.
23
+ 6. Close with the next command the user can run.
24
+
25
+ ## Checks
26
+
27
+ Run this after editing support docs, issue templates, or the playbook:
28
+
29
+ ```powershell
30
+ npm run support:check
31
+ ```
32
+
33
+ Run these when a report becomes fixture work:
34
+
35
+ ```powershell
36
+ npm run fixtures:check
37
+ npm run fixtures:report
38
+ npm run fixtures:report -- --markdown
39
+ ```
40
+
41
+ The playbook is intentionally synthetic and public. Do not add private repository names, private paths, tokens, customer data, or full logs.
@@ -0,0 +1,96 @@
1
+ [
2
+ {
3
+ "id": "gallery-expected-block-docs",
4
+ "source": "report-gallery-feedback",
5
+ "nearestReportExample": "destructive-command-summary",
6
+ "sanitizedReport": {
7
+ "version": "latest",
8
+ "kind": "command",
9
+ "command": "jester summary --kind command \"git reset --hard\"",
10
+ "observed": [
11
+ "Verdict: BLOCK",
12
+ "destructive-git-history",
13
+ "Suggested next: jester tune destructive-git-history"
14
+ ],
15
+ "question": "I expected this to warn, not block, because I only wanted to see the summary output."
16
+ },
17
+ "firstResponse": "Thanks. This looks like expected behavior for the destructive-command summary example: the command is intentionally blocked so the gallery can show a high-signal report. Please share redacted `jester doctor --json` output only if your local output differs from the checked example.",
18
+ "classification": {
19
+ "labels": ["docs"],
20
+ "decision": "expected-behavior-docs-example",
21
+ "rationale": "The reported command matches a checked gallery example and does not indicate a rule bug."
22
+ },
23
+ "maintainerChecks": [
24
+ "npm run reports:check",
25
+ "npm run support:check"
26
+ ],
27
+ "followUpOutcome": {
28
+ "type": "docs-example",
29
+ "action": "Clarify the report gallery row or README wording if multiple adopters expect a non-blocking example."
30
+ }
31
+ },
32
+ {
33
+ "id": "false-positive-fixture-backlog",
34
+ "source": "false-positive",
35
+ "nearestReportExample": "none",
36
+ "sanitizedReport": {
37
+ "version": "latest",
38
+ "kind": "diff",
39
+ "ruleId": "custom-web-storage-sensitive-value",
40
+ "command": "jester summary --kind diff <redacted-diff>",
41
+ "observed": [
42
+ "Verdict: BLOCK",
43
+ "custom-web-storage-sensitive-value",
44
+ "localStorage theme preference"
45
+ ],
46
+ "question": "This looks like a theme preference, not a token or password."
47
+ },
48
+ "firstResponse": "Thanks. Please keep the diff minimal and redacted, then include `jester tune custom-web-storage-sensitive-value --json` and redacted `jester doctor --json` output. If the reduced example only stores a non-sensitive preference, this should become a quiet-pass fixture candidate before any rule change.",
49
+ "classification": {
50
+ "labels": ["false-positive", "rules"],
51
+ "decision": "fixture-backlog",
52
+ "rationale": "The report describes a plausible safe boundary, but maintainers need a minimized redacted reproduction before changing matching behavior."
53
+ },
54
+ "maintainerChecks": [
55
+ "npm run fixtures:check",
56
+ "npm run fixtures:report",
57
+ "npm run support:check"
58
+ ],
59
+ "followUpOutcome": {
60
+ "type": "fixture-backlog",
61
+ "action": "Add a quiet-pass fixture with `absentRuleIds` for the noisy rule if the sanitized reproduction is valid and not already covered."
62
+ }
63
+ },
64
+ {
65
+ "id": "repeated-risky-domain-rule-review",
66
+ "source": "false-positive",
67
+ "nearestReportExample": "none",
68
+ "sanitizedReport": {
69
+ "version": "latest",
70
+ "kind": "plan",
71
+ "ruleId": "risky-domain",
72
+ "command": "jester summary --kind plan \"Update auth docs and verify links\"",
73
+ "observed": [
74
+ "Verdict: CAUTION",
75
+ "risky-domain",
76
+ "High-risk domain touched"
77
+ ],
78
+ "question": "The plan is documentation-only, but the rule still cautions because it mentions auth."
79
+ },
80
+ "firstResponse": "Thanks. This may be expected caution for plan text, but repeated reports can justify a rule-review candidate. Please share redacted `jester doctor --json` output, redacted `jester tune risky-domain --json` output, and the smallest plan text that reproduces the surprise. Do not paste private project details.",
81
+ "classification": {
82
+ "labels": ["false-positive", "rules"],
83
+ "decision": "rule-review-candidate",
84
+ "rationale": "One report is not enough to loosen a broad domain rule, but repeated sanitized reports may show the guidance or matching boundary needs review."
85
+ },
86
+ "maintainerChecks": [
87
+ "npm run fixtures:report -- --markdown",
88
+ "node .\\dist\\cli.js tune risky-domain --json",
89
+ "npm run support:check"
90
+ ],
91
+ "followUpOutcome": {
92
+ "type": "rule-review-candidate",
93
+ "action": "Collect at least two sanitized examples and compare fixture evidence before changing rule guidance or matching."
94
+ }
95
+ }
96
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memento-mori-jester",
3
- "version": "0.1.88",
3
+ "version": "0.1.90",
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 reports: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",
@@ -51,6 +51,7 @@
51
51
  "ci:adoption:check": "node scripts/check-ci-adoption.mjs",
52
52
  "consumer:quickstart:check": "node scripts/check-consumer-quickstart.mjs",
53
53
  "reports:check": "node scripts/check-report-gallery.mjs",
54
+ "support:check": "node scripts/check-support-triage.mjs",
54
55
  "promo:card": "node scripts/render-social-card.mjs",
55
56
  "promo:card:check": "node scripts/render-social-card.mjs --check",
56
57
  "promo:check": "node scripts/check-promo-freshness.mjs",
@@ -73,10 +73,12 @@ for (const path of [
73
73
  "scripts/check-ci-adoption.mjs",
74
74
  "scripts/check-consumer-quickstart.mjs",
75
75
  "scripts/check-report-gallery.mjs",
76
+ "scripts/check-support-triage.mjs",
76
77
  "scripts/check-fixtures.mjs",
77
78
  "scripts/report-fixtures.mjs",
78
79
  ".github/ISSUE_TEMPLATE/bug_report.yml",
79
80
  ".github/ISSUE_TEMPLATE/false_positive.yml",
81
+ ".github/ISSUE_TEMPLATE/report_gallery_feedback.yml",
80
82
  ".github/ISSUE_TEMPLATE/feature_request.yml",
81
83
  ".github/ISSUE_TEMPLATE/config.yml",
82
84
  ".github/workflows/ci.yml",
@@ -89,7 +91,10 @@ for (const path of [
89
91
  "examples/consumer-quickstart/README.md",
90
92
  "examples/consumer-quickstart/package.json",
91
93
  "examples/reports/README.md",
94
+ "examples/reports/feedback-template.md",
92
95
  "examples/reports/report-gallery.json",
96
+ "examples/support/README.md",
97
+ "examples/support/triage-playbook.json",
93
98
  "examples/presets/README.md",
94
99
  "examples/tuning/README.md",
95
100
  "examples/tuning/framework-tuning-cookbook.json",
@@ -117,6 +122,9 @@ requireText("README.md", /examples\/tuning/, "framework tuning cookbook link");
117
122
  requireText("README.md", /adoption-smoke\.yml/, "adoption smoke CI link");
118
123
  requireText("README.md", /consumer-quickstart/, "consumer quickstart smoke link");
119
124
  requireText("README.md", /examples\/reports/, "report gallery link");
125
+ requireText("README.md", /feedback-template\.md/, "report gallery feedback template link");
126
+ requireText("README.md", /examples\/support/, "support triage playbook link");
127
+ requireText("README.md", /report gallery feedback/i, "report gallery feedback guidance");
120
128
  requireText("README.md", /License: PolyForm Noncommercial/, "the noncommercial license badge");
121
129
  requireText("docs/PRODUCTION_READINESS.md", /npm package/i, "npm package readiness");
122
130
  requireText("docs/PRODUCTION_READINESS.md", /GitHub Action/i, "GitHub Action readiness");
@@ -135,6 +143,8 @@ requireText("docs/PRODUCTION_READINESS.md", /framework:tuning:doctor/, "framewor
135
143
  requireText("docs/PRODUCTION_READINESS.md", /adoption-smoke\.yml/, "adoption smoke CI readiness");
136
144
  requireText("docs/PRODUCTION_READINESS.md", /consumer:quickstart:check/, "consumer quickstart smoke readiness");
137
145
  requireText("docs/PRODUCTION_READINESS.md", /reports:check/, "report gallery readiness");
146
+ requireText("docs/PRODUCTION_READINESS.md", /support:check/, "support triage readiness");
147
+ requireText("docs/PRODUCTION_READINESS.md", /examples\/support/, "support triage playbook readiness");
138
148
  requireText("docs/PRODUCTION_READINESS.md", /quiet-pass/, "quiet-pass fixture readiness");
139
149
  requireText("docs/CLI.md", /jester doctor --json/, "doctor JSON CLI docs");
140
150
  requireText("docs/CLI.md", /quiet-pass fixture/, "quiet-pass fixture CLI docs");
@@ -156,6 +166,13 @@ requireText("docs/MAINTAINER_TRIAGE.md", /tune <rule-id> --json/, "tune JSON tri
156
166
  requireText("docs/MAINTAINER_TRIAGE.md", /preset-review-cases\.json/, "fixture suite link");
157
167
  requireText("docs/MAINTAINER_TRIAGE.md", /expectedRuleIds/, "fixture expected rule guidance");
158
168
  requireText("docs/MAINTAINER_TRIAGE.md", /absentRuleIds/, "fixture absent rule guidance");
169
+ requireText("docs/MAINTAINER_TRIAGE.md", /feedback-template\.md/, "report gallery feedback template link");
170
+ requireText("docs/MAINTAINER_TRIAGE.md", /report_gallery_feedback\.yml/, "report gallery issue template link");
171
+ requireText("docs/MAINTAINER_TRIAGE.md", /examples\/support/, "support triage playbook link");
172
+ requireText("docs/MAINTAINER_TRIAGE.md", /docs-example/, "docs example triage outcome");
173
+ requireText("docs/MAINTAINER_TRIAGE.md", /fixture-backlog/, "fixture backlog triage outcome");
174
+ requireText("docs/MAINTAINER_TRIAGE.md", /rule-review-candidate/, "rule review triage outcome");
175
+ requireText("docs/MAINTAINER_TRIAGE.md", /support:check/, "support triage check guidance");
159
176
  requireText("examples/fixtures/README.md", /MAINTAINER_TRIAGE\.md/, "maintainer triage link");
160
177
  requireText("examples/fixtures/README.md", /Adding A Fixture From A Report/, "fixture report conversion guidance");
161
178
  requireText("examples/fixtures/README.md", /fixtures:check/, "fixture authoring check guidance");
@@ -170,10 +187,26 @@ requireText("examples/consumer-quickstart/README.md", /npm run consumer:quicksta
170
187
  requireText("examples/consumer-quickstart/package.json", /jester:summary/, "consumer quickstart summary script");
171
188
  requireText("examples/consumer-quickstart/package.json", /framework:tuning:doctor/, "consumer quickstart tuning doctor script");
172
189
  requireText("examples/reports/README.md", /report-gallery\.json/, "report gallery JSON link");
190
+ requireText("examples/reports/README.md", /feedback-template\.md/, "report gallery feedback template link");
191
+ requireText("examples/reports/README.md", /report_gallery_feedback\.yml/, "report gallery issue template link");
192
+ requireText("examples/reports/README.md", /examples\/support|Maintainer Triage Playbook/i, "support triage playbook link");
173
193
  requireText("examples/reports/README.md", /npm run reports:check/, "report gallery check command");
194
+ requireText("examples/reports/README.md", /npm run support:check/, "support triage check command");
174
195
  requireText("examples/reports/report-gallery.json", /fresh-install-doctor/, "fresh install doctor report");
175
196
  requireText("examples/reports/report-gallery.json", /destructive-command-summary/, "destructive command summary report");
176
197
  requireText("examples/reports/report-gallery.json", /blocked-command-review/, "blocked command review report");
198
+ requireText("examples/reports/feedback-template.md", /doctor --json/, "feedback template doctor diagnostics");
199
+ requireText("examples/reports/feedback-template.md", /summary --kind command "git reset --hard"/, "feedback template summary diagnostics");
200
+ requireText("examples/reports/feedback-template.md", /tune <rule-id> --json/, "feedback template tune diagnostics");
201
+ requireText("examples/reports/feedback-template.md", /Privacy Checklist/, "feedback template privacy checklist");
202
+ requireText("examples/reports/feedback-template.md", /SECURITY\.md/, "feedback template security redirect");
203
+ requireText("examples/support/README.md", /triage-playbook\.json/, "support triage playbook JSON link");
204
+ requireText("examples/support/README.md", /docs-example/, "support triage docs outcome");
205
+ requireText("examples/support/README.md", /fixture-backlog/, "support triage fixture outcome");
206
+ requireText("examples/support/README.md", /rule-review-candidate/, "support triage rule-review outcome");
207
+ requireText("examples/support/triage-playbook.json", /gallery-expected-block-docs/, "support triage docs example");
208
+ requireText("examples/support/triage-playbook.json", /false-positive-fixture-backlog/, "support triage fixture example");
209
+ requireText("examples/support/triage-playbook.json", /repeated-risky-domain-rule-review/, "support triage rule-review example");
177
210
  requireText("examples/tuning/README.md", /framework-tuning-cookbook\.json/, "framework tuning cookbook JSON link");
178
211
  requireText("examples/tuning/README.md", /framework:tuning:doctor/, "framework tuning doctor guidance");
179
212
  requireText("examples/tuning/README.md", /jester tune <rule-id> --json|jester tune [a-z0-9-]+ --json/, "framework tuning command guidance");
@@ -204,6 +237,10 @@ requireText("scripts/check-consumer-quickstart.mjs", /framework:tuning:doctor/,
204
237
  requireText("scripts/check-report-gallery.mjs", /report-gallery\.json/, "report gallery checker target");
205
238
  requireText("scripts/check-report-gallery.mjs", /memento-mori-jester@latest/, "report gallery registry verification option");
206
239
  requireText("scripts/check-report-gallery.mjs", /destructive-command-summary/, "report gallery summary guard");
240
+ requireText("scripts/check-support-triage.mjs", /report_gallery_feedback\.yml/, "support triage issue template guard");
241
+ requireText("scripts/check-support-triage.mjs", /feedback-template\.md/, "support triage feedback template guard");
242
+ requireText("scripts/check-support-triage.mjs", /triage-playbook\.json/, "support triage playbook guard");
243
+ requireText("scripts/check-support-triage.mjs", /unsafeContentPatterns/, "support triage unsafe content checks");
207
244
  requireText("package.json", /"fixtures:check": "node scripts\/check-fixtures\.mjs"/, "fixture authoring check script");
208
245
  requireText("package.json", /"fixtures:report": "node scripts\/report-fixtures\.mjs"/, "fixture coverage report script");
209
246
  requireText("package.json", /"framework:tuning:check": "node scripts\/check-framework-tuning\.mjs"/, "framework tuning cookbook check script");
@@ -211,6 +248,7 @@ requireText("package.json", /"framework:tuning:doctor": "node scripts\/doctor-fr
211
248
  requireText("package.json", /"ci:adoption:check": "node scripts\/check-ci-adoption\.mjs"/, "CI adoption check script");
212
249
  requireText("package.json", /"consumer:quickstart:check": "node scripts\/check-consumer-quickstart\.mjs"/, "consumer quickstart check script");
213
250
  requireText("package.json", /"reports:check": "node scripts\/check-report-gallery\.mjs"/, "report gallery check script");
251
+ requireText("package.json", /"support:check": "node scripts\/check-support-triage\.mjs"/, "support triage check script");
214
252
  requireText("package.json", /"promo:card": "node scripts\/render-social-card\.mjs"/, "social card render script");
215
253
  requireText("package.json", /"promo:card:check": "node scripts\/render-social-card\.mjs --check"/, "social card stale check script");
216
254
  requireText("package.json", /"promo:check": "node scripts\/check-promo-freshness\.mjs"/, "promo freshness check script");
@@ -222,6 +260,7 @@ requireText("package.json", /npm run framework:tuning:doctor/, "framework tuning
222
260
  requireText("package.json", /npm run ci:adoption:check/, "CI adoption check in npm test");
223
261
  requireText("package.json", /npm run consumer:quickstart:check/, "consumer quickstart check in npm test");
224
262
  requireText("package.json", /npm run reports:check/, "report gallery check in npm test");
263
+ requireText("package.json", /npm run support:check/, "support triage check in npm test");
225
264
  requireText("package.json", /npm run promo:check/, "promo freshness check in npm test");
226
265
  requireText("package.json", /npm run site:check/, "site check in npm test");
227
266
  requireText("scripts/check-promo-freshness.mjs", /--require-package-version/, "optional strict package-version promo check");
@@ -235,6 +274,13 @@ requireText(".github/ISSUE_TEMPLATE/bug_report.yml", /doctor --json/, "doctor JS
235
274
  requireText(".github/ISSUE_TEMPLATE/bug_report.yml", /SECURITY\.md|security policy/i, "security redirect");
236
275
  requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /jester tune <rule-id> --json/, "tune JSON prompt");
237
276
  requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /false-positive|noisy rule/i, "false-positive scope");
277
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /Jester version/, "false-positive version prompt");
278
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /doctor --json/, "false-positive doctor diagnostics");
279
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /doctor --json/, "doctor JSON report gallery prompt");
280
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /summary --kind command "git reset --hard"/, "summary report gallery prompt");
281
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized command summary/, "sanitized command report gallery prompt");
282
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized output summary/, "sanitized output report gallery prompt");
283
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /SECURITY\.md/, "report gallery security redirect");
238
284
  requireText(".github/ISSUE_TEMPLATE/feature_request.yml", /local-first and deterministic/, "project constraint prompt");
239
285
  requireText(".github/ISSUE_TEMPLATE/config.yml", /security\/advisories\/new/, "security contact link");
240
286
 
@@ -0,0 +1,234 @@
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
+ "examples/support/README.md",
29
+ "examples/support/triage-playbook.json",
30
+ "docs/MAINTAINER_TRIAGE.md",
31
+ "docs/PRODUCTION_READINESS.md",
32
+ "README.md",
33
+ "SECURITY.md"
34
+ ];
35
+
36
+ for (const path of supportFiles) {
37
+ requireFile(path);
38
+ }
39
+
40
+ for (const path of supportFiles.filter((path) => existsSync(join(root, path)))) {
41
+ const content = read(path);
42
+ for (const unsafe of unsafeContentPatterns) {
43
+ if (unsafe.pattern.test(content)) {
44
+ failures.push(`${path} appears to contain ${unsafe.name}; support examples must stay public-safe and redacted.`);
45
+ }
46
+ }
47
+ }
48
+
49
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Report gallery feedback/, "a report gallery feedback template name");
50
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /fresh-install-doctor/, "the fresh install report option");
51
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /destructive-command-summary/, "the destructive summary report option");
52
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /blocked-command-review/, "the blocked command report option");
53
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /doctor --json/, "doctor JSON diagnostics");
54
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /summary --kind command "git reset --hard"/, "the report-gallery summary smoke");
55
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized command summary/, "sanitized command prompt");
56
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /Sanitized output summary/, "sanitized output prompt");
57
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /SECURITY\.md/, "security redirect");
58
+ requireText(".github/ISSUE_TEMPLATE/report_gallery_feedback.yml", /removed secrets, tokens, private code, private paths, customer data, and full CI logs/, "privacy checkbox");
59
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /Jester version/, "false-positive version prompt");
60
+ requireText(".github/ISSUE_TEMPLATE/false_positive.yml", /doctor --json/, "false-positive doctor diagnostics");
61
+
62
+ requireText("examples/reports/feedback-template.md", /Report Gallery Feedback Template/, "feedback template heading");
63
+ requireText("examples/reports/feedback-template.md", /fresh-install-doctor/, "fresh install report id");
64
+ requireText("examples/reports/feedback-template.md", /destructive-command-summary/, "destructive summary report id");
65
+ requireText("examples/reports/feedback-template.md", /blocked-command-review/, "blocked command report id");
66
+ requireText("examples/reports/feedback-template.md", /doctor --json/, "doctor JSON command");
67
+ requireText("examples/reports/feedback-template.md", /summary --kind command "git reset --hard"/, "summary command");
68
+ requireText("examples/reports/feedback-template.md", /tune <rule-id> --json/, "tune JSON command");
69
+ requireText("examples/reports/feedback-template.md", /Privacy Checklist/, "privacy checklist");
70
+ requireText("examples/reports/feedback-template.md", /SECURITY\.md/, "security redirect");
71
+ requireText("examples/reports/feedback-template.md", /npm run support:check/, "support checker command");
72
+
73
+ requireText("examples/reports/README.md", /feedback-template\.md/, "feedback template link");
74
+ requireText("examples/reports/README.md", /report_gallery_feedback\.yml/, "GitHub issue template link");
75
+ requireText("examples/reports/README.md", /npm run support:check/, "support checker command");
76
+ requireText("examples/reports/README.md", /examples\/support|Maintainer Triage Playbook/i, "maintainer triage playbook link");
77
+
78
+ requireText("examples/support/README.md", /Maintainer Triage Playbook/, "maintainer playbook heading");
79
+ requireText("examples/support/README.md", /triage-playbook\.json/, "maintainer playbook JSON link");
80
+ requireText("examples/support/README.md", /gallery-expected-block-docs/, "docs example playbook case");
81
+ requireText("examples/support/README.md", /false-positive-fixture-backlog/, "fixture backlog playbook case");
82
+ requireText("examples/support/README.md", /repeated-risky-domain-rule-review/, "rule review playbook case");
83
+ requireText("examples/support/README.md", /doctor --json/, "doctor JSON playbook prompt");
84
+ requireText("examples/support/README.md", /tune <rule-id> --json/, "tune JSON playbook prompt");
85
+ requireText("examples/support/README.md", /docs-example/, "docs outcome");
86
+ requireText("examples/support/README.md", /fixture-backlog/, "fixture backlog outcome");
87
+ requireText("examples/support/README.md", /rule-review-candidate/, "rule review outcome");
88
+ requireText("examples/support/README.md", /SECURITY\.md/, "security redirect");
89
+ requireText("examples/support/README.md", /npm run support:check/, "support checker command");
90
+
91
+ requireText("docs/MAINTAINER_TRIAGE.md", /feedback-template\.md/, "feedback template triage link");
92
+ requireText("docs/MAINTAINER_TRIAGE.md", /report_gallery_feedback\.yml/, "report gallery issue template triage link");
93
+ requireText("docs/MAINTAINER_TRIAGE.md", /examples\/support/, "maintainer playbook triage link");
94
+ requireText("docs/MAINTAINER_TRIAGE.md", /docs-example/, "docs example triage outcome");
95
+ requireText("docs/MAINTAINER_TRIAGE.md", /fixture-backlog/, "fixture backlog triage outcome");
96
+ requireText("docs/MAINTAINER_TRIAGE.md", /rule-review-candidate/, "rule review triage outcome");
97
+ requireText("docs/MAINTAINER_TRIAGE.md", /npm(?:\.cmd)? run support:check/, "support checker triage command");
98
+ requireText("docs/PRODUCTION_READINESS.md", /support:check/, "support checker readiness");
99
+ requireText("README.md", /feedback-template\.md/, "feedback template README link");
100
+ requireText("README.md", /examples\/support/, "maintainer triage playbook README link");
101
+ requireText("README.md", /report gallery feedback/i, "report gallery feedback guidance");
102
+
103
+ requireText("package.json", /"support:check": "node scripts\/check-support-triage\.mjs"/, "support checker script");
104
+ requireText("package.json", /npm run support:check/, "support checker in npm test");
105
+
106
+ checkTriagePlaybook();
107
+
108
+ if (failures.length > 0) {
109
+ console.error("Support triage check failed:");
110
+ for (const failure of failures) {
111
+ console.error(`- ${failure}`);
112
+ }
113
+ process.exit(1);
114
+ }
115
+
116
+ console.log("Support triage check passed.");
117
+
118
+ function read(path) {
119
+ return readFileSync(join(root, path), "utf8");
120
+ }
121
+
122
+ function readJson(path) {
123
+ try {
124
+ return JSON.parse(read(path));
125
+ } catch (error) {
126
+ failures.push(`${path} should be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
127
+ return null;
128
+ }
129
+ }
130
+
131
+ function requireFile(path) {
132
+ if (!existsSync(join(root, path))) {
133
+ failures.push(`${path} is missing.`);
134
+ }
135
+ }
136
+
137
+ function requireText(path, pattern, description) {
138
+ if (!existsSync(join(root, path))) {
139
+ failures.push(`${path} is missing; cannot check for ${description}.`);
140
+ return;
141
+ }
142
+
143
+ const content = read(path);
144
+ if (!pattern.test(content)) {
145
+ failures.push(`${path} should include ${description}.`);
146
+ }
147
+ }
148
+
149
+ function checkTriagePlaybook() {
150
+ const path = "examples/support/triage-playbook.json";
151
+ const playbook = readJson(path);
152
+ if (!playbook) {
153
+ return;
154
+ }
155
+
156
+ if (!Array.isArray(playbook) || playbook.length !== 3) {
157
+ failures.push(`${path} should contain exactly three maintainer triage examples.`);
158
+ return;
159
+ }
160
+
161
+ const expectedIds = [
162
+ "gallery-expected-block-docs",
163
+ "false-positive-fixture-backlog",
164
+ "repeated-risky-domain-rule-review"
165
+ ];
166
+ const expectedOutcomes = ["docs-example", "fixture-backlog", "rule-review-candidate"];
167
+ const expectedSources = ["report-gallery-feedback", "false-positive"];
168
+ const seenIds = new Set();
169
+
170
+ for (const [index, entry] of playbook.entries()) {
171
+ const expectedId = expectedIds[index];
172
+ if (entry?.id !== expectedId) {
173
+ failures.push(`${path} entry ${index + 1} should have id ${expectedId}.`);
174
+ continue;
175
+ }
176
+
177
+ if (seenIds.has(entry.id)) {
178
+ failures.push(`${path} has duplicate id ${entry.id}.`);
179
+ }
180
+ seenIds.add(entry.id);
181
+
182
+ if (!expectedSources.includes(entry.source)) {
183
+ failures.push(`${entry.id}.source should be one of ${expectedSources.join(", ")}.`);
184
+ }
185
+
186
+ if (typeof entry.nearestReportExample !== "string" || entry.nearestReportExample.length < 4) {
187
+ failures.push(`${entry.id}.nearestReportExample should be a useful string.`);
188
+ }
189
+
190
+ if (typeof entry.sanitizedReport?.version !== "string") {
191
+ failures.push(`${entry.id}.sanitizedReport.version should be present.`);
192
+ }
193
+
194
+ if (!["command", "plan", "diff", "final"].includes(entry.sanitizedReport?.kind)) {
195
+ failures.push(`${entry.id}.sanitizedReport.kind should be a review kind.`);
196
+ }
197
+
198
+ if (typeof entry.sanitizedReport?.command !== "string" || !entry.sanitizedReport.command.includes("jester")) {
199
+ failures.push(`${entry.id}.sanitizedReport.command should include a jester command.`);
200
+ }
201
+
202
+ if (!Array.isArray(entry.sanitizedReport?.observed) || entry.sanitizedReport.observed.length < 2) {
203
+ failures.push(`${entry.id}.sanitizedReport.observed should include stable output fragments.`);
204
+ }
205
+
206
+ if (typeof entry.sanitizedReport?.question !== "string" || entry.sanitizedReport.question.length < 20) {
207
+ failures.push(`${entry.id}.sanitizedReport.question should explain the adopter surprise.`);
208
+ }
209
+
210
+ if (typeof entry.firstResponse !== "string" || !entry.firstResponse.includes("doctor --json")) {
211
+ failures.push(`${entry.id}.firstResponse should ask for or mention redacted doctor --json diagnostics.`);
212
+ }
213
+
214
+ if (!Array.isArray(entry.classification?.labels) || entry.classification.labels.length === 0) {
215
+ failures.push(`${entry.id}.classification.labels should be a non-empty array.`);
216
+ }
217
+
218
+ if (typeof entry.classification?.decision !== "string" || entry.classification.decision.length < 8) {
219
+ failures.push(`${entry.id}.classification.decision should be present.`);
220
+ }
221
+
222
+ if (!Array.isArray(entry.maintainerChecks) || !entry.maintainerChecks.includes("npm run support:check")) {
223
+ failures.push(`${entry.id}.maintainerChecks should include npm run support:check.`);
224
+ }
225
+
226
+ if (entry.followUpOutcome?.type !== expectedOutcomes[index]) {
227
+ failures.push(`${entry.id}.followUpOutcome.type should be ${expectedOutcomes[index]}.`);
228
+ }
229
+
230
+ if (typeof entry.followUpOutcome?.action !== "string" || entry.followUpOutcome.action.length < 30) {
231
+ failures.push(`${entry.id}.followUpOutcome.action should describe the maintainer action.`);
232
+ }
233
+ }
234
+ }