@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
package/README.md
CHANGED
|
@@ -1,43 +1,112 @@
|
|
|
1
1
|
# @pukujan/create-modular-monolith
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Create a project
|
|
3
|
+
**npm create** scaffold for a modular monolith built for **human + agent** engineering at scale.
|
|
6
4
|
|
|
7
5
|
```bash
|
|
8
6
|
npm create @pukujan/modular-monolith@2 my-platform
|
|
9
7
|
cd my-platform
|
|
10
|
-
|
|
8
|
+
npm install --prefix backend && npm install --prefix frontend
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
Published package: `@pukujan/create-modular-monolith`
|
|
12
|
+
Product reference implementation: [litigation-prompt-engineering](https://github.com/Pukujan/litigation-prompt-engineering)
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## What you get
|
|
17
|
+
|
|
18
|
+
This is **not** a minimal Express/React demo. It is an **architecture platform**:
|
|
19
|
+
|
|
20
|
+
| Layer | Purpose |
|
|
21
|
+
|-------|---------|
|
|
22
|
+
| **Module contract** | Backend `register(app)` + frontend route modules — add features without rewriting core |
|
|
23
|
+
| **Architecture contracts** | Versioned manifest (`docs/architecture/contracts/`) — paths, APIs, exports, dev logs |
|
|
24
|
+
| **File exchange** | Dated `imports/` / `exports/` for human↔agent file handoff |
|
|
25
|
+
| **Pre-push dev logs** | Paired **human markdown** (summary + detail, mermaid, TOC) + **agent JSON** audit |
|
|
26
|
+
| **Consolidated snapshots** | `condense:all` → models, prompts, file tree in `file-exchange/exports/` |
|
|
27
|
+
| **Lint automation** | Boundaries, layers, contracts, repo artifacts, API registry |
|
|
28
|
+
| **Cursor-native** | `AGENTS.md`, `.cursor/rules`, `.cursor/commands` for repeatable agent workflows |
|
|
29
|
+
|
|
30
|
+
Domain business logic is **yours to add** via `npm run new:module`. The repo ships with `_reference` and `model-condenser` only.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Why this architecture exists
|
|
35
|
+
|
|
36
|
+
Modern products are built as much by **agents** as by humans. This template encodes:
|
|
37
|
+
|
|
38
|
+
1. **Discoverability** — Agents read JSON audits and contract manifests instead of guessing folder layout.
|
|
39
|
+
2. **Repeatability** — Every push can produce the same artifact set (dev log pair, tree, API inventory, test results).
|
|
40
|
+
3. **Scale** — New modules plug in under `backend/src/modules/` and `frontend/src/modules/` with enforced boundaries.
|
|
41
|
+
4. **Governance** — `lint:contracts` fails CI if a contract path is missing; `lint:api-docs` keeps routes documented.
|
|
42
|
+
|
|
43
|
+
Read **`template/docs/architecture/PLATFORM_ARCHITECTURE.md`** (in this repo) for the full narrative. After scaffold, start at **`docs/architecture/CONTRACTS_OVERVIEW.md`** in your project.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Repository layout (this GitHub repo)
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
create-modular-monolith/
|
|
51
|
+
README.md ← you are here (npm package docs)
|
|
52
|
+
package.json ← @pukujan/create-modular-monolith
|
|
53
|
+
index.js ← copies template/ into target directory
|
|
54
|
+
template/ ← full starter app (architecture only)
|
|
17
55
|
```
|
|
18
56
|
|
|
19
|
-
|
|
20
|
-
| --- | --- |
|
|
21
|
-
| `--install` | Run `npm install` in backend and frontend |
|
|
22
|
-
| `--git` | `git init` and initial commit |
|
|
57
|
+
---
|
|
23
58
|
|
|
24
|
-
##
|
|
59
|
+
## Architecture scripts (in every scaffolded project)
|
|
60
|
+
|
|
61
|
+
These live under `template/scripts/` and are copied into new projects:
|
|
62
|
+
|
|
63
|
+
| Script | npm command | Role |
|
|
64
|
+
|--------|-------------|------|
|
|
65
|
+
| `lint-contracts.mjs` | `npm run lint:contracts` | Verify `manifest.json` paths exist |
|
|
66
|
+
| `lint-repo-artifacts.mjs` | `npm run lint:repo-artifacts` | Verify exchange, dev-log, contract docs |
|
|
67
|
+
| `check-api-docs.mjs` | `npm run lint:api-docs` | Routes ⊆ `docs/API.md` registry |
|
|
68
|
+
| `write-pre-push-dev-log.mjs` | `npm run dev-log:pre-push` | Human + agent pre-push audit pair |
|
|
69
|
+
| `verify-dev-log.mjs` | `npm run dev-log:verify` | Validate latest dev-log structure |
|
|
70
|
+
| `condense-file-structure.mjs` | `npm run condense-file-structure` | Repo tree → `exports/consolidated-file-structure.json` |
|
|
71
|
+
| `condense-prompts.mjs` | `npm run condense-prompts` | All prompts → consolidated JSON |
|
|
72
|
+
| `import-to-file-exchange.mjs` | `npm run import:file-exchange` | Inbound bundles → `imports/{stamp}/` |
|
|
73
|
+
| `new-module.mjs` | `npm run new:module` | Scaffold backend + frontend module |
|
|
74
|
+
|
|
75
|
+
Supporting libraries: `scripts/lib/repo-tree.mjs`, `api-inventory.mjs`, `dev-log-human-format.mjs`, `git-snapshot.mjs`, `run-tests.mjs`.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Contract catalog (v001)
|
|
25
80
|
|
|
26
|
-
|
|
27
|
-
- **Internal contract** — routes → services → repositories / domain / adapters
|
|
28
|
-
- **AI-ready** — versioned `prompts/` and `evals/` per feature module
|
|
29
|
-
- **Lint** — cross-module boundaries + layer direction (`lint:architecture`)
|
|
81
|
+
Registered in `template/docs/architecture/contracts/manifest.json`:
|
|
30
82
|
|
|
31
|
-
|
|
83
|
+
- **fileExchange** — dated imports/exports, human-readable stamps
|
|
84
|
+
- **consolidatedExports** — snapshot JSON in `file-exchange/exports/`
|
|
85
|
+
- **prePushDevLog** — paired human MD + agent JSON before push
|
|
86
|
+
- **apiDocumentationRegistry** — `docs/API.md` as HTTP source of truth
|
|
87
|
+
- **repoArtifactLayout** — canonical data roots
|
|
32
88
|
|
|
33
|
-
|
|
89
|
+
Module-level contracts (storage layout, pipeline versions) are added when you build domain modules.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Publishing this package
|
|
34
94
|
|
|
35
95
|
```bash
|
|
36
|
-
|
|
37
|
-
|
|
96
|
+
cd packages/create-modular-monolith # or repo root if package.json is here
|
|
97
|
+
npm version patch|minor|major
|
|
38
98
|
npm publish --access public
|
|
39
99
|
```
|
|
40
100
|
|
|
41
|
-
|
|
101
|
+
Users install with:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm create @pukujan/modular-monolith@2 <folder-name>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Version
|
|
42
110
|
|
|
43
|
-
|
|
111
|
+
Package version tracks **architecture platform** releases (contracts, agent tooling, template layout).
|
|
112
|
+
See `package.json` and git tags. Domain app code lives in separate product repos.
|
package/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* npm create @pukujan/modular-monolith
|
|
4
|
+
* Copies template/ into the target directory.
|
|
5
|
+
*/
|
|
6
|
+
import { cpSync, existsSync, mkdirSync } from "fs";
|
|
7
|
+
import { join, resolve } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
|
|
10
|
+
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
11
|
+
const templateDir = join(__dirname, "template");
|
|
12
|
+
|
|
13
|
+
const targetArg = process.argv[2];
|
|
14
|
+
if (!targetArg || targetArg === "--help" || targetArg === "-h") {
|
|
15
|
+
console.log(`
|
|
16
|
+
Usage: npm create @pukujan/modular-monolith@2 <project-directory>
|
|
17
|
+
|
|
18
|
+
Scaffolds a modular monolith with architecture contracts, file-exchange,
|
|
19
|
+
pre-push dev logs (human + agent), and consolidated export tooling.
|
|
20
|
+
|
|
21
|
+
Docs: https://github.com/Pukujan/create-modular-monolith
|
|
22
|
+
`);
|
|
23
|
+
process.exit(targetArg ? 0 : 1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const target = resolve(process.cwd(), targetArg);
|
|
27
|
+
|
|
28
|
+
if (existsSync(target) && existsSync(join(target, "package.json"))) {
|
|
29
|
+
console.error(`Target already exists and looks like a project: ${target}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
mkdirSync(target, { recursive: true });
|
|
34
|
+
cpSync(templateDir, target, { recursive: true });
|
|
35
|
+
|
|
36
|
+
console.log(`
|
|
37
|
+
Created modular monolith at ${target}
|
|
38
|
+
|
|
39
|
+
Next steps:
|
|
40
|
+
cd ${targetArg}
|
|
41
|
+
npm install --prefix backend
|
|
42
|
+
npm install --prefix frontend
|
|
43
|
+
npm run lint:contracts
|
|
44
|
+
|
|
45
|
+
Read docs/architecture/PLATFORM_ARCHITECTURE.md and AGENTS.md before adding modules.
|
|
46
|
+
`);
|
|
47
|
+
console.log(` npm run new:module -- my-feature --label "My Feature"\n`);
|
package/package.json
CHANGED
|
@@ -1,39 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pukujan/create-modular-monolith",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Scaffold a
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Scaffold a modular monolith with architecture contracts, file-exchange, agent dev logs, and lint automation for Cursor-scale engineering.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"create-modular-monolith": "
|
|
7
|
+
"create-modular-monolith": "index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"
|
|
10
|
+
"index.js",
|
|
11
11
|
"template"
|
|
12
12
|
],
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": ">=18"
|
|
15
|
-
},
|
|
16
13
|
"keywords": [
|
|
17
14
|
"modular-monolith",
|
|
18
|
-
"
|
|
15
|
+
"express",
|
|
16
|
+
"react",
|
|
17
|
+
"vite",
|
|
18
|
+
"cursor",
|
|
19
19
|
"architecture",
|
|
20
20
|
"scaffold",
|
|
21
|
-
"create-app"
|
|
22
|
-
"platform",
|
|
23
|
-
"microservices-ready",
|
|
24
|
-
"legal-tech"
|
|
21
|
+
"create-app"
|
|
25
22
|
],
|
|
23
|
+
"author": "Pukujan",
|
|
26
24
|
"license": "MIT",
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
29
|
-
},
|
|
30
25
|
"repository": {
|
|
31
26
|
"type": "git",
|
|
32
|
-
"url": "git+https://github.com/Pukujan/
|
|
33
|
-
"directory": "packages/create-modular-monolith"
|
|
27
|
+
"url": "git+https://github.com/Pukujan/create-modular-monolith.git"
|
|
34
28
|
},
|
|
35
29
|
"bugs": {
|
|
36
|
-
"url": "https://github.com/Pukujan/
|
|
30
|
+
"url": "https://github.com/Pukujan/create-modular-monolith/issues"
|
|
37
31
|
},
|
|
38
|
-
"homepage": "https://github.com/Pukujan/
|
|
32
|
+
"homepage": "https://github.com/Pukujan/create-modular-monolith#readme",
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
}
|
|
39
36
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Planning study log
|
|
2
|
+
|
|
3
|
+
Append a **planning-only** study log entry under `work-log/study-docs/`.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
1. **No sensitive content** — fixtures, APIs, folder layout, architecture only. No party names or filing text.
|
|
8
|
+
2. **User messages** — verbatim in blockquotes under `### {UTC} · You`.
|
|
9
|
+
3. **Assistant** — short bullet summary under `### {UTC} · Cursor`.
|
|
10
|
+
4. **Filename** — `work-log/study-docs/{NNN}_{YYYY-MM-DD}_{HH-MM}_study-log_{slug}.md` using UTC from `formatWorkLogTimestamp` in `backend/src/shared/utils/formatExchangeTimestamp.js`.
|
|
11
|
+
5. **Append vs new file** — append to the latest log for the same program id if under ~400 lines; otherwise create a new file with `Continues from: [previous](./previous.md)`.
|
|
12
|
+
6. **Index** — add a row to `work-log/INDEX.md` when creating a new file.
|
|
13
|
+
7. **Scope** — default planning-only unless the user says to include implementation.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. Read the current conversation turns since the last logged entry (or the whole session if new).
|
|
18
|
+
2. Determine program id (e.g. `006`) and slug from the topic.
|
|
19
|
+
3. Write or append turns with ISO-8601 UTC timestamps per turn.
|
|
20
|
+
4. Confirm the file path in your reply.
|
|
21
|
+
|
|
22
|
+
## Optional tags on user turns
|
|
23
|
+
|
|
24
|
+
- `Program` — pipeline / feature scope (v2)
|
|
25
|
+
- `Architecture` — layout / contracts (v3)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Pre-push dev log (human + agent audit)
|
|
2
|
+
|
|
3
|
+
Create **two** dev logs before every push: one for humans, one structured JSON for agents.
|
|
4
|
+
|
|
5
|
+
## When to run
|
|
6
|
+
|
|
7
|
+
- Before `git push` (or when the user asks to “write dev log” / “pre-push log”).
|
|
8
|
+
- After a meaningful slice of work — same session as the push.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Generate skeletons** (auto-fills git, tests, full repo tree):
|
|
13
|
+
```bash
|
|
14
|
+
npm run dev-log:pre-push -- --slug <kebab-topic> --program 005
|
|
15
|
+
```
|
|
16
|
+
Use `--no-tests` only if tests were already run and recorded manually.
|
|
17
|
+
Use `--title "Readable title"` if the slug is too terse.
|
|
18
|
+
|
|
19
|
+
2. **Fill the agent log first** (`work-log/dev-logs/agent/*_dev-log-agent_*.json`):
|
|
20
|
+
- Replace every `FILL` string with concrete facts.
|
|
21
|
+
- `decisions[]` — id, decision, rationale, alternativesRejected, tradeoff.
|
|
22
|
+
- `iterations[]` — each attempt in order.
|
|
23
|
+
- `changes.narrative`, `improvements`, `tradeoffs`, `regressions`, `risks`, `followUps`.
|
|
24
|
+
- `summary` — dense paragraph an agent can scan in one pass.
|
|
25
|
+
- Keep `apis`, `repositoryTree.treeText`, and `git` as-is unless stale; update `apis` if you added/deprecated routes.
|
|
26
|
+
- `apis.http` = active / stub / deprecated; `apis.versioned` = pipeline + prompt versions.
|
|
27
|
+
|
|
28
|
+
3. **Fill the human log** (`work-log/dev-logs/human/*_dev-log_*.md`):
|
|
29
|
+
- **Part I (top):** fill **I.1 At a glance** only; leave auto audit tables and mermaid as-is unless APIs changed.
|
|
30
|
+
- **Part II (bottom):** decisions, iterations, changes, outcomes — mirror the agent JSON in prose.
|
|
31
|
+
- Do **not** remove Part I audit tables, mermaid blocks, or Part II full tree/git sections.
|
|
32
|
+
|
|
33
|
+
4. **Index** — add two rows to `work-log/INDEX.md` (human + agent).
|
|
34
|
+
|
|
35
|
+
5. **Verify** (optional):
|
|
36
|
+
```bash
|
|
37
|
+
npm run dev-log:pre-push -- --check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
- **No secrets** — no `.env` values, API keys, or real party/filing text.
|
|
43
|
+
- **Pair required** — every human log must have a sibling agent JSON with the same `{NNN}_{date}_{time}` prefix.
|
|
44
|
+
- **Agent log is the audit source of truth** for the next session; human log is the readable narrative.
|
|
45
|
+
- Schema: `work-log/dev-logs/schemas/dev-log-agent.v1.schema.json`
|
|
46
|
+
|
|
47
|
+
## Filename convention
|
|
48
|
+
|
|
49
|
+
| Audience | Path | Pattern |
|
|
50
|
+
|----------|------|---------|
|
|
51
|
+
| Human | `work-log/dev-logs/human/` | `{NNN}_{YYYY-MM-DD}_{HH-MM}_dev-log_{slug}.md` |
|
|
52
|
+
| Agent | `work-log/dev-logs/agent/` | `{NNN}_{YYYY-MM-DD}_{HH-MM}_dev-log-agent_{slug}.json` |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Document every new HTTP route in module API.md and docs/API.md registry
|
|
3
|
+
globs: backend/src/modules/**/routes/**/*.js,backend/src/modules/**/index.js,docs/**/API.md,docs/API.md
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# API documentation contract
|
|
8
|
+
|
|
9
|
+
When you add or change an Express route under `backend/src/modules/<module>/routes/`:
|
|
10
|
+
|
|
11
|
+
1. **Append** to `docs/<module>/API.md`:
|
|
12
|
+
- `## Endpoint quick reference` table: Method | Path | Description
|
|
13
|
+
- Detailed `### \`METHOD /path\`` section if non-trivial
|
|
14
|
+
2. **Append** to `docs/API.md` → `## Endpoint registry`:
|
|
15
|
+
- Full path `/api/<module-id>/...`, module label, short description
|
|
16
|
+
3. Run `npm run lint:api-docs` and fix failures before finishing.
|
|
17
|
+
|
|
18
|
+
Path in module doc = route relative to base (`/health`, not `/api/module/health`).
|
|
19
|
+
Registry path = full path including `/api/<module-id>`.
|
|
20
|
+
|
|
21
|
+
Read [docs/architecture/API_DOCUMENTATION_CONTRACT.md](docs/architecture/API_DOCUMENTATION_CONTRACT.md) for the full checklist.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Mandatory file-exchange inbox before processing inbound bundles or PDFs
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# File exchange inbox (mandatory)
|
|
7
|
+
|
|
8
|
+
**Always apply** when the user provides files, bundles, PDFs, golden datasets, or asks to run `process-batch`, ingest golden, or import from Downloads.
|
|
9
|
+
|
|
10
|
+
## Before any processing
|
|
11
|
+
|
|
12
|
+
1. Run **`npm run import:file-exchange -- "<source-path>"`** unless files are already under `file-exchange/imports/{UTC-stamp}/`.
|
|
13
|
+
2. Use **`formatExchangeTimestamp()`** from `backend/src/shared/utils/formatExchangeTimestamp.js` for the folder name — never ad-hoc slug folders.
|
|
14
|
+
3. Record the stamp in your reply (e.g. `imports/2026-05-23_15-59-43Z/`) so exports can use a matching `exports/{stamp}/`.
|
|
15
|
+
|
|
16
|
+
## Then
|
|
17
|
+
|
|
18
|
+
- Ingest golden from that stamp: `npm run ingest:golden-parsed`, `npm run ingest:golden-expected`.
|
|
19
|
+
- Point `process-batch` / `curl` uploads at PDFs **inside** `file-exchange/imports/{stamp}/`, not `Downloads/` or repo root.
|
|
20
|
+
- Copy deliverables to `file-exchange/exports/{stamp}/` when done.
|
|
21
|
+
- Consolidated repo snapshots: `file-exchange/exports/consolidated-*.json` (`npm run condense:all`).
|
|
22
|
+
|
|
23
|
+
## Do not
|
|
24
|
+
|
|
25
|
+
- Skip import to save time.
|
|
26
|
+
- Process from `~/Downloads/...` directly.
|
|
27
|
+
- Create `imports/synthetic-case-001-.../` without a UTC stamp.
|
|
28
|
+
|
|
29
|
+
See [AGENTS.md](../../AGENTS.md), [file-exchange/README.md](../../file-exchange/README.md), and [REPO_ARTIFACT_LAYOUT.md](../../docs/architecture/REPO_ARTIFACT_LAYOUT.md).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Agent instructions (Cursor / automation)
|
|
2
|
+
|
|
3
|
+
Repo-wide rules for AI agents. Module-specific rules live under `.cursor/rules/`.
|
|
4
|
+
|
|
5
|
+
## Mandatory: file-exchange before processing inbound files
|
|
6
|
+
|
|
7
|
+
Copy user bundles into a dated import folder before processing:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run import:file-exchange -- "/path/to/bundle"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Stamp format: `2026-05-23_15-59-43Z` via `formatExchangeTimestamp` in `backend/src/shared/utils/formatExchangeTimestamp.js`.
|
|
14
|
+
|
|
15
|
+
Deliverables → `file-exchange/exports/{stamp}/`. Consolidated snapshots → `file-exchange/exports/consolidated-*.json` (`npm run condense:all`).
|
|
16
|
+
|
|
17
|
+
See [file-exchange/README.md](file-exchange/README.md) and [docs/architecture/CONTRACTS_OVERVIEW.md](docs/architecture/CONTRACTS_OVERVIEW.md).
|
|
18
|
+
|
|
19
|
+
## Pre-push dev log
|
|
20
|
+
|
|
21
|
+
Before each push:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run dev-log:pre-push -- --slug <topic>
|
|
25
|
+
npm run dev-log:verify
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Paired logs: `work-log/dev-logs/human/` + `work-log/dev-logs/agent/`. See `.cursor/commands/pre-push-dev-log.md`.
|
|
29
|
+
|
|
30
|
+
## Architecture checks
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run lint:architecture
|
|
34
|
+
npm run lint:contracts
|
|
35
|
+
npm run lint:repo-artifacts
|
|
36
|
+
npm run lint:api-docs
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Work log
|
|
40
|
+
|
|
41
|
+
Handoffs and dev-logs under `work-log/` per [work-log/README.md](work-log/README.md).
|
package/template/README.md
CHANGED
|
@@ -1,52 +1,12 @@
|
|
|
1
|
-
# Modular
|
|
1
|
+
# Modular monolith platform (scaffolded)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Architecture-first Express + React starter for products that scale with **human + agent** engineering.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Read first:** [docs/architecture/PLATFORM_ARCHITECTURE.md](docs/architecture/PLATFORM_ARCHITECTURE.md)
|
|
6
|
+
**Contracts:** [docs/architecture/CONTRACTS_OVERVIEW.md](docs/architecture/CONTRACTS_OVERVIEW.md)
|
|
7
|
+
**Agents:** [AGENTS.md](AGENTS.md)
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
**Documentation:** [docs/README.md](./docs/README.md) · [DEVLOG v2](./docs/DEVLOG_V2.md) · [guardrails](./docs/architecture/ARCHITECTURE_GUARDRAILS.md) · [internal contract](./docs/architecture/MODULE_INTERNAL_CONTRACT.md)
|
|
10
|
-
|
|
11
|
-
**Repository:** [github.com/Pukujan/litigation-workflow-application](https://github.com/Pukujan/litigation-workflow-application)
|
|
12
|
-
|
|
13
|
-
## What is included
|
|
14
|
-
|
|
15
|
-
- Backend module auto-loader + frontend route discovery
|
|
16
|
-
- **Inter-module** guardrails (no cross-feature imports; event bus + HTTP)
|
|
17
|
-
- **Intra-module** contract (routes → services → repositories / domain / adapters)
|
|
18
|
-
- Prompts + evals colocated per feature module
|
|
19
|
-
- `lint:architecture`, `npm test`, `npm run test:evals`
|
|
20
|
-
- `_reference` example module (documentation only; not loaded at runtime)
|
|
21
|
-
|
|
22
|
-
## Create a new project (npm CLI)
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm create @pukujan/modular-monolith@2 my-platform
|
|
26
|
-
cd my-platform
|
|
27
|
-
cd backend && npm install && cd ../frontend && npm install
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Publish first: `@pukujan/create-modular-monolith` — see [docs/PUBLISHING.md](./docs/PUBLISHING.md).
|
|
31
|
-
|
|
32
|
-
Local (without publish):
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
node packages/create-modular-monolith/bin/create-modular-monolith.js ../my-platform
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Repo structure
|
|
39
|
-
|
|
40
|
-
```text
|
|
41
|
-
modular-monolith-starter/
|
|
42
|
-
├── backend/src/{core,shared,modules}/
|
|
43
|
-
├── frontend/src/{core,shared,modules}/
|
|
44
|
-
├── docs/architecture/
|
|
45
|
-
├── scripts/new-module.mjs
|
|
46
|
-
└── packages/create-modular-monolith/ # npm CLI
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Run locally (this repo)
|
|
9
|
+
## Quick start
|
|
50
10
|
|
|
51
11
|
```bash
|
|
52
12
|
cd backend && npm install && npm run dev
|
|
@@ -54,20 +14,21 @@ cd backend && npm install && npm run dev
|
|
|
54
14
|
cd frontend && npm install && npm run dev
|
|
55
15
|
```
|
|
56
16
|
|
|
57
|
-
##
|
|
17
|
+
## Architecture commands
|
|
58
18
|
|
|
59
19
|
```bash
|
|
60
|
-
npm run
|
|
20
|
+
npm run lint:contracts # contract manifest paths
|
|
21
|
+
npm run lint:architecture # module boundaries + layers + API docs
|
|
22
|
+
npm run import:file-exchange -- ./my-bundle
|
|
23
|
+
npm run dev-log:pre-push -- --slug initial-setup
|
|
24
|
+
npm run condense:all # consolidated snapshots → file-exchange/exports/
|
|
25
|
+
npm run new:module -- my-feature --label "My Feature"
|
|
61
26
|
```
|
|
62
27
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
## Architecture checks
|
|
28
|
+
## What ships in this template
|
|
66
29
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
npm run test:evals
|
|
71
|
-
```
|
|
30
|
+
- `_reference` + `model-condenser` modules (no domain logic)
|
|
31
|
+
- File exchange, work-log dev logs (human + agent), contract manifest v001
|
|
32
|
+
- Lint and condense tooling for trees, prompts, and schemas
|
|
72
33
|
|
|
73
|
-
|
|
34
|
+
Built with [@pukujan/create-modular-monolith](https://github.com/Pukujan/create-modular-monolith).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Backend — copy to backend/.env
|
|
2
|
+
PORT=3001
|
|
3
|
+
|
|
4
|
+
# OpenRouter (https://openrouter.ai/keys)
|
|
5
|
+
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
6
|
+
MODEL_TEXT_REASONING=google/gemini-2.0-flash-001
|
|
7
|
+
MODEL_VISION_OCR=qwen/qwen2.5-vl-7b-instruct
|
|
8
|
+
OPENROUTER_SITE_URL=http://localhost:5173
|
|
9
|
+
OPENROUTER_APP_NAME=Case Filing AI
|
|
10
|
+
|
|
11
|
+
# Optional batch storage override
|
|
12
|
+
CASE_FILING_BATCH_DIR=
|
|
13
|
+
CASE_FILING_MAX_UPLOAD_MB=25
|
|
14
|
+
|
|
15
|
+
# Model condenser (optional output override)
|
|
16
|
+
MODEL_CONDENSER_OUTPUT_DIR=
|
|
17
|
+
MODEL_CONDENSER_OUTPUT_FILE=consolidated-models.json
|
|
18
|
+
|
|
19
|
+
# Golden dataset eval (default: evals/golden/case_001)
|
|
20
|
+
GOLDEN_DATASET_DIR=
|
|
21
|
+
GOLDEN_CASE_ID=case_001
|
|
22
|
+
|
|
23
|
+
# Eval report bundles copied to repo root (default: eval-bundles/)
|
|
24
|
+
# Case bundle: eval-bundles/{name}/golden/ + runs/{batchId}/
|
|
25
|
+
EVAL_BUNDLE_ROOT_DIR=
|
|
26
|
+
|
|
27
|
+
# Full case export (uploads, outputs, evals, rules, snapshots)
|
|
28
|
+
CASE_EXPORT_ROOT_DIR=
|
|
29
|
+
|
|
30
|
+
# Master prompt (default v1 — same template as before)
|
|
31
|
+
MASTER_PROMPT_VERSION=v1
|
|
32
|
+
MASTER_PROMPT_JSON_RETRY=true
|
|
33
|
+
MASTER_PROMPT_OMIT_AUDIT_NOTES=true
|
|
34
|
+
MASTER_PROMPT_MAX_AUDIT_NOTES=20
|
|
35
|
+
MASTER_PROMPT_MAX_DOC_CHARS=120000
|
|
36
|
+
# compact or v2: compact prompt + structured snapshot merge
|
|
37
|
+
# OPENROUTER_JSON_OBJECT_MODE=true
|
|
38
|
+
OPENROUTER_JSON_OBJECT_MODE=false
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "legal-prmpt-eng-backend",
|
|
3
3
|
"private": true,
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"type": "module",
|
|
@@ -8,13 +8,23 @@
|
|
|
8
8
|
"start": "node src/core/server.js",
|
|
9
9
|
"lint:boundaries": "node scripts/check-module-boundaries.mjs",
|
|
10
10
|
"lint:layers": "node scripts/check-module-layers.mjs",
|
|
11
|
-
"lint:
|
|
11
|
+
"lint:api-docs": "node ../scripts/check-api-docs.mjs",
|
|
12
|
+
"lint:architecture": "npm run lint:boundaries && npm run lint:layers && npm run lint:api-docs",
|
|
12
13
|
"test": "node --test 'src/modules/**/tests/**/*.test.js'",
|
|
14
|
+
"condense-models": "node ../scripts/condense-models.mjs",
|
|
15
|
+
"condense-prompts": "node ../scripts/condense-prompts.mjs",
|
|
16
|
+
"condense-file-structure": "node ../scripts/condense-file-structure.mjs",
|
|
13
17
|
"test:evals": "node ../scripts/run-module-evals.mjs"
|
|
14
18
|
},
|
|
15
19
|
"dependencies": {
|
|
20
|
+
"@napi-rs/canvas": "^1.0.0",
|
|
16
21
|
"cors": "^2.8.5",
|
|
17
22
|
"dotenv": "^16.4.5",
|
|
18
|
-
"express": "^4.19.2"
|
|
23
|
+
"express": "^4.19.2",
|
|
24
|
+
"mammoth": "^1.12.0",
|
|
25
|
+
"multer": "^2.1.1",
|
|
26
|
+
"pdf-parse": "^2.4.5",
|
|
27
|
+
"pdfjs-dist": "^4.10.38",
|
|
28
|
+
"word-extractor": "^1.0.4"
|
|
19
29
|
}
|
|
20
|
-
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Model condenser
|
|
2
|
+
|
|
3
|
+
Scans the repo and writes `models/consolidated-models.json` (JSON schema inventory).
|
|
4
|
+
|
|
5
|
+
**HTTP API:** [docs/model-condenser/API.md](../../../docs/model-condenser/API.md) · [All modules](../../../docs/API.md)
|
|
6
|
+
|
|
7
|
+
**CLI:** `npm run condense-models` (from `backend/`)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
|
|
4
|
+
const repoRoot = join(fileURLToPath(new URL(".", import.meta.url)), "../../../../..");
|
|
5
|
+
|
|
6
|
+
export function getModuleConfig() {
|
|
7
|
+
const modelsDir =
|
|
8
|
+
process.env.MODEL_CONDENSER_OUTPUT_DIR || join(repoRoot, "models");
|
|
9
|
+
return {
|
|
10
|
+
name: "model-condenser",
|
|
11
|
+
label: "Model Condenser",
|
|
12
|
+
repoRoot,
|
|
13
|
+
modelsDir,
|
|
14
|
+
consolidatedFileName:
|
|
15
|
+
process.env.MODEL_CONDENSER_OUTPUT_FILE || "consolidated-models.json"
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** @deprecated Prefer getModuleConfig() */
|
|
20
|
+
export const moduleConfig = getModuleConfig();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function registerModuleEvents(_context) {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createModuleRouter } from "./routes/index.js";
|
|
2
|
+
import { registerModuleEvents } from "./events/index.js";
|
|
3
|
+
import { getModuleConfig } from "./config/index.js";
|
|
4
|
+
import { createModelCondenserFacade } from "./services/modelCondenser.facade.js";
|
|
5
|
+
|
|
6
|
+
export function register(app, context) {
|
|
7
|
+
const config = getModuleConfig();
|
|
8
|
+
const modelCondenser = createModelCondenserFacade({ config });
|
|
9
|
+
const router = createModuleRouter({ config, modelCondenser });
|
|
10
|
+
app.use("/api/model-condenser", router);
|
|
11
|
+
registerModuleEvents(context);
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { getHealth } from "../services/health.service.js";
|
|
3
|
+
|
|
4
|
+
export function createHealthRoutes({ config }) {
|
|
5
|
+
const router = Router();
|
|
6
|
+
router.get("/health", (_req, res) => {
|
|
7
|
+
res.json(getHealth(config));
|
|
8
|
+
});
|
|
9
|
+
return router;
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { createHealthRoutes } from "./health.routes.js";
|
|
3
|
+
import { createModelCondenserRoutes } from "./modelCondenser.routes.js";
|
|
4
|
+
|
|
5
|
+
export function createModuleRouter({ config, modelCondenser }) {
|
|
6
|
+
const router = Router();
|
|
7
|
+
router.use(createHealthRoutes({ config }));
|
|
8
|
+
router.use(createModelCondenserRoutes({ config, modelCondenser }));
|
|
9
|
+
return router;
|
|
10
|
+
}
|