@pukujan/create-modular-monolith 2.0.0 → 2.1.0
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/README.md +91 -22
- package/index.js +47 -0
- package/package.json +16 -19
- package/template/.cursor/commands/planning-study-log.md +25 -0
- package/template/.cursor/commands/pre-push-dev-log.md +52 -0
- package/template/.cursor/rules/api-documentation.mdc +21 -0
- package/template/.cursor/rules/file-exchange-inbox.mdc +29 -0
- package/template/AGENTS.md +41 -0
- package/template/README.md +18 -57
- package/template/backend/.env.example +38 -0
- package/template/backend/package.json +14 -4
- package/template/backend/src/modules/model-condenser/README.md +7 -0
- package/template/backend/src/modules/model-condenser/config/index.js +20 -0
- package/template/backend/src/modules/model-condenser/events/index.js +1 -0
- package/template/backend/src/modules/model-condenser/index.js +12 -0
- package/template/backend/src/modules/model-condenser/routes/health.routes.js +10 -0
- package/template/backend/src/modules/model-condenser/routes/index.js +10 -0
- package/template/backend/src/modules/model-condenser/routes/modelCondenser.routes.js +44 -0
- package/template/backend/src/modules/model-condenser/services/health.service.js +8 -0
- package/template/backend/src/modules/model-condenser/services/modelCondenser.facade.js +58 -0
- package/template/backend/src/modules/model-condenser/services/modelCondenser.service.js +513 -0
- package/template/backend/src/modules/model-condenser/tests/integration/modelCondenser.routes.test.js +40 -0
- package/template/backend/src/modules/model-condenser/tests/unit/modelCondenser.service.test.js +31 -0
- package/template/backend/src/modules/model-condenser/utils/index.js +1 -0
- package/template/backend/src/shared/contracts/consolidatedExports.contract.js +19 -0
- package/template/backend/src/shared/contracts/prePushDevLog.contract.js +28 -0
- package/template/backend/src/shared/domain/case-filing/core-models.js +117 -0
- package/template/backend/src/shared/http/errors.js +8 -0
- package/template/backend/src/shared/utils/consolidatedExport.js +30 -0
- package/template/backend/src/shared/utils/formatExchangeTimestamp.js +47 -0
- package/template/backend/src/shared/utils/formatExchangeTimestamp.test.js +30 -0
- package/template/docs/API.md +42 -0
- package/template/docs/PUBLISHING.md +13 -1
- package/template/docs/README.md +4 -0
- package/template/docs/STARTER_PACK.md +4 -0
- package/template/docs/architecture/API_DOCUMENTATION_CONTRACT.md +112 -0
- package/template/docs/architecture/CONTRACTS_OVERVIEW.md +168 -0
- package/template/docs/architecture/MODULE_INTERNAL_CONTRACT.md +2 -0
- package/template/docs/architecture/PLATFORM_ARCHITECTURE.md +221 -0
- package/template/docs/architecture/REPO_ARTIFACT_LAYOUT.md +76 -0
- package/template/docs/architecture/contracts/apiDocumentationRegistry.contract.md +40 -0
- package/template/docs/architecture/contracts/changelog.jsonl +12 -0
- package/template/docs/architecture/contracts/consolidatedExports.contract.md +58 -0
- package/template/docs/architecture/contracts/fileExchange.contract.md +47 -0
- package/template/docs/architecture/contracts/manifest.json +56 -0
- package/template/docs/architecture/contracts/prePushDevLog.contract.md +69 -0
- package/template/docs/model-condenser/API.md +102 -0
- package/template/file-exchange/README.md +41 -0
- package/template/file-exchange/exports/.gitkeep +0 -0
- package/template/file-exchange/imports/.gitkeep +0 -0
- package/template/frontend/.env.example +2 -0
- package/template/frontend/package.json +1 -1
- package/template/frontend/src/index.css +311 -0
- package/template/frontend/src/modules/_reference/services/health-api.js +1 -1
- package/template/frontend/src/shared/api/client.js +67 -5
- package/template/models/.gitkeep +0 -0
- package/template/package.json +11 -4
- package/template/scripts/check-api-docs.mjs +183 -0
- package/template/scripts/condense-file-structure.mjs +44 -0
- package/template/scripts/condense-models.mjs +70 -0
- package/template/scripts/condense-prompts.mjs +161 -0
- package/template/scripts/consolidated-output.mjs +49 -0
- package/template/scripts/export-consolidated-models.mjs +11 -0
- package/template/scripts/git-hooks/pre-push.sample +15 -0
- package/template/scripts/import-to-file-exchange.mjs +43 -0
- package/template/scripts/lib/api-inventory.mjs +189 -0
- package/template/scripts/lib/dev-log-human-format.mjs +360 -0
- package/template/scripts/lib/git-snapshot.mjs +46 -0
- package/template/scripts/lib/module-scaffold.mjs +37 -1
- package/template/scripts/lib/repo-tree.mjs +127 -0
- package/template/scripts/lib/run-tests.mjs +60 -0
- package/template/scripts/lint-contracts.mjs +57 -0
- package/template/scripts/lint-repo-artifacts.mjs +37 -0
- package/template/scripts/new-module.mjs +7 -0
- package/template/scripts/resolve-import-stamp.mjs +50 -0
- package/template/scripts/verify-dev-log.mjs +50 -0
- package/template/scripts/write-pre-push-dev-log.mjs +220 -0
- package/template/work-log/INDEX.md +3 -0
- package/template/work-log/README.md +40 -0
- package/template/work-log/dev-logs/README.md +97 -0
- package/template/work-log/dev-logs/schemas/dev-log-agent.v1.schema.json +119 -0
- package/template/work-log/dev-logs/templates/dev-log-human.template.md +10 -0
- package/template/work-log/handoffs/README.md +36 -0
- package/template/work-log/study-docs/README.md +13 -0
- package/bin/create-modular-monolith.js +0 -132
- package/template/backend/package-lock.json +0 -882
- package/template/backend/src/modules/_reference/evals/README.md +0 -6
- package/template/backend/src/modules/_reference/evals/datasets/example.cases.json +0 -12
- package/template/backend/src/modules/_reference/evals/runners/example.eval.mjs +0 -25
- package/template/frontend/package-lock.json +0 -1724
- package/template/scripts/run-module-evals.mjs +0 -43
- package/template/scripts/sync-cli-template.mjs +0 -44
- /package/template/{frontend/src/modules → backend/db/migrations}/.gitkeep +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://legal-prmpt-eng.local/schemas/dev-log-agent.v1.json",
|
|
4
|
+
"title": "Agent audit dev log",
|
|
5
|
+
"description": "Machine-readable pre-push audit log for Cursor agents. Pair with human dev-log in work-log/dev-logs/human/.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["meta", "summary", "apis", "git", "tests", "repositoryTree", "changes", "decisions", "iterations", "tradeoffs", "improvements", "regressions", "risks", "followUps"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"meta": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["schemaVersion", "entryId", "slug", "generatedAt", "humanLogPath", "audience"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"schemaVersion": { "const": "1.0.0" },
|
|
14
|
+
"entryId": { "type": "string", "pattern": "^[0-9]{3}$" },
|
|
15
|
+
"slug": { "type": "string" },
|
|
16
|
+
"generatedAt": { "type": "string", "format": "date-time" },
|
|
17
|
+
"humanLogPath": { "type": "string" },
|
|
18
|
+
"audience": { "const": "agent" },
|
|
19
|
+
"filledBy": { "type": "string", "enum": ["script", "agent", "human"] },
|
|
20
|
+
"handoffRefs": { "type": "array", "items": { "type": "string" } }
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"summary": { "type": "string" },
|
|
24
|
+
"apis": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"description": "HTTP routes, versioned contracts, deprecated surfaces",
|
|
27
|
+
"properties": {
|
|
28
|
+
"capturedAt": { "type": "string" },
|
|
29
|
+
"sourceDocs": { "type": "array", "items": { "type": "string" } },
|
|
30
|
+
"http": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"properties": {
|
|
33
|
+
"active": { "type": "array" },
|
|
34
|
+
"stub": { "type": "array" },
|
|
35
|
+
"deprecated": { "type": "array" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"moduleStatus": { "type": "array" },
|
|
39
|
+
"versioned": { "type": "object" },
|
|
40
|
+
"deprecated": { "type": "object" },
|
|
41
|
+
"cli": { "type": "array" }
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"git": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"properties": {
|
|
47
|
+
"branch": { "type": "string" },
|
|
48
|
+
"sha": { "type": "string" },
|
|
49
|
+
"shortSha": { "type": "string" },
|
|
50
|
+
"changedFiles": { "type": "array" },
|
|
51
|
+
"diffStatAgainstHead": { "type": "string" },
|
|
52
|
+
"recentCommits": { "type": "array", "items": { "type": "string" } }
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"tests": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"properties": {
|
|
58
|
+
"ran": { "type": "boolean" },
|
|
59
|
+
"exitCode": { "type": ["integer", "null"] },
|
|
60
|
+
"summary": { "type": "string" },
|
|
61
|
+
"passed": { "type": "array", "items": { "type": "string" } },
|
|
62
|
+
"failed": { "type": "array", "items": { "type": "string" } },
|
|
63
|
+
"commands": { "type": "array", "items": { "type": "string" } }
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"repositoryTree": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"properties": {
|
|
69
|
+
"capturedAt": { "type": "string" },
|
|
70
|
+
"excludeDirs": { "type": "array", "items": { "type": "string" } },
|
|
71
|
+
"treeIgnoreFlag": { "type": "string" },
|
|
72
|
+
"stats": { "type": "object" },
|
|
73
|
+
"treeText": { "type": "string" },
|
|
74
|
+
"flatPathCount": { "type": "integer" }
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"changes": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"byArea": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "string" } } },
|
|
81
|
+
"added": { "type": "array", "items": { "type": "string" } },
|
|
82
|
+
"modified": { "type": "array", "items": { "type": "string" } },
|
|
83
|
+
"deleted": { "type": "array", "items": { "type": "string" } },
|
|
84
|
+
"narrative": { "type": "array", "items": { "type": "string" } }
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"decisions": {
|
|
88
|
+
"type": "array",
|
|
89
|
+
"items": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"required": ["id", "decision", "rationale"],
|
|
92
|
+
"properties": {
|
|
93
|
+
"id": { "type": "string" },
|
|
94
|
+
"decision": { "type": "string" },
|
|
95
|
+
"rationale": { "type": "string" },
|
|
96
|
+
"alternativesRejected": { "type": "array", "items": { "type": "string" } },
|
|
97
|
+
"tradeoff": { "type": "string" }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"iterations": {
|
|
102
|
+
"type": "array",
|
|
103
|
+
"items": {
|
|
104
|
+
"type": "object",
|
|
105
|
+
"properties": {
|
|
106
|
+
"attempt": { "type": "integer" },
|
|
107
|
+
"action": { "type": "string" },
|
|
108
|
+
"outcome": { "type": "string" },
|
|
109
|
+
"blockedBy": { "type": "string" }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"tradeoffs": { "type": "array", "items": { "type": "string" } },
|
|
114
|
+
"improvements": { "type": "array", "items": { "type": "string" } },
|
|
115
|
+
"regressions": { "type": "array", "items": { "type": "string" } },
|
|
116
|
+
"risks": { "type": "array", "items": { "type": "string" } },
|
|
117
|
+
"followUps": { "type": "array", "items": { "type": "string" } }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Dev log (human) — two-part layout
|
|
2
|
+
|
|
3
|
+
Generated by `npm run dev-log:pre-push`. Do not edit this file directly.
|
|
4
|
+
|
|
5
|
+
The generator builds:
|
|
6
|
+
|
|
7
|
+
1. **Part I — Summary** (top): TOC, mermaid diagrams, audit tables (API, versions/prompts, tests, git, condensed tree).
|
|
8
|
+
2. **Part II — Detailed** (bottom): decisions, iterations, full API registry, full git snapshot, full tree.
|
|
9
|
+
|
|
10
|
+
See `scripts/lib/dev-log-human-format.mjs`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Handoffs
|
|
2
|
+
|
|
3
|
+
Implementation specs and starter packs. Parent folder: [work-log](../README.md).
|
|
4
|
+
|
|
5
|
+
Study logs and planning notes live in **[../study-docs/](../study-docs/)** — not here.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
work-log/handoffs/
|
|
11
|
+
001_*_starter_*/ ← starter pack (folder)
|
|
12
|
+
002_*_handoff_*.md
|
|
13
|
+
005_*_handoff_*.md ← original, v2, v3
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Full index: [../INDEX.md](../INDEX.md).
|
|
17
|
+
|
|
18
|
+
## Filename convention
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
{NNN}_{YYYY-MM-DD}_{HH-MM}_{kind}_{short-slug}.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Part | Example |
|
|
25
|
+
|------|---------|
|
|
26
|
+
| Date | `2026-05-23` |
|
|
27
|
+
| Time | `10-49` (24h, optional) |
|
|
28
|
+
| Kind | `handoff`, `handoff-v2`, `handoff-v3`, `handoff-original` |
|
|
29
|
+
|
|
30
|
+
Same pattern in [study-docs](../study-docs/README.md) (`study-log`) and [dev-logs](../dev-logs/README.md) (`dev-log`).
|
|
31
|
+
|
|
32
|
+
## 005 execution order
|
|
33
|
+
|
|
34
|
+
1. [Original](./005_2026-05-23_10-49_handoff-original_parsed-cache-rule-authority.md) — requirements
|
|
35
|
+
2. [v3](./005_2026-05-23_11-20_handoff-v3_filing-structure-architecture.md) — architecture first
|
|
36
|
+
3. [v2](./005_2026-05-23_11-14_handoff-v2_planned-review-in-cursor.md) — pipeline implementation
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Study docs
|
|
2
|
+
|
|
3
|
+
Design rationale, planning conversations, and portfolio study logs. Parent: [work-log](../README.md).
|
|
4
|
+
|
|
5
|
+
Implementation specs are in **[../handoffs/](../handoffs/)**.
|
|
6
|
+
|
|
7
|
+
## Filename convention
|
|
8
|
+
|
|
9
|
+
Same as [handoffs](../handoffs/README.md) and [dev-logs](../dev-logs/README.md):
|
|
10
|
+
|
|
11
|
+
`{NNN}_{YYYY-MM-DD}_{HH-MM}_study-log_{slug}.md`
|
|
12
|
+
|
|
13
|
+
Full index: [../INDEX.md](../INDEX.md).
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
cpSync,
|
|
4
|
-
existsSync,
|
|
5
|
-
mkdirSync,
|
|
6
|
-
readFileSync,
|
|
7
|
-
readdirSync,
|
|
8
|
-
writeFileSync
|
|
9
|
-
} from "fs";
|
|
10
|
-
import { join, resolve, basename } from "path";
|
|
11
|
-
import { fileURLToPath } from "url";
|
|
12
|
-
import { spawnSync } from "child_process";
|
|
13
|
-
|
|
14
|
-
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
15
|
-
const templateDir = join(__dirname, "..", "template");
|
|
16
|
-
|
|
17
|
-
const args = process.argv.slice(2).filter((a) => a !== "--");
|
|
18
|
-
const installDeps = args.includes("--install");
|
|
19
|
-
const initGit = args.includes("--git");
|
|
20
|
-
const positional = args.filter((a) => !a.startsWith("--"));
|
|
21
|
-
|
|
22
|
-
const targetArg = positional[0];
|
|
23
|
-
const cwd = process.cwd();
|
|
24
|
-
const targetDir = targetArg ? resolve(cwd, targetArg) : resolve(cwd, "my-platform");
|
|
25
|
-
const projectName = basename(targetDir);
|
|
26
|
-
|
|
27
|
-
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(projectName)) {
|
|
28
|
-
console.error(
|
|
29
|
-
"Project folder name must be kebab-case (example: my-platform).\n",
|
|
30
|
-
"Usage: npm create @pukujan/modular-monolith@2 my-platform"
|
|
31
|
-
);
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (!existsSync(templateDir)) {
|
|
36
|
-
console.error("Template missing. Reinstall @pukujan/create-modular-monolith.");
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (existsSync(targetDir)) {
|
|
41
|
-
try {
|
|
42
|
-
const entries = readdirSync(targetDir);
|
|
43
|
-
if (entries.length > 0) {
|
|
44
|
-
console.error(`Target directory is not empty: ${targetDir}`);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
} catch {
|
|
48
|
-
console.error(`Cannot use target: ${targetDir}`);
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const displayName = toTitleCase(projectName);
|
|
54
|
-
|
|
55
|
-
console.log(`\nCreating modular monolith starter: ${projectName}`);
|
|
56
|
-
console.log(` → ${targetDir}\n`);
|
|
57
|
-
|
|
58
|
-
mkdirSync(targetDir, { recursive: true });
|
|
59
|
-
cpSync(templateDir, targetDir, { recursive: true });
|
|
60
|
-
|
|
61
|
-
replaceInTree(targetDir, [
|
|
62
|
-
["modular-monolith-starter-backend", `${projectName}-backend`],
|
|
63
|
-
["modular-monolith-starter-frontend", `${projectName}-frontend`],
|
|
64
|
-
["modular-monolith-starter", projectName],
|
|
65
|
-
["Modular Monolith Platform Starter", displayName]
|
|
66
|
-
]);
|
|
67
|
-
|
|
68
|
-
if (installDeps) {
|
|
69
|
-
console.log("Installing dependencies…");
|
|
70
|
-
run("npm", ["install"], join(targetDir, "backend"));
|
|
71
|
-
run("npm", ["install"], join(targetDir, "frontend"));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (initGit) {
|
|
75
|
-
run("git", ["init"], targetDir);
|
|
76
|
-
run("git", ["add", "."], targetDir);
|
|
77
|
-
run("git", ["commit", "-m", "chore: scaffold modular monolith starter"], targetDir);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
console.log("\nDone.\n");
|
|
81
|
-
console.log("Next steps:");
|
|
82
|
-
console.log(` cd ${targetArg || projectName}`);
|
|
83
|
-
if (!installDeps) {
|
|
84
|
-
console.log(" cd backend && npm install");
|
|
85
|
-
console.log(" cd ../frontend && npm install");
|
|
86
|
-
}
|
|
87
|
-
console.log(" npm run dev:backend # terminal 1");
|
|
88
|
-
console.log(" npm run dev:frontend # terminal 2");
|
|
89
|
-
console.log(` npm run new:module -- my-feature --label "My Feature"`);
|
|
90
|
-
console.log(" npm run lint:architecture && npm test\n");
|
|
91
|
-
|
|
92
|
-
function replaceInTree(dir, pairs) {
|
|
93
|
-
for (const file of walkFiles(dir)) {
|
|
94
|
-
if (!/\.(json|md|js|jsx|mjs|html)$/.test(file)) continue;
|
|
95
|
-
let content = readFileSync(file, "utf8");
|
|
96
|
-
let changed = false;
|
|
97
|
-
for (const [from, to] of pairs) {
|
|
98
|
-
if (content.includes(from)) {
|
|
99
|
-
content = content.split(from).join(to);
|
|
100
|
-
changed = true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (changed) writeFileSync(file, content, "utf8");
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function walkFiles(dir, acc = []) {
|
|
108
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
109
|
-
const full = join(dir, entry.name);
|
|
110
|
-
if (entry.isDirectory()) {
|
|
111
|
-
if (entry.name === "node_modules") continue;
|
|
112
|
-
walkFiles(full, acc);
|
|
113
|
-
} else {
|
|
114
|
-
acc.push(full);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return acc;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function toTitleCase(value) {
|
|
121
|
-
return value
|
|
122
|
-
.split("-")
|
|
123
|
-
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
|
|
124
|
-
.join(" ");
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function run(cmd, cmdArgs, dir) {
|
|
128
|
-
const result = spawnSync(cmd, cmdArgs, { cwd: dir, stdio: "inherit" });
|
|
129
|
-
if (result.status !== 0) {
|
|
130
|
-
console.warn(`Warning: ${cmd} ${cmdArgs.join(" ")} exited with ${result.status}`);
|
|
131
|
-
}
|
|
132
|
-
}
|