@genvidtech/c3-domain-manager 0.0.1 → 0.6.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.
Files changed (70) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +195 -29
  3. package/dist/adapters/locations.d.ts +22 -0
  4. package/dist/adapters/locations.d.ts.map +1 -0
  5. package/dist/adapters/locations.js +42 -0
  6. package/dist/adapters/locations.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +99 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/domain/classification.d.ts +8 -0
  12. package/dist/domain/classification.d.ts.map +1 -0
  13. package/dist/domain/classification.js +66 -0
  14. package/dist/domain/classification.js.map +1 -0
  15. package/dist/domain/contextMap.d.ts +8 -0
  16. package/dist/domain/contextMap.d.ts.map +1 -0
  17. package/dist/domain/contextMap.js +168 -0
  18. package/dist/domain/contextMap.js.map +1 -0
  19. package/dist/domain/domainAnalysis.d.ts +25 -0
  20. package/dist/domain/domainAnalysis.d.ts.map +1 -0
  21. package/dist/domain/domainAnalysis.js +136 -0
  22. package/dist/domain/domainAnalysis.js.map +1 -0
  23. package/dist/domain/domainGenerator.d.ts +33 -0
  24. package/dist/domain/domainGenerator.d.ts.map +1 -0
  25. package/dist/domain/domainGenerator.js +307 -0
  26. package/dist/domain/domainGenerator.js.map +1 -0
  27. package/dist/domain/editorValidation.d.ts +19 -0
  28. package/dist/domain/editorValidation.d.ts.map +1 -0
  29. package/dist/domain/editorValidation.js +40 -0
  30. package/dist/domain/editorValidation.js.map +1 -0
  31. package/dist/domain/formatting.d.ts +16 -0
  32. package/dist/domain/formatting.d.ts.map +1 -0
  33. package/dist/domain/formatting.js +414 -0
  34. package/dist/domain/formatting.js.map +1 -0
  35. package/dist/domain/glossary.d.ts +20 -0
  36. package/dist/domain/glossary.d.ts.map +1 -0
  37. package/dist/domain/glossary.js +62 -0
  38. package/dist/domain/glossary.js.map +1 -0
  39. package/dist/domain/health.d.ts +14 -0
  40. package/dist/domain/health.d.ts.map +1 -0
  41. package/dist/domain/health.js +21 -0
  42. package/dist/domain/health.js.map +1 -0
  43. package/dist/domain/relationships.d.ts +13 -0
  44. package/dist/domain/relationships.d.ts.map +1 -0
  45. package/dist/domain/relationships.js +74 -0
  46. package/dist/domain/relationships.js.map +1 -0
  47. package/dist/domain/types.d.ts +290 -0
  48. package/dist/domain/types.d.ts.map +1 -0
  49. package/dist/domain/types.js +29 -0
  50. package/dist/domain/types.js.map +1 -0
  51. package/dist/index.d.ts +11 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +12 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/mcp/server.d.ts +3 -0
  56. package/dist/mcp/server.d.ts.map +1 -0
  57. package/dist/mcp/server.js +519 -0
  58. package/dist/mcp/server.js.map +1 -0
  59. package/docs/TOC.md +27 -0
  60. package/docs/decisions/0001-adopt-c3source-extractors.md +67 -0
  61. package/docs/decisions/0002-configurable-locations-adapters-seam.md +72 -0
  62. package/docs/decisions/0003-adopt-loadprojectconfig-schema-first.md +73 -0
  63. package/docs/decisions/0004-adopt-mcp-utils-0.4.0-helpers.md +74 -0
  64. package/docs/decisions/0005-validateforeditor-read-side-diagnostic.md +65 -0
  65. package/docs/decisions/0006-event-variable-reference-coupling.md +77 -0
  66. package/docs/decisions/0007-project-dir-resolverootfolder.md +72 -0
  67. package/docs/decisions/0008-adopt-openproject-option-a.md +74 -0
  68. package/docs/domain-architecture.md +242 -0
  69. package/docs/releasing.md +122 -0
  70. package/package.json +79 -8
@@ -0,0 +1,242 @@
1
+ # Domain Architecture
2
+
3
+ How to organize a Construct 3 project into domains, configure classification, and use the analysis tools.
4
+
5
+ ## Overview
6
+
7
+ A domain in this context is a named grouping of source files (event sheets, layouts, scripts) that map to a coherent user-facing feature area. Grouping files this way makes it easier to:
8
+
9
+ - Find where a change should be made
10
+ - Measure coupling between features
11
+ - Enforce architectural boundaries
12
+
13
+ The groupings are declared in `domain-config.json` at the project root. The `c3-domain-manager` package reads this file to classify files, generate a browsable index, and run health and boundary checks.
14
+
15
+ ## Primary domains vs shared subdomains
16
+
17
+ **Primary domains** represent distinct user experiences — each one owns a vertical slice of the product. Examples: Authentication, Gameplay, Shop & Economy.
18
+
19
+ **Shared subdomains** contain code that is genuinely reused across multiple primary domains. Examples: UI Components, Chat, Analytics.
20
+
21
+ A shared subdomain is worth defining only when both conditions hold:
22
+
23
+ 1. Multiple domains include the same event sheets, layouts, or scripts
24
+ 2. Knowing the subdomain actually narrows down where to look for a change
25
+
26
+ If different domains implement the same concept independently (e.g. each domain has its own reward screen), a shared subdomain would not help — the concept is not shared at the code level.
27
+
28
+ ## domain-config.json structure
29
+
30
+ ```json
31
+ {
32
+ "domains": {
33
+ "Authentication": {
34
+ "description": "Login, device binding, user profile",
35
+ "strategy": "supporting",
36
+ "eventSheetDirs": ["Login", "Profile"],
37
+ "layoutDirs": ["Login"],
38
+ "scriptDirs": ["Auth"],
39
+ "glossary": {
40
+ "session": "An authenticated user session with a backend token"
41
+ }
42
+ }
43
+ },
44
+ "sharedSubdomains": {
45
+ "UI Components": {
46
+ "description": "Reusable UI widgets used across domains",
47
+ "scriptDirs": ["UI"]
48
+ }
49
+ },
50
+ "overrides": {
51
+ "eventSheets/Shared/ChatEvents.json": "Watch Content"
52
+ },
53
+ "relationships": [
54
+ {
55
+ "from": "Gameplay",
56
+ "to": "Authentication",
57
+ "type": "conformist",
58
+ "description": "Gameplay reads the authenticated user ID without influencing Auth"
59
+ }
60
+ ]
61
+ }
62
+ ```
63
+
64
+ ### domains
65
+
66
+ Each entry under `domains` is a primary domain. Fields:
67
+
68
+ | Field | Type | Description |
69
+ |-------|------|-------------|
70
+ | `description` | string | One-line summary of what this domain covers |
71
+ | `strategy` | `"core"` \| `"supporting"` \| `"generic"` | DDD strategic classification (optional) |
72
+ | `eventSheetDirs` | string[] | Subdirectories of `eventSheets/` owned by this domain |
73
+ | `layoutDirs` | string[] | Subdirectories of `layouts/` owned by this domain |
74
+ | `scriptDirs` | string[] | Subdirectories of `scripts/` owned by this domain |
75
+ | `glossary` | Record<string, string> | Domain-specific term definitions (optional) |
76
+
77
+ ### sharedSubdomains
78
+
79
+ Same structure as `domains`. Entries here are flagged as shared in the generated index and health reports.
80
+
81
+ ### overrides
82
+
83
+ A flat map of `relativePath → domainName`. Overrides take precedence over directory-based classification. Use them for files that live in a directory owned by one domain but logically belong to another.
84
+
85
+ Paths are relative to the project root, using forward slashes: `eventSheets/Shared/Chat.json`.
86
+
87
+ ### relationships
88
+
89
+ Optional. Declares the expected integration patterns between domains using DDD relationship types:
90
+
91
+ | Type | Meaning |
92
+ |------|---------|
93
+ | `shared-kernel` | Both teams share a subset of code and coordinate changes |
94
+ | `customer-supplier` | Downstream team (customer) depends on upstream team (supplier) |
95
+ | `conformist` | Downstream conforms to upstream's model without influence |
96
+ | `anti-corruption-layer` | Downstream translates upstream's model through an adapter |
97
+ | `open-host-service` | Upstream publishes a stable protocol for any consumer |
98
+
99
+ Declared relationships are checked by `validate-boundaries`. Observed dependencies (found in event sheet includes and event-variable references) that are not declared produce warnings.
100
+
101
+ ### Validation
102
+
103
+ The config is validated against a lenient zod schema (`DomainConfigSchema`) when loaded. "Lenient" means unknown keys are **tolerated and preserved** (so extra fields you add survive a load→edit→write round-trip through the MCP `set-overrides`/`remove-overrides` tools) and non-essential fields are optional; only `domains` and each domain's `description` are required. A missing file, malformed JSON, or a schema violation produces a clear error prefixed `loadProjectConfig(domain-config.json): …` — from the CLI it aborts the command, and from the MCP server it is returned as a structured tool error.
104
+
105
+ ## File classification rules
106
+
107
+ Files are classified in two steps:
108
+
109
+ 1. **Exact override** — if the file's relative path appears in `overrides`, that domain wins. This has highest priority.
110
+ 2. **Directory prefix** — the file's path (stripped of the file-type root, e.g. `eventSheets/`) is matched against `eventSheetDirs` / `layoutDirs` / `scriptDirs`. The longest matching prefix wins, allowing nested directories to override parent directories.
111
+
112
+ File type roots:
113
+
114
+ | File type | Root directory |
115
+ |-----------|----------------|
116
+ | `eventSheet` | `eventSheets/` |
117
+ | `layout` | `layouts/` |
118
+ | `script` | `scripts/` |
119
+
120
+ Example: a file at `eventSheets/Battle/Skills/ActiveSkills.json` with config `eventSheetDirs: ["Battle"]` matches `Battle/` and is classified under that domain. If a second domain declares `eventSheetDirs: ["Battle/Skills"]`, the longer prefix wins and the file goes to the second domain.
121
+
122
+ Files that match no rule are "uncategorized". Run `c3-domain-manager list-uncategorized` to find them.
123
+
124
+ ## Strategic classification
125
+
126
+ The optional `strategy` field on a domain or subdomain marks its DDD strategic role:
127
+
128
+ - **core** — competitive differentiator; invest heavily, do not outsource
129
+ - **supporting** — necessary but not differentiating; can be built with standard solutions
130
+ - **generic** — commodity capability; prefer off-the-shelf solutions
131
+
132
+ `validate-boundaries` uses this to enforce direction rules. For example, a `supporting` domain should not depend on a `core` domain (that would invert the dependency direction).
133
+
134
+ ## Generated domain index
135
+
136
+ Running `c3-domain-manager generate` (or `regenerate` via MCP) writes files to `extracted/domain-index/`:
137
+
138
+ - `index.md` — master index listing all domains with file counts and descriptions
139
+ - `<DomainName>.md` — per-domain page with:
140
+ - File lists (event sheets, layouts, scripts)
141
+ - Exported function signatures extracted from event sheets
142
+ - Include graph (which sheets include which, within and across domains)
143
+ - Event-variable reference graph (cross-domain references to/from this domain, when present)
144
+ - Cross-domain dependency summary
145
+
146
+ Commit `extracted/domain-index/` to version control so the index is always available without regenerating.
147
+
148
+ ## Paths and locations
149
+
150
+ By default the tool scans `eventSheets/`, `layouts/`, and `scripts/` under the auto-detected C3 project root, reads `domain-config.json` from that root, and writes generated output to `extracted/` there. All three locations can be overridden:
151
+
152
+ | Flag | Default | Effect |
153
+ |------|---------|--------|
154
+ | `--project-dir <path>` | auto-detected (see below) | Sets the C3 project source root — the directory whose `eventSheets/`, `layouts/`, and `scripts/` are scanned. Relative paths resolve against the **current working directory**; absolute paths are used as-is. |
155
+ | `--config <path>` | `<project-root>/domain-config.json` | Selects the domain-config file. |
156
+ | `--extracted <path>` | `<project-root>/extracted` | Selects the domain-index output directory. |
157
+
158
+ Relative paths for `--config` and `--extracted` resolve against the **project root** (as set by `--project-dir` or auto-detection), never the package install directory. Absolute paths are used as-is. Operator-supplied paths are trusted — paths outside the project root are intentionally allowed.
159
+
160
+ **`--project-dir` resolution precedence** (highest to lowest):
161
+
162
+ 1. **`--project-dir <path>`** — explicit flag. Relative resolves against the current working directory; absolute used as-is. No containment restriction — `../sibling` is valid.
163
+ 2. **`C3_PROJECT_DIR` environment variable** — same resolution rules as the flag.
164
+ 3. **Discovery** — the current directory and its immediate children (depth 1) are searched for a directory or file named `project.c3proj` (the Construct 3 project manifest). Exactly one match becomes the project root. Two or more matches produce an ambiguity error: the command prints it and exits non-zero, requiring the user to pass `--project-dir` explicitly. This is the intended behavior for a repository hosting multiple C3 projects.
165
+ 4. **Fallback** — the current working directory (preserves prior behavior when no project marker is found).
166
+
167
+ This resolution is implemented by `resolveProjectRoot` in `src/adapters/locations.ts`, a thin wrapper over `@genvidtech/mcp-utils`'s `resolveRootFolder` that passes `PROJECT_MANIFEST_FILE` (from `@genvidtech/c3source`) as the discovery marker.
168
+
169
+ **Ephemeral mode** — pass `none` as the `--extracted` value to route output into a temporary directory that is automatically deleted when the command finishes (or when the MCP server shuts down on SIGINT/SIGTERM). This is useful as a no-side-effect validation pass: generation runs but leaves no files behind in the project tree.
170
+
171
+ When using the MCP server, the resolved locations are forwarded from the CLI `server` command via `startServer(loc: ResolvedLocations)`. The MCP server itself does not re-run discovery — the root is fixed at startup.
172
+
173
+ ## Cross-domain coupling sources
174
+
175
+ Two independent sources contribute to the observed coupling graph between domains:
176
+
177
+ ### Include coupling
178
+
179
+ Event sheets can include other event sheets using include events. When a sheet in domain A includes a sheet in domain B, that creates an include edge from A to B. The include graph is stored in `DomainData` as `includesFrom` (outgoing: A → B, payload = included sheet names) and `includedBy` (incoming: B ← A, same payload).
180
+
181
+ ### Event-variable reference coupling
182
+
183
+ C3 event sheets can also reference event variables declared in other sheets via System ACEs. When a sheet in domain A references a variable that is declared in domain B, that creates a reference edge from A to B. The reference graph is stored as two sibling maps alongside the include maps: `referencesFrom` (outgoing: A → B, payload = variable names) and `referencedBy` (incoming: B ← A, same payload).
184
+
185
+ **Resolution policy:**
186
+
187
+ - **Global-scope approximation** — only top-level (sheet-root) `variable` events are indexed as declarations. C3 cross-sheet variable references require global variables, and root-level declarations are the global-scope approximation. Local variables declared inside groups or functions are deliberately excluded.
188
+ - **Attribute-to-all on collision** — if the same variable name is declared at the top level of sheets in multiple domains, a reference to that name creates an edge to every declaring domain.
189
+ - **Unresolved references produce no edge** — if the referenced variable name has no indexed (root-level) declaration anywhere in the project, the reference is silently ignored. There is no diagnostics bucket for unresolved names.
190
+ - **Same-domain references produce no edge** — consistent with include coupling, references resolved to the same domain as the referencing sheet are not recorded.
191
+
192
+ **Limitation:** only top-level declarations are indexed. Variables scoped inside a group or function block are not visible across sheets in C3, so excluding them is correct behaviour. A variable declared inside a block but referenced from another sheet would be unresolvable and fall into the "unresolved → no edge" path above.
193
+
194
+ No `domain-config.json` schema change is required — reference coupling is derived entirely from event sheet content and does not need configuration.
195
+
196
+ ### How coupling surfaces in analysis
197
+
198
+ Both coupling sources are aggregated with **union semantics** across all downstream consumers:
199
+
200
+ - **Health metrics** (`computeHealth`) — Ca and Ce count the union of include-coupled and reference-coupled distinct domains, with overlap deduped (a domain that is both include-coupled and reference-coupled is counted only once).
201
+ - **Boundary validation** (`validateBoundaries`) — the undeclared-dependency and forbidden-direction checks operate over the union of include and reference target domains. A reference edge to an undeclared domain produces an `undeclared` violation exactly as an include edge would.
202
+ - **Context map** (`generateContextMap`) — reference coupling surfaces as a distinct `observed-ref` edge kind. In text format it appears as `[observed-ref]`; in Mermaid it renders as `-.->|var|`. Edge precedence is: declared > observed (include) > observed-ref. An include and a reference to the same domain pair produce only the higher-precedence edge.
203
+ - **Domain pages** (`formatDomainPage`) — the "Cross-Domain Dependencies" section gains two subsections: "Event-variable references from this domain" and "Event-variable references into this domain", rendered only when the respective map is non-empty.
204
+
205
+ ## Health metrics
206
+
207
+ `domain-health` (MCP tool or library `computeHealth`) computes per-domain:
208
+
209
+ - **Ca (afferent coupling)** — how many other domains depend on this domain (via includes or event-variable references)
210
+ - **Ce (efferent coupling)** — how many domains this domain depends on (via includes or event-variable references)
211
+ - **Instability** — `Ce / (Ca + Ce)`, range 0–1. 0 is maximally stable (nothing it depends on can break it); 1 is maximally unstable (many dependencies, no dependents)
212
+
213
+ High instability in a core domain is a warning sign.
214
+
215
+ ## Boundary validation
216
+
217
+ `validate-boundaries` (MCP tool or library `validateBoundaries`) checks:
218
+
219
+ - **Undeclared dependencies** — domain A includes sheets from domain B, or references event-variables declared in domain B, but no relationship is declared from A to B
220
+ - **Stale declarations** — a declared relationship has no corresponding observed dependency
221
+ - **Forbidden directions** — e.g. a `supporting` domain depending on a `core` domain
222
+
223
+ Filter to a single domain by passing the `domain` parameter.
224
+
225
+ ## Glossary collision detection
226
+
227
+ Each domain can define a `glossary` map of terms to definitions. `glossary-check` collects all definitions across domains and reports terms that appear with different definitions in different domains. These collisions indicate shared language that may need alignment.
228
+
229
+ ## Editor-strictness validation
230
+
231
+ `validate-editor` (CLI subcommand or MCP `READ_ONLY` tool "Validate Editor Strictness") checks whether the target project's event sheets are structurally valid from the C3 editor's perspective. It re-walks `eventSheets/` fresh from disk, attributes each sheet to a domain via `classifyFile`, and runs `@genvidtech/c3source`'s `validateForEditor` per sheet. Issues are grouped by sheet; sheets that match no domain classification are reported under `"(unclassified)"`.
232
+
233
+ This is a read-side diagnostic only. `c3-domain-manager` never writes or modifies event sheets — the report surfaces sheets the C3 editor would refuse to import (e.g. a `variable` event missing its `comment` field, or a `group` event missing its `description`) so you can fix them in the C3 editor.
234
+
235
+ Because it reads sheets directly from disk, the MCP tool does not append the stale-index warning that other read tools emit — index freshness is irrelevant to its output.
236
+
237
+ ## Maintenance
238
+
239
+ - After adding or renaming files, run `c3-domain-manager list-uncategorized` to confirm coverage
240
+ - After deleting files, run `c3-domain-manager list-stale-overrides` to clean up orphaned override entries
241
+ - Regenerate the domain index after any `domain-config.json` change: `c3-domain-manager generate`
242
+ - To check event sheets for C3 editor compatibility: `c3-domain-manager validate-editor`
@@ -0,0 +1,122 @@
1
+ # Releasing
2
+
3
+ How to cut a new release of `@genvidtech/c3-domain-manager`. Routine releases are
4
+ fully self-service — this repo is already wired for OIDC **trusted publishing**,
5
+ so there is no npm token to manage and nothing in the `publish-npm-package` skill
6
+ to re-run (that skill is one-time setup, not per-release).
7
+
8
+ ## TL;DR
9
+
10
+ ```bash
11
+ # 1. Land all release content on main first (the tag publishes whatever main points at).
12
+ # 2. Bump the version (patch for fixes, minor for features) — updates all 3 spots, no commit/tag:
13
+ npm version X.Y.Z --no-git-tag-version
14
+ # 3. Commit + tag + push:
15
+ git add package.json package-lock.json
16
+ git commit -m "chore: Release X.Y.Z" # see message shape below
17
+ git tag vX.Y.Z # lightweight tag — matches recent convention
18
+ git push origin main
19
+ git push origin vX.Y.Z # this push triggers the publish workflow
20
+ # 4. After it publishes: file the downstream plugin update request (step 7).
21
+ ```
22
+
23
+ ## Step by step
24
+
25
+ 1. **Bump the version.** Choose the bump per semver — patch (`0.1.2 → 0.1.3`) for a
26
+ bug fix, minor for a backward-compatible feature. **At `0.x`, a breaking change to
27
+ the public API takes a minor bump even when the work is a bug fix** — removing or
28
+ renaming an exported function/type (anything re-exported from `src/index.ts`) is
29
+ the pre-1.0 "breaking" signal. Example: `0.1.3 → 0.2.0` for issue #5, which fixed
30
+ the extraction by retiring the public `extractIncludes`/`extractFunctions` exports.
31
+ Run `npm version X.Y.Z --no-git-tag-version` — it updates all **three** spots and
32
+ makes **no commit and no tag**, so you keep control of the message and tag style
33
+ below:
34
+ - `package.json` → `"version"`
35
+ - `package-lock.json` → the top-level `"version"`
36
+ - `package-lock.json` → `packages."".version` (the root package entry, ~line 9)
37
+
38
+ (You can edit the three spots by hand instead, but that risks missing the second
39
+ `package-lock.json` spot; the flag-driven bump is safer. See the note below.)
40
+
41
+ 2. **Commit** with the project's release-commit shape — a `chore: Release X.Y.Z`
42
+ subject, a short body summarising what the release contains (issue refs welcome),
43
+ and the standard co-author trailer:
44
+
45
+ ```
46
+ chore: Release 0.1.3
47
+
48
+ Patch release fixing `--version` reporting "unknown" instead of the
49
+ package version (#3).
50
+
51
+ Co-Authored-By: <current model> <noreply@anthropic.com>
52
+ ```
53
+
54
+ 3. **Tag.** Use a **lightweight** tag matching the recent convention
55
+ (`v0.1.1`, `v0.1.2`, `v0.1.3` are lightweight; only the original `v0.1.0` was
56
+ annotated):
57
+
58
+ ```bash
59
+ git tag vX.Y.Z
60
+ ```
61
+
62
+ 4. **Push the commit, then the tag.** The tag is what triggers publishing:
63
+
64
+ ```bash
65
+ git push origin main
66
+ git push origin vX.Y.Z
67
+ ```
68
+
69
+ 5. **Watch the publish.** The tag push fires `.github/workflows/publish.yml`
70
+ (trigger: `push` on `v*.*.*`). It runs the shared `public-github-actions` node-gate,
71
+ then publishes to npm via OIDC trusted publishing (automatic provenance, no
72
+ stored token). Confirm:
73
+
74
+ ```bash
75
+ gh run list --workflow Publish --limit 1
76
+ npm view @genvidtech/c3-domain-manager version # should show the new version as latest
77
+ ```
78
+
79
+ 6. **Smoke-check the CLI version** (catches the class of bug that motivated this doc):
80
+
81
+ ```bash
82
+ npx -y @genvidtech/c3-domain-manager@X.Y.Z --version # prints X.Y.Z, not "unknown"
83
+ ```
84
+
85
+ 7. **File the downstream plugin update request.** The `genvid-c3` plugin
86
+ (`GenvidTechnologies/claude-code-plugin-gvt-construct3`) **pins** this package in
87
+ `plugin/.claude-plugin/plugin.json` (`mcpServers.c3-domain-manager`, e.g.
88
+ `@genvidtech/c3-domain-manager@0.3.0`) and references the pinned version in its
89
+ `c3-explorer` / `c3-implementer` agent docs. Every publish here therefore needs a
90
+ follow-up issue there to bump the pin and reconcile the tool surface. Open one with
91
+ `gh issue create --repo GenvidTechnologies/claude-code-plugin-gvt-construct3`, and call out
92
+ any **MCP tool-surface change** (a tool added/renamed/removed) — that repo runs
93
+ `docs/tool-surface-reconciliation.md` and updates the `c3-explorer` `tools:`
94
+ allow-list off it. Example: 0.4.0 added the `validate-editor` READ_ONLY tool, so the
95
+ request flagged it for the allow-list (issue
96
+ [#12](https://github.com/GenvidTechnologies/claude-code-plugin-gvt-construct3/issues/12)).
97
+
98
+ ## Notes & gotchas
99
+
100
+ - **`process.cwd()` is the target project, not this package.** The CLI reads its
101
+ own version from `package.json` resolved via `import.meta.url`. If you add files
102
+ the published CLI must read at runtime, resolve them relative to the module, never
103
+ `cwd`. See the "TypeScript / module setup" section in `CLAUDE.md`.
104
+ - **Why `npm version --no-git-tag-version` and not a bare `npm version`?** A bare
105
+ `npm version patch` bumps all three spots but *also* makes a commit (default message
106
+ `X.Y.Z`) and an **annotated** tag — neither matches the `chore: Release X.Y.Z` +
107
+ lightweight-tag + co-author-trailer convention. The `--no-git-tag-version` flag keeps
108
+ the correct three-spot bump while making no commit and no tag, so you commit and
109
+ lightweight-tag by hand (steps 2–4) to match the convention. Hand-editing the three
110
+ spots also works but risks missing the second `package-lock.json` spot
111
+ (`packages."".version`).
112
+ - **If the version bump already landed with the feature/fix branch**, the release step
113
+ is just *tag the merge commit* — there's no need for a separate `chore: Release X.Y.Z`
114
+ commit. The tag publishes whatever `main` points at, and `main` already carries the
115
+ bumped version. (This is how issue #5 shipped: `package.json`/`package-lock.json` were
116
+ bumped to `0.2.0` in the fix branch, so releasing it is a one-step `git tag v0.2.0`.)
117
+ - **A republish of an already-published version is rejected by npm.** If the publish
118
+ workflow fails *after* the version was published, bump to the next patch rather than
119
+ retrying the same version.
120
+ - **Publish entry-point pitfall:** keep `main`/`types`/`exports` at the top level of
121
+ `package.json` pointing at `./dist/...`; do not move them into `publishConfig`
122
+ (see the "Publish pitfall" note in `CLAUDE.md`). Verify against `npm pack` if in doubt.
package/package.json CHANGED
@@ -1,10 +1,81 @@
1
1
  {
2
- "name": "@genvidtech/c3-domain-manager",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @genvidtech/c3-domain-manager",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
2
+ "name": "@genvidtech/c3-domain-manager",
3
+ "version": "0.6.1",
4
+ "description": "Analyzes Construct 3 projects through a domain-driven-design lens: classifies eventSheets/layouts/scripts into named domains and produces a domain index, health/coupling metrics, boundary validation, glossary checks, and a context map. Exposed as both a CLI and an MCP server.",
5
+ "license": "MIT-0",
6
+ "author": "Genvid Technologies, inc. <support@genvidtech.com>",
7
+ "homepage": "https://github.com/GenvidTechnologies/c3-domain-manager#readme",
8
+ "bugs": "https://github.com/GenvidTechnologies/c3-domain-manager/issues",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/GenvidTechnologies/c3-domain-manager.git"
12
+ },
13
+ "keywords": [
14
+ "construct3",
15
+ "construct",
16
+ "domain-driven-design",
17
+ "ddd",
18
+ "mcp",
19
+ "model-context-protocol",
20
+ "static-analysis"
21
+ ],
22
+ "type": "module",
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "bin": {
26
+ "c3-domain-manager": "./dist/cli.js"
27
+ },
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "./mcp": {
34
+ "types": "./dist/mcp/server.d.ts",
35
+ "default": "./dist/mcp/server.js"
36
+ }
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "docs",
41
+ "LICENSE",
42
+ "README.md"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "overrides": {
48
+ "serialize-javascript": "^7.0.5"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc && node -e \"const fs=require('fs');const f='dist/cli.js';const c=fs.readFileSync(f,'utf8');if(!c.startsWith('#!')){fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c)}\"",
52
+ "prepack": "npm run build",
53
+ "test": "mocha --timeout 5000 --import=tsx --require ./test/setup.ts 'test/**/*.test.ts' --exit",
54
+ "lint": "eslint --ext .ts --max-warnings 0 src/ test/",
55
+ "typecheck": "tsc -p tsconfig.test.json --noEmit"
56
+ },
57
+ "engines": {
58
+ "node": ">=22"
59
+ },
60
+ "dependencies": {
61
+ "@genvidtech/c3source": "^1.7.0",
62
+ "@genvidtech/mcp-utils": "^0.5.1",
63
+ "@modelcontextprotocol/sdk": "^1.27.1",
64
+ "yargs": "^17.7.2",
65
+ "zod": "^3.23.0"
66
+ },
67
+ "devDependencies": {
68
+ "@types/chai": "^4.3.16",
69
+ "@types/mocha": "^10.0.6",
70
+ "@types/node": "^22.0.0",
71
+ "@types/yargs": "^17.0.33",
72
+ "@typescript-eslint/eslint-plugin": "^7.10.0",
73
+ "@typescript-eslint/parser": "^7.10.0",
74
+ "chai": "^5.1.1",
75
+ "eslint": "^8.36.0",
76
+ "eslint-config-prettier": "^8.7.0",
77
+ "mocha": "^10.4.0",
78
+ "tsx": "^4.21.0",
79
+ "typescript": "^5.4.5"
80
+ }
10
81
  }