@pukujan/create-modular-monolith 2.1.0 → 2.2.1
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/LICENSE +50 -0
- package/README.md +146 -61
- package/package.json +3 -2
- package/template/.github/workflows/ci.yml +44 -0
- package/template/LICENSE +11 -0
- package/template/NOTICE +13 -0
- package/template/README.md +98 -18
- package/template/backend/package-lock.json +1976 -0
- package/template/backend/scripts/check-module-boundaries.mjs +3 -0
- package/template/backend/src/modules/model-condenser/tests/unit/modelCondenser.service.test.js +2 -2
- package/template/backend/src/shared/utils/traceId.js +19 -0
- package/template/docs/README.md +3 -1
- package/template/docs/architecture/CONTRACTS_OVERVIEW.md +12 -0
- package/template/docs/architecture/EVAL_AND_CI.md +79 -0
- package/template/docs/architecture/REPO_ARTIFACT_LAYOUT.md +12 -55
- package/template/docs/architecture/contracts/manifest.json +0 -17
- package/template/file-exchange/README.md +1 -1
- package/template/file-exchange/exports/consolidated-models.json +625 -0
- package/template/frontend/package-lock.json +1727 -0
- package/template/package.json +2 -0
- package/template/scripts/condense-prompts.mjs +10 -10
- package/template/scripts/lib/api-inventory.mjs +14 -21
- package/template/scripts/run-module-evals.mjs +43 -0
package/template/package.json
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
"lint:repo-artifacts": "node scripts/lint-repo-artifacts.mjs",
|
|
13
13
|
"lint:architecture": "npm --prefix backend run lint:architecture",
|
|
14
14
|
"test": "npm --prefix backend test && npm --prefix frontend test",
|
|
15
|
+
"test:evals": "npm --prefix backend run test:evals",
|
|
16
|
+
"test:ci": "npm run lint:contracts && npm run lint:repo-artifacts && npm run lint:architecture && npm test && npm run test:evals",
|
|
15
17
|
"new:module": "node scripts/new-module.mjs",
|
|
16
18
|
"condense-prompts": "node scripts/condense-prompts.mjs",
|
|
17
19
|
"condense-file-structure": "node scripts/condense-file-structure.mjs",
|
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
* Collect all versioned prompt templates into models/consolidated-prompts.json
|
|
4
4
|
* Usage: node scripts/condense-prompts.mjs
|
|
5
5
|
*/
|
|
6
|
-
import { readFile, readdir, stat } from "fs/promises";
|
|
6
|
+
import { readFile, readdir, stat, access } from "fs/promises";
|
|
7
|
+
import { existsSync } from "fs";
|
|
7
8
|
import { join, relative, dirname } from "path";
|
|
8
9
|
import { fileURLToPath } from "url";
|
|
9
10
|
import { writeConsolidatedArtifact } from "./consolidated-output.mjs";
|
|
10
11
|
|
|
11
12
|
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
12
13
|
|
|
13
|
-
const SCAN_ROOTS = [
|
|
14
|
-
"backend/src/modules",
|
|
15
|
-
"work-log/handoffs/001_2026-05-23_starter_case-filing-ai-updated/prompts"
|
|
16
|
-
];
|
|
14
|
+
const SCAN_ROOTS = ["backend/src/modules"];
|
|
17
15
|
|
|
18
16
|
const PROMPT_EXTENSIONS = [".prompt.md", ".prompt.js"];
|
|
19
17
|
|
|
@@ -74,11 +72,14 @@ async function findManifests() {
|
|
|
74
72
|
return manifests;
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
async function
|
|
75
|
+
async function loadDomainPromptVersions() {
|
|
78
76
|
const path = join(
|
|
79
77
|
repoRoot,
|
|
80
78
|
"backend/src/modules/case-filing-ai/prompts/promptVersions.js"
|
|
81
79
|
);
|
|
80
|
+
if (!existsSync(path)) {
|
|
81
|
+
return { sourcePath: null, versions: {} };
|
|
82
|
+
}
|
|
82
83
|
const raw = await readFile(path, "utf8");
|
|
83
84
|
const versions = {};
|
|
84
85
|
const blockRe = /(\w+):\s*\{[^}]*id:\s*"([^"]+)"[^}]*masterCaseFiling:\s*"([^"]+)"[^}]*description:\s*"([^"]+)"/gs;
|
|
@@ -133,7 +134,7 @@ async function main() {
|
|
|
133
134
|
};
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
const
|
|
137
|
+
const domainPromptVersions = await loadDomainPromptVersions();
|
|
137
138
|
const moduleManifests = await findManifests();
|
|
138
139
|
|
|
139
140
|
const doc = {
|
|
@@ -141,11 +142,10 @@ async function main() {
|
|
|
141
142
|
generatedAt: new Date().toISOString(),
|
|
142
143
|
repositoryRoot: repoRoot,
|
|
143
144
|
condensedBy: "condense-prompts",
|
|
144
|
-
description:
|
|
145
|
-
"Consolidated prompt templates for legal-prmpt-eng (active + starter reference).",
|
|
145
|
+
description: "Consolidated prompt templates across backend modules.",
|
|
146
146
|
promptCount: inventory.length
|
|
147
147
|
},
|
|
148
|
-
|
|
148
|
+
domainPromptVersions,
|
|
149
149
|
moduleManifests,
|
|
150
150
|
inventory,
|
|
151
151
|
prompts
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import { readFileSync,
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
|
|
4
|
-
const SKIP_MODULES = new Set(["_reference"]);
|
|
5
|
-
const ROUTE_RE = /router\.(get|post|put|patch|delete)\(\s*["'`]([^"'`]+)["'`]/gi;
|
|
6
|
-
const BASE_PATH_RE = /app\.use\(\s*["'`](\/api\/[^"'`]+)["'`]/;
|
|
7
|
-
|
|
8
4
|
function readText(path) {
|
|
9
5
|
return readFileSync(path, "utf8");
|
|
10
6
|
}
|
|
@@ -80,8 +76,7 @@ export async function collectApiInventory(repoRoot) {
|
|
|
80
76
|
|
|
81
77
|
const http = { active: [], stub: [], deprecated: [] };
|
|
82
78
|
for (const row of registry) {
|
|
83
|
-
|
|
84
|
-
http[bucket].push({
|
|
79
|
+
http[classifyRoute(row)].push({
|
|
85
80
|
method: row.method,
|
|
86
81
|
path: row.path,
|
|
87
82
|
module: row.module,
|
|
@@ -89,23 +84,20 @@ export async function collectApiInventory(repoRoot) {
|
|
|
89
84
|
});
|
|
90
85
|
}
|
|
91
86
|
|
|
92
|
-
const promptVersions = {
|
|
93
|
-
defaultEnv: "n/a",
|
|
94
|
-
envVar: "MASTER_PROMPT_VERSION",
|
|
95
|
-
allowed: [],
|
|
96
|
-
specs: {},
|
|
97
|
-
notes: ["Add promptVersions.js in your domain module when you introduce LLM workflows"]
|
|
98
|
-
};
|
|
99
|
-
|
|
100
87
|
const pkg = JSON.parse(readText(join(repoRoot, "package.json")));
|
|
101
|
-
const pipelineVersions = {
|
|
102
|
-
app: pkg.version ?? "2.0.0",
|
|
103
|
-
note: "Add pipelineVersions.contract.js in domain modules for batch/runtime versioning"
|
|
104
|
-
};
|
|
105
88
|
|
|
106
89
|
const versioned = {
|
|
107
|
-
pipeline:
|
|
108
|
-
|
|
90
|
+
pipeline: {
|
|
91
|
+
app: pkg.version ?? "2.0.0",
|
|
92
|
+
note: "Add pipelineVersions.contract.js in domain modules when you introduce batch workflows"
|
|
93
|
+
},
|
|
94
|
+
prompts: {
|
|
95
|
+
defaultEnv: "n/a",
|
|
96
|
+
envVar: "MASTER_PROMPT_VERSION",
|
|
97
|
+
allowed: [],
|
|
98
|
+
specs: {},
|
|
99
|
+
notes: ["Add promptVersions.js in your domain module when you introduce LLM workflows"]
|
|
100
|
+
},
|
|
109
101
|
storage: {},
|
|
110
102
|
app: { packageJson: pkg.version }
|
|
111
103
|
};
|
|
@@ -123,6 +115,7 @@ export async function collectApiInventory(repoRoot) {
|
|
|
123
115
|
}
|
|
124
116
|
|
|
125
117
|
const cli = [
|
|
118
|
+
{ command: "npm run test:ci", purpose: "All CI gates (lint + test + evals)" },
|
|
126
119
|
{ command: "npm run dev-log:pre-push", purpose: "Paired human + agent dev logs" },
|
|
127
120
|
{ command: "npm run condense:all", purpose: "Snapshots → file-exchange/exports/" },
|
|
128
121
|
{ command: "npm run import:file-exchange", purpose: "Inbound → file-exchange/imports/{stamp}/" },
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readdirSync, existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { spawnSync } from "child_process";
|
|
5
|
+
|
|
6
|
+
const moduleName = process.argv[2];
|
|
7
|
+
const root = new URL("../", import.meta.url).pathname;
|
|
8
|
+
const modulesDir = join(root, "backend/src/modules");
|
|
9
|
+
|
|
10
|
+
if (!existsSync(modulesDir)) {
|
|
11
|
+
console.error("No modules directory.");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const targets = moduleName
|
|
16
|
+
? [moduleName]
|
|
17
|
+
: readdirSync(modulesDir, { withFileTypes: true })
|
|
18
|
+
.filter((d) => d.isDirectory() && !d.name.startsWith("_"))
|
|
19
|
+
.map((d) => d.name);
|
|
20
|
+
|
|
21
|
+
let failed = false;
|
|
22
|
+
|
|
23
|
+
for (const name of targets) {
|
|
24
|
+
const runnersDir = join(modulesDir, name, "evals", "runners");
|
|
25
|
+
if (!existsSync(runnersDir)) continue;
|
|
26
|
+
|
|
27
|
+
const runners = readdirSync(runnersDir).filter(
|
|
28
|
+
(f) => f.endsWith(".eval.mjs") || f.endsWith(".eval.js")
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
for (const runner of runners) {
|
|
32
|
+
const file = join(runnersDir, runner);
|
|
33
|
+
console.log(`\n▶ eval ${name}/${runner}`);
|
|
34
|
+
const result = spawnSync(process.execPath, ["--test", file], {
|
|
35
|
+
stdio: "inherit",
|
|
36
|
+
cwd: join(root, "backend")
|
|
37
|
+
});
|
|
38
|
+
if (result.status !== 0) failed = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (failed) process.exit(1);
|
|
43
|
+
console.log("\nEvals complete.");
|