memento-mori-jester 0.1.3

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.
@@ -0,0 +1,21 @@
1
+ name: Jester Review
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+
7
+ jobs:
8
+ jester:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - name: Checkout
13
+ uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Review pull request diff
18
+ uses: Martin123132/Memento-Mori@main
19
+ with:
20
+ fail-on: block
21
+ subject: pull request diff
@@ -0,0 +1,28 @@
1
+ {
2
+ "tone": "court_jester",
3
+ "intensity": 3,
4
+ "riskTolerance": "medium",
5
+ "hookFailOn": "block",
6
+ "blockedCommands": [
7
+ "git reset --hard",
8
+ "git clean -fd"
9
+ ],
10
+ "sensitiveDomains": [
11
+ "auth",
12
+ "billing",
13
+ "payments",
14
+ "production",
15
+ "customer data"
16
+ ],
17
+ "customRules": [
18
+ {
19
+ "id": "no-force-push-main",
20
+ "pattern": "git\\s+push\\s+--force(?:-with-lease)?\\s+origin\\s+main",
21
+ "severity": 5,
22
+ "title": "Force-push to main",
23
+ "detail": "This project treats force-pushing main as a stop-and-think event.",
24
+ "suggestedCheck": "Create a branch or use --force-with-lease only after confirming the protected branch policy.",
25
+ "kinds": ["command", "plan"]
26
+ }
27
+ ]
28
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "memento-mori-jester",
3
+ "version": "0.1.3",
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
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Martin123132/Memento-Mori.git"
9
+ },
10
+ "homepage": "https://github.com/Martin123132/Memento-Mori#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/Martin123132/Memento-Mori/issues"
13
+ },
14
+ "main": "./dist/core.js",
15
+ "types": "./dist/core.d.ts",
16
+ "bin": {
17
+ "jester": "dist/cli.js",
18
+ "memento-mori-jester": "dist/cli.js",
19
+ "memento-mori-jester-mcp": "dist/server.js"
20
+ },
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/core.d.ts",
24
+ "import": "./dist/core.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "!dist/**/*.test.*",
30
+ "docs",
31
+ "examples",
32
+ "scripts",
33
+ "LICENSE",
34
+ "README.md"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsc -p tsconfig.json",
38
+ "start": "node dist/server.js",
39
+ "start:mcp": "node dist/server.js",
40
+ "test": "npm run build && node scripts/run-tests.mjs",
41
+ "doctor": "node dist/cli.js doctor",
42
+ "pack:dry": "npm pack --dry-run",
43
+ "prepare": "npm run build",
44
+ "prepublishOnly": "npm test && npm run pack:dry"
45
+ },
46
+ "keywords": [
47
+ "mcp",
48
+ "ai-agent",
49
+ "coding-agent",
50
+ "safety",
51
+ "cli",
52
+ "code-review",
53
+ "memento-mori",
54
+ "court-jester"
55
+ ],
56
+ "publishConfig": {
57
+ "access": "public"
58
+ },
59
+ "dependencies": {
60
+ "@modelcontextprotocol/sdk": "^1.29.0",
61
+ "zod": "^4.1.12"
62
+ },
63
+ "devDependencies": {
64
+ "@types/node": "^24.10.1",
65
+ "typescript": "^5.9.3"
66
+ },
67
+ "engines": {
68
+ "node": ">=20"
69
+ },
70
+ "license": "MIT"
71
+ }
@@ -0,0 +1,30 @@
1
+ param(
2
+ [string]$PackageSpec = "memento-mori-jester@latest",
3
+ [ValidateSet("npx", "global")]
4
+ [string]$Mode = "npx"
5
+ )
6
+
7
+ $ErrorActionPreference = "Stop"
8
+
9
+ function Assert-Command($Name, $InstallHint) {
10
+ if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
11
+ throw "$Name was not found. $InstallHint"
12
+ }
13
+ }
14
+
15
+ Assert-Command "node" "Install Node.js 20 or newer, then run this script again."
16
+ Assert-Command "npm.cmd" "Install npm with Node.js, then run this script again."
17
+
18
+ $nodeMajor = [int](& node -p "process.versions.node.split('.')[0]")
19
+ if ($nodeMajor -lt 20) {
20
+ throw "Node.js 20 or newer is required. Found: $(& node --version)"
21
+ }
22
+
23
+ if ($Mode -eq "global") {
24
+ & npm.cmd install -g $PackageSpec
25
+ & jester doctor
26
+ & jester mcp-config --mode global
27
+ } else {
28
+ & npx -y $PackageSpec doctor
29
+ & npx -y $PackageSpec mcp-config --mode npx --package $PackageSpec
30
+ }
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ PACKAGE_SPEC="${PACKAGE_SPEC:-memento-mori-jester@latest}"
5
+ MODE="${MODE:-npx}"
6
+
7
+ if ! command -v node >/dev/null 2>&1; then
8
+ echo "node was not found. Install Node.js 20 or newer, then run this script again." >&2
9
+ exit 1
10
+ fi
11
+
12
+ if ! command -v npm >/dev/null 2>&1; then
13
+ echo "npm was not found. Install npm with Node.js, then run this script again." >&2
14
+ exit 1
15
+ fi
16
+
17
+ NODE_MAJOR="$(node -p "process.versions.node.split('.')[0]")"
18
+ if [ "$NODE_MAJOR" -lt 20 ]; then
19
+ echo "Node.js 20 or newer is required. Found: $(node --version)" >&2
20
+ exit 1
21
+ fi
22
+
23
+ if [ "$MODE" = "global" ]; then
24
+ npm install -g "$PACKAGE_SPEC"
25
+ jester doctor
26
+ jester mcp-config --mode global
27
+ else
28
+ npx -y "$PACKAGE_SPEC" doctor
29
+ npx -y "$PACKAGE_SPEC" mcp-config --mode npx --package "$PACKAGE_SPEC"
30
+ fi
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { readdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ const testFiles = await findTestFiles("dist");
7
+
8
+ if (testFiles.length === 0) {
9
+ console.error("No compiled test files found in dist.");
10
+ process.exit(1);
11
+ }
12
+
13
+ const result = spawnSync(process.execPath, ["--test", ...testFiles], {
14
+ stdio: "inherit"
15
+ });
16
+
17
+ process.exit(result.status ?? 1);
18
+
19
+ async function findTestFiles(dir) {
20
+ const entries = await readdir(dir, { withFileTypes: true });
21
+ const files = await Promise.all(entries.map(async (entry) => {
22
+ const path = join(dir, entry.name);
23
+
24
+ if (entry.isDirectory()) {
25
+ return findTestFiles(path);
26
+ }
27
+
28
+ return entry.isFile() && entry.name.endsWith(".test.js") ? [path] : [];
29
+ }));
30
+
31
+ return files.flat().sort();
32
+ }