mnemonica 1.0.0 → 1.0.6

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 (92) hide show
  1. package/.ai/ONBOARDING.md +1 -1
  2. package/.ai/ask/AGENTS.md +15 -9
  3. package/.ai/async_init.md +2 -2
  4. package/.ai/rules-skill/contributing.md +1 -1
  5. package/.ai/rules-skill/define-patterns.md +8 -2
  6. package/.ai/rules-skill/ecosystem.md +4 -4
  7. package/.ai/rules-skill/instance-methods.md +48 -15
  8. package/.ai/rules-skill/type-system.md +12 -2
  9. package/AGENTS.md +6 -2
  10. package/CONTRIBUTING.md +61 -9
  11. package/FOR_HUMANS.md +149 -239
  12. package/README.md +75 -40
  13. package/SKILL.md +1 -1
  14. package/build/api/errors/exceptionConstructor.js +20 -12
  15. package/build/api/errors/index.js +9 -5
  16. package/build/api/errors/throwModificationError.js +15 -9
  17. package/build/api/index.js +35 -2
  18. package/build/api/types/InstanceCreator.js +5 -2
  19. package/build/api/types/Mnemosyne.d.ts +6 -6
  20. package/build/api/types/Mnemosyne.js +43 -120
  21. package/build/api/types/Props.js +5 -3
  22. package/build/api/types/TypeProxy.js +13 -9
  23. package/build/api/types/compileNewModificatorFunctionBody.js +14 -8
  24. package/build/api/types/index.js +56 -13
  25. package/build/api/utils/index.js +21 -12
  26. package/build/constants/index.js +11 -8
  27. package/build/descriptors/types/index.js +79 -26
  28. package/build/index.d.ts +4 -4
  29. package/build/index.js +62 -15
  30. package/build/types/index.d.ts +52 -31
  31. package/build/types/index.js +1 -1
  32. package/build/utils/clone.d.ts +1 -0
  33. package/build/utils/clone.js +11 -0
  34. package/build/utils/collectConstructors.js +5 -3
  35. package/build/utils/exception.d.ts +1 -0
  36. package/build/utils/exception.js +14 -0
  37. package/build/utils/extract.d.ts +2 -3
  38. package/build/utils/extract.js +3 -2
  39. package/build/utils/fork.d.ts +1 -0
  40. package/build/utils/fork.js +33 -0
  41. package/build/utils/index.d.ts +2 -3
  42. package/build/utils/index.js +21 -7
  43. package/build/utils/merge.d.ts +2 -1
  44. package/build/utils/merge.js +10 -6
  45. package/build/utils/parent.d.ts +1 -1
  46. package/build/utils/parent.js +3 -2
  47. package/build/utils/parse.d.ts +2 -12
  48. package/build/utils/parse.js +1 -1
  49. package/build/utils/pick.d.ts +4 -3
  50. package/build/utils/pick.js +4 -5
  51. package/build/utils/sibling.d.ts +1 -0
  52. package/build/utils/sibling.js +25 -0
  53. package/build/utils/toJSON.d.ts +1 -1
  54. package/build/utils/toJSON.js +3 -2
  55. package/docs/UTILS.md +184 -0
  56. package/docs/ai-learning-trajectory.md +1 -1
  57. package/docs/async-constructors.md +3 -1
  58. package/docs/empathy-in-ai.md +170 -0
  59. package/docs/hott-primer.md +47 -0
  60. package/docs/performance-vs-security.md +395 -0
  61. package/docs/purpose.md +38 -7
  62. package/docs/tactica-pattern.md +10 -10
  63. package/docs/theory-of-operations.md +224 -0
  64. package/docs/typed-lookup.md +12 -12
  65. package/docs/typeomatica.md +1 -1
  66. package/package.json +13 -6
  67. package/src/api/errors/exceptionConstructor.ts +14 -9
  68. package/src/api/errors/index.ts +8 -4
  69. package/src/api/errors/throwModificationError.ts +10 -9
  70. package/src/api/types/InstanceCreator.ts +5 -8
  71. package/src/api/types/Mnemosyne.ts +72 -231
  72. package/src/api/types/Props.ts +4 -2
  73. package/src/api/types/TypeProxy.ts +7 -11
  74. package/src/api/types/compileNewModificatorFunctionBody.ts +13 -7
  75. package/src/api/types/index.ts +15 -8
  76. package/src/api/utils/index.ts +16 -14
  77. package/src/constants/index.ts +6 -9
  78. package/src/descriptors/types/index.ts +44 -24
  79. package/src/index.ts +28 -21
  80. package/src/types/index.ts +101 -69
  81. package/src/utils/clone.ts +11 -0
  82. package/src/utils/collectConstructors.ts +4 -2
  83. package/src/utils/exception.ts +16 -0
  84. package/src/utils/extract.ts +5 -2
  85. package/src/utils/fork.ts +57 -0
  86. package/src/utils/index.ts +32 -13
  87. package/src/utils/merge.ts +18 -6
  88. package/src/utils/parent.ts +4 -6
  89. package/src/utils/parse.ts +5 -4
  90. package/src/utils/pick.ts +10 -2
  91. package/src/utils/sibling.ts +33 -0
  92. package/src/utils/toJSON.ts +3 -2
package/.ai/ONBOARDING.md CHANGED
@@ -25,7 +25,7 @@ const admin = new user.Admin({ role: 'admin' }); // inherits from user instance
25
25
 
26
26
  **Why not TypeScript interfaces alone?** TypeScript is structural at compile time: a `Payment` and an `Invoice` with identical fields are interchangeable to the type checker. At runtime, `processPayment(invoice)` silently succeeds and produces wrong results. mnemonica's runtime types are nominal — the type IS its name, established at `define()` time and stable thereafter.
27
27
 
28
- **Why not Object.assign / spread?** `{...raw, ...apiResult}` is one flat object with no lineage. You cannot answer "which step set `amount`?" without reading the source. mnemonica's prototype chain preserves every ancestor; `enriched.parent('ApiResult')` returns the exact API response object.
28
+ **Why not Object.assign / spread?** `{...raw, ...apiResult}` is one flat object with no lineage. You cannot answer "which step set `amount`?" without reading the source. mnemonica's prototype chain preserves every ancestor; `utils.parent(enriched, 'ApiResult')` returns the exact API response object.
29
29
 
30
30
  ---
31
31
 
package/.ai/ask/AGENTS.md CHANGED
@@ -37,7 +37,7 @@ Creates type constructors with special inheritance capabilities:
37
37
  ### 3. Proxy Architecture
38
38
 
39
39
  - **TypeProxy** — Wraps type constructors, handles `.call`, `.apply`
40
- - **Mnemosyne** — Manages instance prototype chain, provides `.fork()`, `.parent()`
40
+ - **Mnemosyne** — Manages instance prototype chain
41
41
  - **TypesCollectionProxy** — Manages type registry, handles type lookup
42
42
 
43
43
  ### 4. Symbol System
@@ -68,15 +68,21 @@ const TypeProxy = new Proxy(Constructor, {
68
68
  });
69
69
  ```
70
70
 
71
- ## Explaining Instance Methods
71
+ ## Explaining Instance Introspection
72
72
 
73
- | Method | Purpose | Defined In |
74
- |--------|---------|------------|
75
- | `.fork()` | Create shallow copy | Mnemosyne.ts |
76
- | `.parent()` | Access parent instance | Mnemosyne.ts |
77
- | `.pick()` | Extract specific properties | Mnemosyne.ts |
78
- | `.extract()` | Get all inherited properties | extract.ts |
79
- | `.parse()` | Parse instance structure | parse.ts |
73
+ Starting from v1.0.6 the legacy instance methods are no longer auto-injected.
74
+ Use the standalone `utils` export:
75
+
76
+ | Utility | Purpose | Defined In |
77
+ |---------|---------|------------|
78
+ | `utils.fork(instance)` | Create a fork constructor | fork.ts |
79
+ | `utils.parent(instance)` | Access parent instance | parent.ts |
80
+ | `utils.pick(instance, ...keys)` | Extract specific properties | pick.ts |
81
+ | `utils.extract(instance)` | Get all inherited properties | extract.ts |
82
+ | `utils.parse(instance)` | Parse instance structure | parse.ts |
83
+
84
+ To restore the old `instance.fork()` / `instance.extract()` style, attach the
85
+ methods to the constructor's prototype before calling `define()`.
80
86
 
81
87
  ## Test Framework Differences
82
88
 
package/.ai/async_init.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  JavaScript class constructors cannot be declared `async`. However, a constructor **can return a Promise**. When a base class constructor returns `Promise.resolve(this)`, the subclass `this` becomes the Promise object — class fields initialize on the Promise wrapper, not the real instance. This breaks field inheritance in raw JS.
6
6
 
7
- Mnemonica handles this correctly through its wrapper architecture. See also the [abstract demonstration](../../async_test/README.md) showing the problem and wrapper fix in library-agnostic terms.
7
+ Mnemonica handles this correctly through its wrapper architecture. See also the [test suite](../test_async/index.js) showing the problem and wrapper fix in practice.
8
8
 
9
9
  ## How Mnemonica Preserves Class Fields
10
10
 
@@ -89,6 +89,6 @@ Tests live in `test_async/index.js` and run via `npm run test:async_init`.
89
89
 
90
90
  ## Related
91
91
 
92
- - [Abstract async test demonstration](../../async_test/README.md) — library-agnostic explanation of the problem and wrapper fix
92
+ - [`test_async/index.js`](../test_async/index.js) — test suite covering async initialization scenarios
93
93
  - [TC39 proposal-async-init issue #3](https://github.com/tc39/proposal-async-init/issues/3) — language-level discussion of the same problem
94
94
  - [Mnemonica README](../README.md) — project overview and API documentation
@@ -57,7 +57,7 @@ Before implementing, I need to clarify:
57
57
  1. **Scope**: Should this config be per-type or per-collection?
58
58
  2. **Proxy compatibility**: TypeProxy handles `.get`, `.set`, `.construct`.
59
59
  Adding config requires checking all three traps.
60
- 3. **Existing options**: `strictChain`, `blockErrors`, `exposeInstanceMethods`
60
+ 3. **Existing options**: `strictChain`, `blockErrors`, `awaitReturn`
61
61
  already exist. Does this fit the pattern?
62
62
  4. **TypeRegistry impact**: Will tactica need to regenerate types?
63
63
 
@@ -3,7 +3,7 @@ name: mnemonica-define-patterns
3
3
  description: |
4
4
  Patterns for defining types and subtypes with mnemonica's define() function.
5
5
  Use when the user asks about define(), creating types, subtype inheritance,
6
- strictChain, blockErrors, exposeInstanceMethods, or type configuration options.
6
+ strictChain, blockErrors, awaitReturn, or type configuration options.
7
7
  metadata:
8
8
  tags: [mnemonica, define, types, subtypes, inheritance]
9
9
  ---
@@ -71,9 +71,15 @@ define('Parent.Child', function (this: Child, data: Data) {
71
71
  | `blockErrors` | `true` | Block construction if error exists in prototype chain |
72
72
  | `submitStack` | `false` | Collect stack trace as `__stack__` property |
73
73
  | `awaitReturn` | `true` | `await new Constructor()` must return a value |
74
- | `exposeInstanceMethods` | `true` | Expose `extract()`, `fork()`, etc. on instance |
75
74
  | `asClass` | auto-detected | Force class mode detection |
76
75
 
76
+ ## Instance Method Opt-In
77
+
78
+ Starting from v1.0.6, `extract()`, `pick()`, `parent()`, `fork()`, `exception()`,
79
+ `sibling()`, and `clone()` are **not** auto-injected on instances. Use the standalone
80
+ `utils` export, or attach the methods to the constructor's prototype before calling
81
+ `define()`.
82
+
77
83
  ## Before/After: strictChain
78
84
 
79
85
  **Before** (strictChain: false — allows broken chains)
@@ -56,7 +56,7 @@ supports different users.
56
56
 
57
57
  | Environment | Tools |
58
58
  |-------------|-------|
59
- | **VS Code** | Mnemographica extension, Tactica LSP, Mnemonica Logger |
59
+ | **VS Code** | Mnemographica extension, Tactica CLI, Mnemonica Logger |
60
60
  | **Runtime (Node.js)** | CDP Connection (port 9229), Strategy MCP (ports 9230/9231) |
61
61
 
62
62
  #### Collaboration Modes
@@ -76,7 +76,7 @@ supports different users.
76
76
  │ Mnemonica Ecosystem │
77
77
  ├─────────────────────────────────────────┤
78
78
  │ mnemographica │ VS Code Extension │
79
- │ tactica │ Type Generator/LSP
79
+ │ tactica │ Type Generator/CLI
80
80
  │ strategy │ MCP Server │
81
81
  │ topologica │ Module Loader │
82
82
  │ mnemonica │ Core Runtime │
@@ -88,7 +88,7 @@ supports different users.
88
88
 
89
89
  ### Integration Points
90
90
 
91
- 1. **Tactica → VS Code**: Language Service Plugin
91
+ 1. **Tactica → VS Code**: CLI type generator
92
92
  2. **Strategy → CDP**: Runtime evaluation
93
93
  3. **Mnemographica → Strategy**: HTTP/WebSocket servers
94
94
  4. **All → Topologica**: Module loading
@@ -136,5 +136,5 @@ interface Runnable { run(): void; }
136
136
 
137
137
  ## References
138
138
 
139
- - [Wikipedia: PACT (interaction design)](https://en.wikipedia.org/wiki/PACT_(interaction_design))
139
+ - [Wikipedia: PACT (interaction design)](https://en.wikipedia.org/wiki/PACT_%28interaction_design%29)
140
140
  - `strategy/README.md` — MCP architecture
@@ -2,33 +2,66 @@
2
2
  name: mnemonica-instance-methods
3
3
  description: |
4
4
  Instance methods and properties in mnemonica: extract, pick, parent, fork,
5
- clone, getProps, and the internal __self__ reference. Use when the user asks
6
- about instance introspection, prototype chain traversal, forking instances,
7
- or the internal props system.
5
+ clone, sibling, exception, getProps, and the internal __self__ reference.
6
+ Starting from v1.0.6 these convenience methods are no longer auto-injected;
7
+ use the standalone utils.* API or attach them to a constructor prototype before
8
+ calling define().
8
9
  metadata:
9
10
  tags: [mnemonica, instances, methods, introspection, prototype]
10
11
  ---
11
12
 
12
13
  # Instance Methods
13
14
 
14
- ## Available Methods
15
+ For the type-level details of the corresponding standalone utilities
16
+ (`utils.extract`, `utils.pick`, `utils.parent`, `utils.fork`, `utils.clone`,
17
+ `utils.sibling`, `utils.exception`), see [`docs/UTILS.md`](../../docs/UTILS.md).
15
18
 
16
- | Method | Description |
17
- |--------|-------------|
18
- | `extract()` | Returns all enumerable properties as a plain object |
19
- | `pick(...keys)` | Returns selected properties |
20
- | `parent()` | Returns the parent instance in the prototype chain |
21
- | `parent(path)` | Looks up parent by constructor name |
22
- | `fork(...args)` | Creates a new instance with same or different args |
23
- | `clone` | Alias for `fork()` with no arguments |
24
- | `exception(error, ...args)` | Creates an error with context |
25
- | `sibling(name)` | Finds a sibling type by name |
19
+ ## Standalone Utilities (Default)
20
+
21
+ Starting from v1.0.6 the convenience methods are **not** exposed on instances by
22
+ default. Import them from the `utils` export:
23
+
24
+ ```typescript
25
+ import { utils } from 'mnemonica';
26
+
27
+ utils.extract(instance);
28
+ utils.pick(instance, 'name', 'age');
29
+ utils.parent(instance, 'UserType');
30
+ utils.fork(instance)(newArgs);
31
+ utils.clone(instance);
32
+ utils.sibling(instance);
33
+ utils.exception(instance, new Error('oops'));
34
+ ```
35
+
36
+ All utilities infer their type parameter from the instance argument.
37
+
38
+ ## Legacy Instance-Method Style (Opt-In)
39
+
40
+ To restore the old `instance.extract()` style for a root constructor, attach the
41
+ methods to its prototype **before** passing it to `define()`. See
42
+ `test/instance-methods-helper.js` for the full reference pattern.
43
+
44
+ ```typescript
45
+ import { define, utils } from 'mnemonica';
46
+
47
+ function UserType(data) {
48
+ Object.assign(this, data);
49
+ }
50
+
51
+ Object.defineProperty(UserType.prototype, 'extract', {
52
+ get() { return () => utils.extract(this); }
53
+ });
54
+
55
+ const User = define('User', UserType);
56
+ const user = new User({ name: 'Ada' });
57
+ user.extract(); // works
58
+ ```
26
59
 
27
60
  ## Internal Props System
28
61
 
29
62
  Instance metadata is stored externally via `WeakMap` against the prototype object,
30
63
  not the instance itself. This keeps instance enumeration clean — internal props
31
- never show up in `for...in`, `Object.keys`, or `JSON.stringify`.
64
+ never show up in `for...in`, `Object.keys()`, or `JSON.stringify()`.
32
65
 
33
66
  ```typescript
34
67
  const props = getProps(instance);
@@ -26,7 +26,8 @@ type UserData = { name: string; age: number; };
26
26
  // ❌ WRONG - Instance is NOT an interface!
27
27
  interface UserData { name: string; age: number; }
28
28
 
29
- // ✅ CORRECT - Constructor/Prototype contract uses INTERFACE
29
+ // ✅ CORRECT - Constructor/Prototype contract uses INTERFACE (when attaching
30
+ // legacy instance methods to the prototype before define())
30
31
  interface MnemonicaInstance {
31
32
  extract(): Record<string, unknown>;
32
33
  parent(): object | undefined;
@@ -78,7 +79,7 @@ from (prototype, arguments, config). The resulting constructor is simultaneously
78
79
 
79
80
  - a runtime value (callable, `new`-able, with `.prototype`)
80
81
  - a node in the type Trie (carries `.subtypes`, participates in `instanceof`)
81
- - a behavioral contract (the prototype chain provides `.extract()`, `.fork()`, etc.)
82
+ - a behavioral contract (the prototype chain provides the user's own properties; legacy instance methods must be attached explicitly if desired)
82
83
 
83
84
  Augmented to user-specific types via a `TypeRegistry` declaration-merge — hand-written or generated by tactica.
84
85
 
@@ -112,3 +113,12 @@ const AdminType = UserType.define('AdminType', function (this: AdminType) {
112
113
  this.role = 'admin';
113
114
  });
114
115
  ```
116
+
117
+ ## Generic Public Utilities
118
+
119
+ The standalone utilities in `utils` infer their type parameters from the instance
120
+ argument. Callers should never need an explicit `<T>` cast for ordinary operations.
121
+
122
+ The full reference — helper types (`Extracted`, `Merge`, `InstanceResult`,
123
+ `Parsed`, `SiblingAccessor`), every utility signature, and the type-level
124
+ explanation of `utils.merge` — lives in [`docs/UTILS.md`](../../docs/UTILS.md).
package/AGENTS.md CHANGED
@@ -78,6 +78,8 @@ npm run watch # watch mode
78
78
 
79
79
  **Must run `npm run test:cov` before completing any task.**
80
80
 
81
+ **Documentation changes:** When modifying any `.md` file, `npm run lint:md` is mandatory. It checks for broken links and anchors. Run it and fix any reported issues before finishing.
82
+
81
83
  ## Code Style (Project-Specific)
82
84
 
83
85
  See [`.ai/rules-skill/code-style.md`](./.ai/rules-skill/code-style.md) for the full style reference. Key rules: tabs only, space before function parens, colons aligned in object literals, `strict: true`, **no `any`** (`no-explicit-any: error`).
@@ -172,9 +174,11 @@ For test passing confirmations (e.g., `npm run test:cov`), checking the end of t
172
174
 
173
175
  These configuration files define the project's strict standards. Any changes require user approval first.
174
176
 
175
- ## Return Statement Design Rule
177
+ ## Return Statement Design Rule (Non-negotiable)
178
+
179
+ **Every return expression must go through an intermediate variable/constant.** No exceptions. This is critical for debuggability with `npm run debug` and Chrome Dev Tools — when execution pauses on `return result`, you can hover your mouse over `result` and inspect the value. With `return SomeFn(arg)`, the value is gone before the debugger can show it.
176
180
 
177
- **Always use an intermediate variable before returning.** This is critical for debuggability with `npm run debug` and Chrome Dev Tools.
181
+ **This rule is enforced. If you write `return new Foo()` or `return fn()`, the PR will be rejected.**
178
182
 
179
183
  ### Prohibited patterns:
180
184
  ```typescript
package/CONTRIBUTING.md CHANGED
@@ -26,6 +26,12 @@ npm run test:jest:cov
26
26
  `src/` → `build/`. To run linters with auto-fix, use `npm run lint:fix`.
27
27
  To run linters in read-only mode (CI parity), use `npm run lint:check`.
28
28
 
29
+ ### Doc-only changes
30
+
31
+ If your change touches only Markdown files (no `src/`, `test/`, `test-jest/`,
32
+ `test-ts/`, or build config), you can **skip `npm run build` and the test
33
+ suites**. Run `npm run lint:md` to catch dead links and broken anchors instead.
34
+
29
35
  ## Test frameworks
30
36
 
31
37
  There are two suites and both must stay green:
@@ -47,7 +53,7 @@ Conventional commits are preferred:
47
53
  ```
48
54
  feat: add lookupTyped overload for nested registry
49
55
  fix(InstanceCreator): preserve __args__ across async chain
50
- docs: clarify exposeInstanceMethods default
56
+ docs: clarify instance method opt-in pattern
51
57
  chore(ci): bump setup-node to v4
52
58
  ```
53
59
 
@@ -100,13 +106,59 @@ Per [AGENTS.md](AGENTS.md):
100
106
  - The build must produce **zero** ESLint warnings on `./src` — fix the
101
107
  source, do not relax the rules.
102
108
 
109
+ ## Keeping docs consistent
110
+
111
+ When adding or renaming a file, update any `.md` files that link to it.
112
+ When adding a new concept or section, check whether an existing doc already
113
+ covers it — prefer extending one place over splitting the explanation across
114
+ two. Run `npm run lint:md` before committing doc changes; it catches dead
115
+ links and broken anchors across all Markdown files in the repo.
116
+
103
117
  ## Releasing
104
118
 
105
- 1. Update release notes.
106
- 2. Bump `version` in `package.json`.
107
- 3. `npm run verify` (build + lint:check).
108
- 4. `npm run test:cov && npm run test:jest:cov` (both 100% coverage).
109
- 5. `npm pack --dry-run` and verify the tarball includes `build/`,
110
- `module/`, `README.md`, `LICENSE`, and does **not** include
111
- `test/decorate.js` or `test/example.js`.
112
- 6. Tag and publish.
119
+ ### 1. Update the changelog
120
+
121
+ In `CHANGELOG.md`, move everything under `## [Unreleased]` into a
122
+ new versioned section:
123
+
124
+ ```markdown
125
+ ## [1.0.1] - 2026-05-22
126
+
127
+ ### Fixed
128
+ - ...
129
+ ```
130
+
131
+ Leave a fresh empty `## [Unreleased]` block at the top for the next cycle.
132
+
133
+ ### 2. Bump the version
134
+
135
+ ```bash
136
+ npm version patch # 1.0.0 → 1.0.1
137
+ # or: minor (1.0.0 → 1.1.0) major (1.0.0 → 2.0.0)
138
+ ```
139
+
140
+ `npm version` updates `package.json` and creates a git commit + tag
141
+ (`v1.0.1`) automatically. Do not edit `package.json` by hand for this.
142
+
143
+ ### 3. Verify
144
+
145
+ ```bash
146
+ npm run verify # build + lint:check
147
+ npm run test:cov && npm run test:jest:cov # both suites, 100% coverage
148
+ npm run lint:md # no dead links or broken anchors
149
+ ```
150
+
151
+ All three must pass before publishing.
152
+
153
+ ### 4. Inspect the tarball
154
+
155
+ ```bash
156
+ npm pack --dry-run
157
+ ```
158
+
159
+ The tarball must include: `build/`, `module/`, `src/`, `docs/`, `.ai/`,
160
+ `examples/`, `README.md`, `FOR_HUMANS.md`, `AGENTS.md`, `SKILL.md`,
161
+ `CONTRIBUTING.md`, `LICENSE`.
162
+
163
+ It must **not** include: `test/`, `test-jest/`, `test-ts/`, `test_async/`,
164
+ `reports/`, `.husky/`, `node_modules/`.