memento-mori-jester 0.1.79 → 0.1.80
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 +6 -0
- package/README.md +1 -0
- package/ROADMAP.md +2 -1
- package/docs/PRODUCTION_READINESS.md +2 -2
- package/docs/RELEASE.md +1 -0
- package/docs/RELEASE_NOTES_v0.1.80.md +40 -0
- package/package.json +3 -1
- package/scripts/check-production-readiness.mjs +4 -0
- package/scripts/check-promo-freshness.mjs +6 -0
- package/scripts/render-social-card.mjs +105 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to Memento Mori Jester are tracked here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.1.80
|
|
8
|
+
|
|
9
|
+
- Added a deterministic `promo/share-kit/social-card.svg` for GitHub, X, and project-update link previews.
|
|
10
|
+
- Added `npm run promo:card` and `npm run promo:card:check` to regenerate or verify the social card.
|
|
11
|
+
- Extended promo freshness checks and docs so the social card stays part of the maintainer release flow.
|
|
12
|
+
|
|
7
13
|
## 0.1.79
|
|
8
14
|
|
|
9
15
|
- Added `npm run promo:check` to verify the current repo-local promo video, stills, docs, and fixture evidence numbers stay aligned.
|
package/README.md
CHANGED
|
@@ -503,6 +503,7 @@ Use the false-positive template for noisy cautions or blocks. Include `jester su
|
|
|
503
503
|
Maintainers can use [docs/MAINTAINER_TRIAGE.md](docs/MAINTAINER_TRIAGE.md) to turn useful false-positive reports into redacted fixtures.
|
|
504
504
|
Run `npm run fixtures:check` before merging fixture changes; it catches duplicate IDs, missing rule metadata, weak descriptions, unsafe-looking content, and duplicate content.
|
|
505
505
|
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.
|
|
506
|
+
Run `npm run promo:card` to regenerate the repo-local social preview card after changing its copy or design.
|
|
506
507
|
Run `npm run promo:check` after editing promo assets; it checks the current demo video, stills, docs, and fixture evidence numbers stay in sync.
|
|
507
508
|
|
|
508
509
|
For vulnerabilities, private code exposure, or credential-handling concerns, follow [SECURITY.md](SECURITY.md) instead of opening a public issue with sensitive details.
|
package/ROADMAP.md
CHANGED
|
@@ -6,6 +6,7 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
|
|
|
6
6
|
|
|
7
7
|
## Recently Shipped
|
|
8
8
|
|
|
9
|
+
- Social preview card in v0.1.80, adding a deterministic 1200x630 promo card plus generation and freshness checks.
|
|
9
10
|
- Promo freshness check in v0.1.79, verifying the current demo video, share-kit stills, docs, and fixture evidence numbers before public posting.
|
|
10
11
|
- Fresh demo render in v0.1.78, updating the repo-local X video and share-kit stills to current version and fixture totals.
|
|
11
12
|
- Promo/share kit in v0.1.77, adding X post copy, a short demo script, a posting checklist, and still images from the existing demo video.
|
|
@@ -70,7 +71,7 @@ Memento Mori Jester is usable today as a CLI, MCP server, GitHub Action, and git
|
|
|
70
71
|
|
|
71
72
|
- Collect real-world reports for the next lowest-count preset slices now highlighted by `fixtures:report`.
|
|
72
73
|
- Add more framework-specific false-positive examples from real reports so tuning guidance keeps getting sharper.
|
|
73
|
-
- Add a
|
|
74
|
+
- Add a small web landing page that reuses the existing demo, social card, and start command.
|
|
74
75
|
|
|
75
76
|
## Quality And Safety
|
|
76
77
|
|
|
@@ -9,7 +9,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
|
|
|
9
9
|
- GitHub Releases and npm publishing are automated from annotated `v*` tags through GitHub Actions trusted publishing.
|
|
10
10
|
- CI runs tests and a package dry run on every push to `main` and pull request.
|
|
11
11
|
- The local playground, GitHub Action, MCP setup snippets, preset examples, fixtures, and release notes ship in the npm package.
|
|
12
|
-
- Repo-local promo assets stay outside the npm package, but `npm run promo:check` keeps the current demo video, stills, docs, and fixture evidence numbers aligned.
|
|
12
|
+
- Repo-local promo assets stay outside the npm package, but `npm run promo:check` keeps the current demo video, stills, social card, docs, and fixture evidence numbers aligned.
|
|
13
13
|
|
|
14
14
|
## npm Package
|
|
15
15
|
|
|
@@ -55,7 +55,7 @@ This checklist defines what "production grade" means for Memento Mori Jester rig
|
|
|
55
55
|
- `docs/MAINTAINER_TRIAGE.md` explains how to turn useful false-positive reports into fixture coverage before changing rule logic.
|
|
56
56
|
- `npm run fixtures:check` validates fixture IDs, metadata, unsafe-looking content, duplicate content, and explicit expected/absent rule intent.
|
|
57
57
|
- `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.
|
|
58
|
-
- `npm run promo:check` verifies current repo-local promo assets against the current fixture evidence before maintainers post or refresh the demo.
|
|
58
|
+
- `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.
|
|
59
59
|
- npm publish has a manual workflow fallback, but the normal release path is tag-driven trusted publishing.
|
|
60
60
|
|
|
61
61
|
## Static Guard
|
package/docs/RELEASE.md
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Memento Mori Jester v0.1.80
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
This release adds a deterministic social preview card for GitHub, X, and project-update links. It keeps the promo work local and reviewable while making shared links look intentional.
|
|
6
|
+
|
|
7
|
+
## What Changed
|
|
8
|
+
|
|
9
|
+
- Added `promo/share-kit/social-card.svg`.
|
|
10
|
+
- Added `scripts/render-social-card.mjs`.
|
|
11
|
+
- Added `npm run promo:card` and `npm run promo:card:check`.
|
|
12
|
+
- Extended `npm run promo:check` to verify the social card exists, has 1200x630 dimensions, includes the product name, and includes the `npx` start command.
|
|
13
|
+
- Updated promo docs, release docs, production-readiness docs, roadmap, changelog, and release notes.
|
|
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, or verdict behavior changes.
|
|
21
|
+
- No GitHub Action behavior changes.
|
|
22
|
+
- `promo/` remains outside the npm package `files` list.
|
|
23
|
+
|
|
24
|
+
## Release Validation
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
npm.cmd test
|
|
28
|
+
npm.cmd run demo:svg:check
|
|
29
|
+
npm.cmd run promo:card:check
|
|
30
|
+
npm.cmd run promo:check
|
|
31
|
+
npm.cmd run pack:dry
|
|
32
|
+
git diff --check
|
|
33
|
+
git diff | node .\dist\cli.js diff --fail-on block --subject "v0.1.80 social preview card"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Expected:
|
|
37
|
+
|
|
38
|
+
- `promo/share-kit/social-card.svg` is deterministic and current,
|
|
39
|
+
- default `promo:check` includes social-card validation,
|
|
40
|
+
- GitHub Release and npm Publish complete from the `v0.1.80` tag.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memento-mori-jester",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.80",
|
|
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": {
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
"demo:svg:check": "node scripts/render-demo-svg.mjs --check",
|
|
47
47
|
"fixtures:check": "node scripts/check-fixtures.mjs",
|
|
48
48
|
"fixtures:report": "node scripts/report-fixtures.mjs",
|
|
49
|
+
"promo:card": "node scripts/render-social-card.mjs",
|
|
50
|
+
"promo:card:check": "node scripts/render-social-card.mjs --check",
|
|
49
51
|
"promo:check": "node scripts/check-promo-freshness.mjs",
|
|
50
52
|
"production:check": "node scripts/check-production-readiness.mjs",
|
|
51
53
|
"pack:dry": "npm pack --dry-run",
|
|
@@ -65,6 +65,7 @@ for (const path of [
|
|
|
65
65
|
`docs/RELEASE_NOTES_${tag}.md`,
|
|
66
66
|
"action.yml",
|
|
67
67
|
"scripts/check-promo-freshness.mjs",
|
|
68
|
+
"scripts/render-social-card.mjs",
|
|
68
69
|
"scripts/check-fixtures.mjs",
|
|
69
70
|
"scripts/report-fixtures.mjs",
|
|
70
71
|
".github/ISSUE_TEMPLATE/bug_report.yml",
|
|
@@ -133,11 +134,14 @@ requireText("scripts/report-fixtures.mjs", /--markdown/, "Markdown fixture repor
|
|
|
133
134
|
forbidText("scripts/report-fixtures.mjs", /src\/config\.ts|src\/types\.ts/, "source-only fixture report dependencies");
|
|
134
135
|
requireText("package.json", /"fixtures:check": "node scripts\/check-fixtures\.mjs"/, "fixture authoring check script");
|
|
135
136
|
requireText("package.json", /"fixtures:report": "node scripts\/report-fixtures\.mjs"/, "fixture coverage report script");
|
|
137
|
+
requireText("package.json", /"promo:card": "node scripts\/render-social-card\.mjs"/, "social card render script");
|
|
138
|
+
requireText("package.json", /"promo:card:check": "node scripts\/render-social-card\.mjs --check"/, "social card stale check script");
|
|
136
139
|
requireText("package.json", /"promo:check": "node scripts\/check-promo-freshness\.mjs"/, "promo freshness check script");
|
|
137
140
|
requireText("package.json", /npm run fixtures:check/, "fixture authoring check in npm test");
|
|
138
141
|
requireText("package.json", /npm run fixtures:report/, "fixture coverage report in npm test");
|
|
139
142
|
requireText("package.json", /npm run promo:check/, "promo freshness check in npm test");
|
|
140
143
|
requireText("scripts/check-promo-freshness.mjs", /--require-package-version/, "optional strict package-version promo check");
|
|
144
|
+
requireText("scripts/check-promo-freshness.mjs", /social-card\.svg/, "social-card freshness check");
|
|
141
145
|
requireText("SECURITY.md", /doctor --json/, "doctor JSON redaction guidance");
|
|
142
146
|
requireText("SECURITY.md", /security\/advisories\/new/, "private vulnerability report link");
|
|
143
147
|
requireText(".github/ISSUE_TEMPLATE/bug_report.yml", /doctor --json/, "doctor JSON support prompt");
|
|
@@ -117,6 +117,7 @@ const demoDir = `promo/${demoId}`;
|
|
|
117
117
|
const demoVideoPath = linkedTarget ? `promo/${linkedTarget}` : "";
|
|
118
118
|
const fixtureTotal = Array.isArray(fixtures) ? fixtures.length : 0;
|
|
119
119
|
const riskyEvidence = loadRiskyDomainEvidence();
|
|
120
|
+
const socialCardPath = "promo/share-kit/social-card.svg";
|
|
120
121
|
|
|
121
122
|
if (requirePackageVersion && packageJson.version !== promoVersion) {
|
|
122
123
|
failures.push(`Current promo version v${promoVersion} should match package.json ${packageJson.version} when --require-package-version is used.`);
|
|
@@ -133,6 +134,11 @@ if (promoVersion !== "unknown") {
|
|
|
133
134
|
for (const still of ["01-opener.jpg", "02-command-block.jpg", "03-tuning-evidence.jpg", "04-try-it.jpg"]) {
|
|
134
135
|
requireFile(`promo/share-kit/stills/${still}`, `share-kit still ${still}`, 50_000);
|
|
135
136
|
}
|
|
137
|
+
requireFile(socialCardPath, "social preview card", 2_000);
|
|
138
|
+
requireText(socialCardPath, /width="1200" height="630"/, "1200x630 social-card dimensions");
|
|
139
|
+
requireText(socialCardPath, /Memento Mori Jester/, "product name");
|
|
140
|
+
requireText(socialCardPath, /npx -y memento-mori-jester@latest start/, "start command");
|
|
141
|
+
requireText("promo/share-kit/README.md", /social-card\.svg/, "social-card asset row");
|
|
136
142
|
|
|
137
143
|
try {
|
|
138
144
|
const demoPackage = readJson(`${demoDir}/package.json`);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
6
|
+
const targetPath = resolve(root, "promo/share-kit/social-card.svg");
|
|
7
|
+
const mode = process.argv.includes("--check") ? "check" : "write";
|
|
8
|
+
|
|
9
|
+
const width = 1200;
|
|
10
|
+
const height = 630;
|
|
11
|
+
|
|
12
|
+
const copy = {
|
|
13
|
+
title: "Memento Mori Jester",
|
|
14
|
+
eyebrow: "For AI agents with ambition",
|
|
15
|
+
headline: ["A local court jester", "for AI coding agents."],
|
|
16
|
+
detail: ["Reviews commands, plans, diffs, and final answers", "before the agent gets too pleased with itself."],
|
|
17
|
+
command: "npx -y memento-mori-jester@latest start",
|
|
18
|
+
footer: "Codex | Claude Code | MCP | hooks | CI"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function escapeXml(value) {
|
|
22
|
+
return value
|
|
23
|
+
.replaceAll("&", "&")
|
|
24
|
+
.replaceAll("<", "<")
|
|
25
|
+
.replaceAll(">", ">")
|
|
26
|
+
.replaceAll("\"", """);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function text(value) {
|
|
30
|
+
return escapeXml(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function renderSvg() {
|
|
34
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-labelledby="title desc">
|
|
35
|
+
<title id="title">${text(copy.title)} social preview card</title>
|
|
36
|
+
<desc id="desc">${text(copy.detail.join(" "))}</desc>
|
|
37
|
+
<defs>
|
|
38
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
39
|
+
<stop offset="0%" stop-color="#11100e"/>
|
|
40
|
+
<stop offset="58%" stop-color="#171410"/>
|
|
41
|
+
<stop offset="100%" stop-color="#211b14"/>
|
|
42
|
+
</linearGradient>
|
|
43
|
+
<radialGradient id="heat" cx="78%" cy="16%" r="70%">
|
|
44
|
+
<stop offset="0%" stop-color="#d7a642" stop-opacity="0.36"/>
|
|
45
|
+
<stop offset="42%" stop-color="#d64b3f" stop-opacity="0.12"/>
|
|
46
|
+
<stop offset="100%" stop-color="#11100e" stop-opacity="0"/>
|
|
47
|
+
</radialGradient>
|
|
48
|
+
<filter id="soft-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
49
|
+
<feDropShadow dx="0" dy="24" stdDeviation="24" flood-color="#050403" flood-opacity="0.38"/>
|
|
50
|
+
</filter>
|
|
51
|
+
</defs>
|
|
52
|
+
<rect width="${width}" height="${height}" fill="url(#bg)"/>
|
|
53
|
+
<rect width="${width}" height="${height}" fill="url(#heat)"/>
|
|
54
|
+
<g opacity="0.09">
|
|
55
|
+
<path d="M0 90H1200M0 180H1200M0 270H1200M0 360H1200M0 450H1200M0 540H1200" stroke="#f2eadc" stroke-width="1"/>
|
|
56
|
+
<path d="M100 0V630M200 0V630M300 0V630M400 0V630M500 0V630M600 0V630M700 0V630M800 0V630M900 0V630M1000 0V630M1100 0V630" stroke="#f2eadc" stroke-width="1"/>
|
|
57
|
+
</g>
|
|
58
|
+
<g transform="translate(875 74)" opacity="0.55">
|
|
59
|
+
<circle cx="150" cy="150" r="145" fill="none" stroke="#d7a642" stroke-width="3" opacity="0.55"/>
|
|
60
|
+
<circle cx="150" cy="150" r="95" fill="none" stroke="#d64b3f" stroke-width="3" opacity="0.36"/>
|
|
61
|
+
<circle cx="150" cy="150" r="48" fill="none" stroke="#f2eadc" stroke-width="3" opacity="0.28"/>
|
|
62
|
+
</g>
|
|
63
|
+
<text x="-36" y="612" fill="#f2eadc" opacity="0.055" font-family="Georgia, serif" font-size="132" font-weight="900">remember you are shipping code</text>
|
|
64
|
+
<g transform="translate(74 66)">
|
|
65
|
+
<g transform="translate(0 0)">
|
|
66
|
+
<circle cx="27" cy="27" r="27" fill="#f2eadc"/>
|
|
67
|
+
<path d="M27 0A27 27 0 0 1 54 27H27Z" fill="#d64b3f"/>
|
|
68
|
+
<path d="M27 27H54A27 27 0 0 1 13 50Z" fill="#d7a642"/>
|
|
69
|
+
<path d="M27 0V27H0A27 27 0 0 1 27 0Z" fill="#f2eadc"/>
|
|
70
|
+
</g>
|
|
71
|
+
<text x="76" y="36" fill="#f2eadc" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="25" font-weight="800" letter-spacing="4">${text(copy.title.toUpperCase())}</text>
|
|
72
|
+
</g>
|
|
73
|
+
<g transform="translate(76 166)">
|
|
74
|
+
<text x="0" y="0" fill="#d7a642" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="22" font-weight="700" letter-spacing="3">${text(copy.eyebrow.toUpperCase())}</text>
|
|
75
|
+
<text x="0" y="76" fill="#f2eadc" font-family="Georgia, serif" font-size="72" font-weight="900">${text(copy.headline[0])}</text>
|
|
76
|
+
<text x="0" y="146" fill="#f2eadc" font-family="Georgia, serif" font-size="72" font-weight="900">${text(copy.headline[1])}</text>
|
|
77
|
+
<text x="0" y="202" fill="#d8cbb5" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="25">${text(copy.detail[0])}</text>
|
|
78
|
+
<text x="0" y="238" fill="#d8cbb5" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="25">${text(copy.detail[1])}</text>
|
|
79
|
+
</g>
|
|
80
|
+
<g transform="translate(76 432)" filter="url(#soft-shadow)">
|
|
81
|
+
<rect x="0" y="0" width="812" height="88" rx="18" fill="#1b1814" stroke="#d7a642" stroke-opacity="0.48" stroke-width="2"/>
|
|
82
|
+
<text x="32" y="55" fill="#d7a642" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="28">$</text>
|
|
83
|
+
<text x="64" y="55" fill="#f2eadc" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="28" font-weight="700">${text(copy.command)}</text>
|
|
84
|
+
</g>
|
|
85
|
+
<g transform="translate(76 546)">
|
|
86
|
+
<rect x="0" y="-28" width="650" height="48" rx="24" fill="#d64b3f"/>
|
|
87
|
+
<text x="28" y="3" fill="#fff3eb" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="18" font-weight="800" letter-spacing="1.5">${text(copy.footer.toUpperCase())}</text>
|
|
88
|
+
</g>
|
|
89
|
+
</svg>
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const svg = renderSvg();
|
|
94
|
+
|
|
95
|
+
if (mode === "check") {
|
|
96
|
+
const existing = await readFile(targetPath, "utf8");
|
|
97
|
+
if (existing !== svg) {
|
|
98
|
+
process.stderr.write("promo/share-kit/social-card.svg is stale. Run `npm run promo:card`.\n");
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
103
|
+
await writeFile(targetPath, svg, "utf8");
|
|
104
|
+
process.stdout.write(`Wrote ${targetPath}\n`);
|
|
105
|
+
}
|