run-dmcp 0.1.0 → 0.2.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.
Files changed (135) hide show
  1. package/README.md +76 -10
  2. package/dist/bin/run-dmcp.d.ts +2 -0
  3. package/dist/bin/run-dmcp.js +55 -0
  4. package/dist/db/connection.d.ts +32 -0
  5. package/dist/db/connection.js +38 -16
  6. package/dist/db/schema.d.ts +29 -1
  7. package/dist/db/schema.js +439 -7
  8. package/dist/http/server.js +3 -3
  9. package/dist/index.d.ts +36 -2
  10. package/dist/index.js +184 -92
  11. package/dist/mcp-server.d.ts +49 -0
  12. package/dist/mcp-server.js +127 -0
  13. package/dist/reader/turnReader.d.ts +185 -0
  14. package/dist/reader/turnReader.js +288 -0
  15. package/dist/register/batch.js +5 -79
  16. package/dist/register/mcp-resources.d.ts +9 -0
  17. package/dist/register/mcp-resources.js +16 -62
  18. package/dist/register/render.d.ts +17 -0
  19. package/dist/register/render.js +50 -0
  20. package/dist/register/resolve.d.ts +14 -0
  21. package/dist/register/resolve.js +102 -0
  22. package/dist/register/resources.js +11 -4
  23. package/dist/register/timeline.d.ts +2 -0
  24. package/dist/register/timeline.js +311 -0
  25. package/dist/rpg/index.d.ts +29 -0
  26. package/dist/rpg/index.js +55 -0
  27. package/dist/rpg/register/abilities.d.ts +2 -0
  28. package/dist/rpg/register/abilities.js +165 -0
  29. package/dist/rpg/register/batch.d.ts +2 -0
  30. package/dist/rpg/register/batch.js +92 -0
  31. package/dist/rpg/register/combat.d.ts +2 -0
  32. package/dist/rpg/register/combat.js +207 -0
  33. package/dist/rpg/register/mcp-prompts.d.ts +2 -0
  34. package/dist/rpg/register/mcp-prompts.js +684 -0
  35. package/dist/rpg/register/mcp-resources.d.ts +2 -0
  36. package/dist/rpg/register/mcp-resources.js +61 -0
  37. package/dist/rpg/register/quests.d.ts +2 -0
  38. package/dist/rpg/register/quests.js +118 -0
  39. package/dist/rpg/register/status.d.ts +2 -0
  40. package/dist/rpg/register/status.js +130 -0
  41. package/dist/rpg/register/tables.d.ts +2 -0
  42. package/dist/rpg/register/tables.js +146 -0
  43. package/dist/rpg/tools/ability.d.ts +48 -0
  44. package/dist/rpg/tools/ability.js +238 -0
  45. package/dist/rpg/tools/combat.d.ts +13 -0
  46. package/dist/rpg/tools/combat.js +195 -0
  47. package/dist/rpg/tools/dice.d.ts +23 -0
  48. package/dist/rpg/tools/dice.js +111 -0
  49. package/dist/rpg/tools/quest.d.ts +34 -0
  50. package/dist/rpg/tools/quest.js +164 -0
  51. package/dist/rpg/tools/status.d.ts +36 -0
  52. package/dist/rpg/tools/status.js +218 -0
  53. package/dist/rpg/tools/tables.d.ts +33 -0
  54. package/dist/rpg/tools/tables.js +209 -0
  55. package/dist/schemas/index.d.ts +12 -12
  56. package/dist/timeline/adjudication.d.ts +150 -0
  57. package/dist/timeline/adjudication.js +174 -0
  58. package/dist/timeline/changes.d.ts +100 -0
  59. package/dist/timeline/changes.js +161 -0
  60. package/dist/timeline/checkpoint.d.ts +69 -0
  61. package/dist/timeline/checkpoint.js +131 -0
  62. package/dist/timeline/clock.d.ts +89 -0
  63. package/dist/timeline/clock.js +173 -0
  64. package/dist/timeline/constrained.d.ts +220 -0
  65. package/dist/timeline/constrained.js +671 -0
  66. package/dist/timeline/export.d.ts +171 -0
  67. package/dist/timeline/export.js +329 -0
  68. package/dist/timeline/irreversible.d.ts +85 -0
  69. package/dist/timeline/irreversible.js +108 -0
  70. package/dist/timeline/kinds.d.ts +14 -0
  71. package/dist/timeline/kinds.js +22 -0
  72. package/dist/timeline/narration.d.ts +175 -0
  73. package/dist/timeline/narration.js +259 -0
  74. package/dist/timeline/projection.d.ts +97 -0
  75. package/dist/timeline/projection.js +330 -0
  76. package/dist/timeline/provenance.d.ts +66 -0
  77. package/dist/timeline/provenance.js +45 -0
  78. package/dist/timeline/registry.d.ts +95 -0
  79. package/dist/timeline/registry.js +124 -0
  80. package/dist/timeline/render.d.ts +121 -0
  81. package/dist/timeline/render.js +187 -0
  82. package/dist/timeline/replay.d.ts +64 -0
  83. package/dist/timeline/replay.js +104 -0
  84. package/dist/timeline/resolve.d.ts +262 -0
  85. package/dist/timeline/resolve.js +226 -0
  86. package/dist/timeline/schema.d.ts +13 -0
  87. package/dist/timeline/schema.js +262 -0
  88. package/dist/timeline/t.d.ts +80 -0
  89. package/dist/timeline/t.js +37 -0
  90. package/dist/tools/constraint.d.ts +44 -80
  91. package/dist/tools/constraint.js +115 -124
  92. package/dist/tools/relationship.d.ts +83 -2
  93. package/dist/tools/relationship.js +139 -62
  94. package/dist/tools/resource.d.ts +31 -6
  95. package/dist/tools/resource.js +106 -153
  96. package/dist/types/index.d.ts +19 -1
  97. package/dist/utils/output-schemas.d.ts +593 -2
  98. package/dist/utils/output-schemas.js +3 -0
  99. package/dist/utils/webui.d.ts +32 -0
  100. package/dist/utils/webui.js +54 -1
  101. package/package.json +20 -4
  102. package/dist/__tests__/engineVocabulary.test.d.ts +0 -1
  103. package/dist/__tests__/engineVocabulary.test.js +0 -147
  104. package/dist/db/__tests__/connection.test.d.ts +0 -1
  105. package/dist/db/__tests__/connection.test.js +0 -72
  106. package/dist/db/__tests__/testDb.d.ts +0 -33
  107. package/dist/db/__tests__/testDb.js +0 -41
  108. package/dist/test-setup.d.ts +0 -1
  109. package/dist/test-setup.js +0 -13
  110. package/dist/tools/__tests__/audio.test.d.ts +0 -1
  111. package/dist/tools/__tests__/audio.test.js +0 -59
  112. package/dist/tools/__tests__/conserved.test.d.ts +0 -1
  113. package/dist/tools/__tests__/conserved.test.js +0 -488
  114. package/dist/tools/__tests__/constraint.test.d.ts +0 -1
  115. package/dist/tools/__tests__/constraint.test.js +0 -212
  116. package/dist/tools/__tests__/expiry-consequences.test.d.ts +0 -1
  117. package/dist/tools/__tests__/expiry-consequences.test.js +0 -110
  118. package/dist/tools/__tests__/images.test.d.ts +0 -1
  119. package/dist/tools/__tests__/images.test.js +0 -59
  120. package/dist/tools/__tests__/relationship.test.d.ts +0 -1
  121. package/dist/tools/__tests__/relationship.test.js +0 -132
  122. package/dist/tools/__tests__/resource-constraints.test.d.ts +0 -1
  123. package/dist/tools/__tests__/resource-constraints.test.js +0 -131
  124. package/dist/tools/__tests__/resource.test.d.ts +0 -1
  125. package/dist/tools/__tests__/resource.test.js +0 -190
  126. package/dist/tools/__tests__/time.test.d.ts +0 -1
  127. package/dist/tools/__tests__/time.test.js +0 -404
  128. package/dist/tools/__tests__/timers.test.d.ts +0 -1
  129. package/dist/tools/__tests__/timers.test.js +0 -426
  130. package/dist/tools/__tests__/world.test.d.ts +0 -1
  131. package/dist/tools/__tests__/world.test.js +0 -70
  132. package/dist/utils/__tests__/json.test.d.ts +0 -1
  133. package/dist/utils/__tests__/json.test.js +0 -55
  134. package/dist/utils/__tests__/validation.test.d.ts +0 -1
  135. package/dist/utils/__tests__/validation.test.js +0 -90
@@ -0,0 +1,220 @@
1
+ import { type T } from "./t.js";
2
+ /**
3
+ * The choke point (design §5.4 option (C), Phase 3 step 2): the ONE place a
4
+ * constrained numeric fact key is written, and the ONE place `resources`'
5
+ * former `resource_history` table is replaced by reading the interval-
6
+ * versioned `facts` the projection triggers (projection.ts) already produce.
7
+ *
8
+ * Before this module existed, "what did this value used to be" had two
9
+ * disconnected answers -- a bespoke `resource_history` table that only
10
+ * `updateResourceValue`/`transferResourceValue` (src/tools/resource.ts) wrote
11
+ * to, and the timeline's own `facts`, which the projection triggers were
12
+ * ALREADY appending to on every write, unread by anyone. Two write paths for
13
+ * the same fact is exactly the failure root CLAUDE.md's "engine records
14
+ * decisions" framing and the project's own history (the predecessor's
15
+ * `resource_history`/`relationship_history`, engineVocabulary.test.ts's
16
+ * epigraph) warn about generalizing badly: something gets added because one
17
+ * caller needed it, nothing generalizes the idea, and the concept of
18
+ * versioning ends up living in exactly as many places as someone happened to
19
+ * ask for it. This module collapses that back to one: `writeConstrainedValue`
20
+ * is the only way a constrained numeric value changes, and `valueHistory` is
21
+ * built entirely from what the timeline already recorded.
22
+ *
23
+ * IMPORT DIRECTION IS LOAD-BEARING. This file imports nothing from
24
+ * `src/tools/` -- registry.ts's doc comment explains why in detail, and the
25
+ * short version is: `src/tools/constraint.ts` already imports
26
+ * `src/tools/resource.ts` (for `getResource`), and `src/tools/resource.ts`
27
+ * needs to import THIS module (to delegate `updateResourceValue`/
28
+ * `transferResourceValue` to it). If this module reached back into
29
+ * `src/tools/` for anything -- `getResource`, a resource-shaped type, a
30
+ * resource-specific constant -- that would close
31
+ * `tools/resource.ts -> timeline/constrained.ts -> tools/*` into a cycle.
32
+ * Every value this module needs about "the entity currently reads a column
33
+ * with this key" comes from the timeline's own vocabulary instead:
34
+ * `entities`, `PROJECTED_TABLES`, `liveColumns` (projection.ts) and
35
+ * `constraintsFor`/`conservedConstraintFor` (registry.ts).
36
+ */
37
+ /**
38
+ * One recorded transition of a constrained numeric fact key. A row, never a
39
+ * verdict (hard rule 2) -- there is no `wasClamped`, no `violatedConstraint`,
40
+ * just what changed, when, and (if a constrained write made it) why.
41
+ */
42
+ export interface ValueTransition {
43
+ entityId: string;
44
+ key: string;
45
+ previousValue: number;
46
+ newValue: number;
47
+ delta: number;
48
+ reason: string | null;
49
+ /** Where on the timeline this landed. */
50
+ t: T;
51
+ /** The fact this write opened; null when the write changed nothing (no
52
+ * new interval opens for a value that didn't move -- see
53
+ * `applyLiveWrite`). */
54
+ factId: string | null;
55
+ /** The annotation event this write logged; null for a transition no
56
+ * constrained write made (an unannotated fact-only transition -- a
57
+ * direct column write, a bounds re-clamp, a startup reconciliation). */
58
+ eventId: string | null;
59
+ /** Wall-clock ISO stamp recorded by the choke point; null when
60
+ * unannotated. */
61
+ at: string | null;
62
+ }
63
+ /**
64
+ * A2: the single site where the declared constraint family (design §5.3) --
65
+ * `monotonic`, `bounded`, `conserved`, and (issue #13) `resolve_only` -- is
66
+ * evaluated against an intended change. Every one of `checkResourceConstraints()`
67
+ * and `checkBoundedAndMonotonicConstraints()`'s (formerly src/tools/constraint.ts)
68
+ * rules lives here now and ONLY here -- grep the tree for
69
+ * `constraint.direction ===` or `constraint.kind === "bounded"` and this file
70
+ * is the only hit outside a test.
71
+ *
72
+ * Reads via `constraintsFor(entityId, key)` (registry.ts), not
73
+ * `allConstraintsForEntity` -- this is the behavioral point of Phase 3 step
74
+ * 1's key-scoping: a `monotonic` (or, now, `resolve_only`) constraint
75
+ * declared on one fact key must never reach a write to a different key on
76
+ * the same entity, even though every constraint declared through today's
77
+ * `declare*()` functions other than `declareResolveOnlyConstraint` happens
78
+ * to govern `'value'`.
79
+ *
80
+ * `bounds` is optional. When a caller has no bounds to check against (e.g.
81
+ * `updateResource`'s own guard below, which is not itself moving a value
82
+ * against declared min/max -- it is refusing a conserved reclamp), the
83
+ * `bounded` branch is simply skipped rather than crashing on a missing
84
+ * object. `monotonic` and `conserved` need no bounds and are always
85
+ * evaluated when applicable.
86
+ *
87
+ * MESSAGE PRESERVATION: every string thrown below is copied verbatim from
88
+ * `checkResourceConstraints`/`checkBoundedAndMonotonicConstraints` as they
89
+ * stood before this module existed -- `conserved.test.ts` asserts against
90
+ * the conserved-rejection text by regex, and nothing here is worth rewording
91
+ * away from wording a real caller may already be matching on.
92
+ */
93
+ export declare function assertConstraintsAllow(params: {
94
+ entityId: string;
95
+ key: string;
96
+ previousValue: number;
97
+ intendedValue: number;
98
+ bounds?: {
99
+ minValue: number | null;
100
+ maxValue: number | null;
101
+ };
102
+ /** "reject" -- a direct single-entity write to a conserved member is
103
+ * refused (the ambiguity has no answer). "allow" -- the caller is the
104
+ * counterpart-carrying transfer, the one write that CAN preserve the
105
+ * total. */
106
+ conservedMemberWrite: "reject" | "allow";
107
+ /** Appended to a conserved rejection in place of the default sentence
108
+ * about `update_resource_value`, so the message names the operation the
109
+ * caller actually performed. */
110
+ context?: string;
111
+ }): void;
112
+ /**
113
+ * A3: the only way a constrained numeric value changes. Resolve, check,
114
+ * clamp, write -- in that order, and the order is load-bearing: clamping
115
+ * BEFORE the constraint check would let a declared `bounded` constraint's
116
+ * rejection be silently satisfied by the very clamp it exists to prevent
117
+ * (an intended value of 150 against a [0, 100] bound would arrive at the
118
+ * check already clamped to 100, and a `bounded` constraint's whole point is
119
+ * to refuse 150, not to see 100). Clamping AFTER means the constraint check
120
+ * always sees the caller's actual, unclamped intent.
121
+ */
122
+ export declare function writeConstrainedValue(params: {
123
+ entityId: string;
124
+ key: string;
125
+ mode: "delta" | "set";
126
+ value: number;
127
+ reason?: string | null;
128
+ bounds?: {
129
+ minValue: number | null;
130
+ maxValue: number | null;
131
+ };
132
+ context?: string;
133
+ }): ValueTransition;
134
+ /**
135
+ * A4: the counterpart-carrying two-leg write for conserved sets. Ported from
136
+ * `transferResourceValue` (src/tools/resource.ts) minus its argument
137
+ * validation (self-transfer, non-finite, negative, not-found), which stays
138
+ * in resource.ts because it is about resource IDENTITY, not about the
139
+ * constraint family this module owns -- see the doc comment there.
140
+ *
141
+ * Checks run BEFORE the transaction (membership, then bounded/monotonic on
142
+ * both legs, then the never-clamp bounds rejection), exactly as
143
+ * `transferResourceValue` ordered them -- a transfer that is going to be
144
+ * rejected should never touch either live row. Both legs' writes, plus the
145
+ * defense-in-depth sum re-verification, land in ONE `withTransaction()`.
146
+ */
147
+ export declare function transferConstrainedValue(params: {
148
+ fromEntityId: string;
149
+ toEntityId: string;
150
+ key: string;
151
+ amount: number;
152
+ reason?: string | null;
153
+ fromBounds?: {
154
+ minValue: number | null;
155
+ maxValue: number | null;
156
+ };
157
+ toBounds?: {
158
+ minValue: number | null;
159
+ maxValue: number | null;
160
+ };
161
+ fromLabel?: string;
162
+ toLabel?: string;
163
+ }): {
164
+ from: ValueTransition;
165
+ to: ValueTransition;
166
+ };
167
+ /**
168
+ * A5: the payoff -- `valueHistory` is built ENTIRELY from the timeline
169
+ * (`facts` and `events`), with no `resource_history` in sight, because by
170
+ * this point in the merge there is no `resource_history` writer left to
171
+ * read from.
172
+ *
173
+ * Two sources, both scoped to `(entityId, key)`:
174
+ *
175
+ * 1. every FACT TRANSITION: consecutive facts, ordered `(valid_from_t,
176
+ * rowid)`, paired so each fact after the first supplies a
177
+ * previousValue/newValue/delta. The first fact is the value's
178
+ * CREATION, not a change -- `createResource` writes no history row
179
+ * today, and this function must not invent one, so the pairing loop
180
+ * starts at index 1, never 0.
181
+ * 2. every `"value.changed"` annotation event whose `causes.$.fact_id` is
182
+ * JSON null -- a constrained write that changed nothing. A no-op write
183
+ * opens no fact (see `applyLiveWrite`), so its annotation event is the
184
+ * ONLY record of it; without this second source, a zero-amount
185
+ * transfer or a zero-delta update would silently vanish from history,
186
+ * which is exactly what conserved.test.ts's "logged even though
187
+ * nothing moved" assertions were written against.
188
+ *
189
+ * Fact transitions are joined to their annotation (if any) by
190
+ * `json_extract(causes, '$.fact_id') = facts.id` -- an EXACT, unique link,
191
+ * because `applyLiveWrite` recorded the fact id at write time. This is
192
+ * deliberately stronger than irreversible.ts's `findOpenedByEventId`, which
193
+ * has to approximate the same relationship via `(at_t, row_id)` because the
194
+ * projection triggers that write `row_id` have no fact id to record at the
195
+ * point they fire (issue #2 predates this module). Here, recording the real
196
+ * id costs nothing extra and removes the approximation entirely.
197
+ *
198
+ * `json_valid(causes)` guards every extraction, matching irreversible.ts's
199
+ * `CASE WHEN json_valid(causes) THEN causes END` idiom for the same reason
200
+ * given there: `events.causes` has no CHECK constraint, timeline import
201
+ * (export.ts) carries it through verbatim by design, and SQLite's
202
+ * `json_extract` raises for the WHOLE query -- not just the offending row --
203
+ * when it meets a value that isn't JSON. A provenance hop must never be able
204
+ * to fail the query it annotates.
205
+ *
206
+ * Rows with no matching annotation (a direct column write, a bounds
207
+ * re-clamp, a startup reconciliation) come back with `reason: null`,
208
+ * `eventId: null`, `at: null` -- MORE history than `resource_history` ever
209
+ * held, because that table only ever got a row when
210
+ * `updateResourceValue`/`transferResourceValue` themselves wrote one.
211
+ *
212
+ * Ordered newest-first by `(t, rowid)` descending, matching
213
+ * `resource_history`'s old `ORDER BY timestamp DESC` in spirit -- but by the
214
+ * timeline's own axis, `t`, not by wall-clock time, because an unannotated
215
+ * transition has no wall-clock stamp to sort by and `t` is the one ordering
216
+ * this whole codebase agrees on (t.ts). `rowid` is the tiebreak for the rare
217
+ * case two rows share a `t`, mirroring `changes.ts`'s own tiebreak
218
+ * discipline. `limit` applies after ordering, never before.
219
+ */
220
+ export declare function valueHistory(entityId: string, key: string, limit?: number): ValueTransition[];