@polintpro/proposit-core 0.2.3 → 0.2.5
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 +14 -11
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/core/ArgumentEngine.d.ts +23 -19
- package/dist/lib/core/ArgumentEngine.d.ts.map +1 -1
- package/dist/lib/core/ArgumentEngine.js +11 -11
- package/dist/lib/core/ArgumentEngine.js.map +1 -1
- package/dist/lib/core/ChangeCollector.d.ts +13 -14
- package/dist/lib/core/ChangeCollector.d.ts.map +1 -1
- package/dist/lib/core/ChangeCollector.js.map +1 -1
- package/dist/lib/core/ExpressionManager.d.ts +15 -13
- package/dist/lib/core/ExpressionManager.d.ts.map +1 -1
- package/dist/lib/core/ExpressionManager.js +52 -22
- package/dist/lib/core/ExpressionManager.js.map +1 -1
- package/dist/lib/core/PremiseManager.d.ts +21 -20
- package/dist/lib/core/PremiseManager.d.ts.map +1 -1
- package/dist/lib/core/PremiseManager.js +19 -24
- package/dist/lib/core/PremiseManager.js.map +1 -1
- package/dist/lib/core/VariableManager.d.ts +7 -8
- package/dist/lib/core/VariableManager.d.ts.map +1 -1
- package/dist/lib/core/VariableManager.js +4 -1
- package/dist/lib/core/VariableManager.js.map +1 -1
- package/dist/lib/core/diff.d.ts +1 -1
- package/dist/lib/core/diff.d.ts.map +1 -1
- package/dist/lib/core/diff.js +19 -11
- package/dist/lib/core/diff.js.map +1 -1
- package/dist/lib/schemata/propositional.d.ts.map +1 -1
- package/dist/lib/schemata/propositional.js +0 -1
- package/dist/lib/schemata/propositional.js.map +1 -1
- package/dist/lib/schemata/shared.d.ts +4 -0
- package/dist/lib/schemata/shared.d.ts.map +1 -1
- package/dist/lib/types/diff.d.ts +15 -15
- package/dist/lib/types/diff.d.ts.map +1 -1
- package/dist/lib/types/mutation.d.ts +7 -20
- package/dist/lib/types/mutation.d.ts.map +1 -1
- package/dist/lib/utils/position.d.ts +9 -3
- package/dist/lib/utils/position.d.ts.map +1 -1
- package/dist/lib/utils/position.js +9 -4
- package/dist/lib/utils/position.js.map +1 -1
- package/package.json +3 -2
- package/skills/proposit-core/SKILL.md +35 -0
- package/skills/proposit-core/docs/api-usage.md +442 -0
- package/skills/proposit-core/docs/architecture.md +256 -0
- package/skills/proposit-core/docs/cli.md +304 -0
- package/skills/proposit-core/docs/testing.md +281 -0
- package/skills/proposit-core/docs/types-schemas.md +648 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Testing Guide
|
|
2
|
+
|
|
3
|
+
Reference for proposit-core test structure, conventions, and how to add new tests.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Test File
|
|
8
|
+
|
|
9
|
+
All tests live in a single file: `test/ExpressionManager.test.ts` (~6500 lines, Vitest).
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm run test # run all tests
|
|
13
|
+
pnpm run typecheck # tsc --noEmit
|
|
14
|
+
pnpm run lint # prettier --check + eslint
|
|
15
|
+
pnpm run check # typecheck + lint + test + build (all in sequence)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Structure
|
|
21
|
+
|
|
22
|
+
Each `describe` block corresponds to a method or logical grouping. New features get a new `describe` at the bottom. Do not modify existing blocks unless fixing them.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Fixture Convention
|
|
27
|
+
|
|
28
|
+
No shared `beforeEach`. Every test builds fixtures inline using helpers defined at the top of the test file.
|
|
29
|
+
|
|
30
|
+
### Constants and factory functions
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const ARG: Omit<TCoreArgument, "checksum"> = { id: "arg-1", version: 1 }
|
|
34
|
+
|
|
35
|
+
function makeVar(id: string, symbol: string): TVariableInput {
|
|
36
|
+
return { id, argumentId: ARG.id, argumentVersion: ARG.version, symbol }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function makeVarExpr(
|
|
40
|
+
id: string,
|
|
41
|
+
variableId: string,
|
|
42
|
+
opts: { parentId?: string | null; position?: number } = {}
|
|
43
|
+
): TExpressionInput {
|
|
44
|
+
return {
|
|
45
|
+
id,
|
|
46
|
+
argumentId: ARG.id,
|
|
47
|
+
argumentVersion: ARG.version,
|
|
48
|
+
type: "variable",
|
|
49
|
+
variableId,
|
|
50
|
+
parentId: opts.parentId ?? null,
|
|
51
|
+
position: opts.position ?? POSITION_INITIAL,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function makeOpExpr(
|
|
56
|
+
id: string,
|
|
57
|
+
operator: "not" | "and" | "or" | "implies" | "iff",
|
|
58
|
+
opts: { parentId?: string | null; position?: number } = {}
|
|
59
|
+
): TExpressionInput {
|
|
60
|
+
return {
|
|
61
|
+
id,
|
|
62
|
+
argumentId: ARG.id,
|
|
63
|
+
argumentVersion: ARG.version,
|
|
64
|
+
type: "operator",
|
|
65
|
+
operator,
|
|
66
|
+
parentId: opts.parentId ?? null,
|
|
67
|
+
position: opts.position ?? POSITION_INITIAL,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function makeFormulaExpr(
|
|
72
|
+
id: string,
|
|
73
|
+
opts: { parentId?: string | null; position?: number } = {}
|
|
74
|
+
): TExpressionInput {
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
argumentId: ARG.id,
|
|
78
|
+
argumentVersion: ARG.version,
|
|
79
|
+
type: "formula",
|
|
80
|
+
parentId: opts.parentId ?? null,
|
|
81
|
+
position: opts.position ?? POSITION_INITIAL,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Pre-built variables
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const VAR_P = makeVar("var-p", "P")
|
|
90
|
+
const VAR_Q = makeVar("var-q", "Q")
|
|
91
|
+
const VAR_R = makeVar("var-r", "R")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Helper functions
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
/** Create a premise (via ArgumentEngine) with P, Q, R pre-loaded. */
|
|
98
|
+
function premiseWithVars(): PremiseManager {
|
|
99
|
+
const eng = new ArgumentEngine(ARG)
|
|
100
|
+
eng.addVariable(VAR_P)
|
|
101
|
+
eng.addVariable(VAR_Q)
|
|
102
|
+
eng.addVariable(VAR_R)
|
|
103
|
+
const { result: pm } = eng.createPremise()
|
|
104
|
+
return pm
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Create a PremiseManager directly with a deterministic ID (for toData tests). */
|
|
108
|
+
function makePremise(extras?: Record<string, unknown>): PremiseManager {
|
|
109
|
+
const vm = new VariableManager()
|
|
110
|
+
return new PremiseManager("premise-1", ARG, vm, extras)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Adding a New Test
|
|
117
|
+
|
|
118
|
+
1. Add a new `describe` block at the bottom of the file.
|
|
119
|
+
2. Build fixtures inline using the helpers above (`premiseWithVars()`, `makeVarExpr()`, etc.).
|
|
120
|
+
3. Destructure mutation results: `const { result, changes } = ...`
|
|
121
|
+
4. Assert on both the return value and changeset side effects.
|
|
122
|
+
5. Run `pnpm run test` to verify.
|
|
123
|
+
|
|
124
|
+
### Example: testing a new PremiseManager method
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
describe("PremiseManager —myNewMethod", () => {
|
|
128
|
+
it("does the expected thing", () => {
|
|
129
|
+
const pm = premiseWithVars()
|
|
130
|
+
const { result: root } = pm.addExpression(makeOpExpr("op-1", "and"))
|
|
131
|
+
const { result, changes } = pm.myNewMethod("op-1")
|
|
132
|
+
|
|
133
|
+
// Assert on the direct return value
|
|
134
|
+
expect(result).toBeDefined()
|
|
135
|
+
|
|
136
|
+
// Assert on changeset side effects
|
|
137
|
+
expect(changes.expressions?.modified).toHaveLength(1)
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Existing Describe Blocks
|
|
145
|
+
|
|
146
|
+
Full ordered list (42 blocks):
|
|
147
|
+
|
|
148
|
+
| # | Block name |
|
|
149
|
+
| --- | ------------------------------------------------------------------------ |
|
|
150
|
+
| 1 | `addExpression` |
|
|
151
|
+
| 2 | `insertExpression` |
|
|
152
|
+
| 3 | `removeExpression` |
|
|
153
|
+
| 4 | `removeExpression —operator collapse` |
|
|
154
|
+
| 5 | `removeVariable` |
|
|
155
|
+
| 6 | `addExpression ordering` |
|
|
156
|
+
| 7 | `toArray behaviour (via toData().expressions)` |
|
|
157
|
+
| 8 | `stress test` |
|
|
158
|
+
| 9 | `formula` |
|
|
159
|
+
| 10 | `ArgumentEngine premise CRUD` |
|
|
160
|
+
| 11 | `ArgumentEngine —addVariable / removeVariable` |
|
|
161
|
+
| 12 | `PremiseManager —single-root enforcement` |
|
|
162
|
+
| 13 | `PremiseManager —addExpression / removeExpression / insertExpression` |
|
|
163
|
+
| 14 | `PremiseManager —toDisplayString` |
|
|
164
|
+
| 15 | `PremiseManager —toData` |
|
|
165
|
+
| 16 | `PremiseManager —validation and evaluation` |
|
|
166
|
+
| 17 | `ArgumentEngine —roles and evaluation` |
|
|
167
|
+
| 18 | `ArgumentEngine —complex argument scenarios across multiple evaluations` |
|
|
168
|
+
| 19 | `diffArguments` |
|
|
169
|
+
| 20 | `Kleene three-valued logic helpers` |
|
|
170
|
+
| 21 | `PremiseManager —three-valued evaluation` |
|
|
171
|
+
| 22 | `ArgumentEngine —three-valued evaluation` |
|
|
172
|
+
| 23 | `schema shapes with additionalProperties` |
|
|
173
|
+
| 24 | `field preservation —unknown fields survive round-trips` |
|
|
174
|
+
| 25 | `buildPremiseProfile` |
|
|
175
|
+
| 26 | `analyzePremiseRelationships —direct relationships` |
|
|
176
|
+
| 27 | `analyzePremiseRelationships —transitive relationships` |
|
|
177
|
+
| 28 | `analyzePremiseRelationships —precedence and edge cases` |
|
|
178
|
+
| 29 | `position utilities` |
|
|
179
|
+
| 30 | `PremiseManager —appendExpression and addExpressionRelative` |
|
|
180
|
+
| 31 | `ChangeCollector` |
|
|
181
|
+
| 32 | `PremiseManager —mutation changesets` |
|
|
182
|
+
| 33 | `ArgumentEngine —mutation changesets` |
|
|
183
|
+
| 34 | `checksum utilities` |
|
|
184
|
+
| 35 | `entity checksum fields` |
|
|
185
|
+
| 36 | `createChecksumConfig` |
|
|
186
|
+
| 37 | `ArgumentEngine —variable management` |
|
|
187
|
+
| 38 | `PremiseManager —deleteExpressionsUsingVariable` |
|
|
188
|
+
| 39 | `variable expressions cannot have children` |
|
|
189
|
+
| 40 | `ArgumentEngine —auto-conclusion on first premise` |
|
|
190
|
+
| 41 | `PremiseManager —updateExpression` |
|
|
191
|
+
| 42 | `removeExpression —deleteSubtree parameter` |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Key Testing Patterns
|
|
196
|
+
|
|
197
|
+
### Destructure mutation results
|
|
198
|
+
|
|
199
|
+
All mutating methods return `TCoreMutationResult<T>`. Always destructure and assert on both parts:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const { result, changes } = pm.addExpression(makeVarExpr("v1", "var-p"))
|
|
203
|
+
expect(result.id).toBe("v1")
|
|
204
|
+
expect(changes.expressions?.added).toHaveLength(1)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Operator collapse after removal
|
|
208
|
+
|
|
209
|
+
When removing an expression, assert on the parent/child state afterward. Operator collapse may delete the parent or promote a surviving child:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const { changes } = pm.removeExpression("child-2", true)
|
|
213
|
+
// Parent operator collapsed -- check it was removed
|
|
214
|
+
expect(changes.expressions?.removed?.map((e) => e.id)).toContain("op-1")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Cascade operations (e.g. removeVariable)
|
|
218
|
+
|
|
219
|
+
Check `changes.expressions.removed` across all affected premises:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const { changes } = engine.removeVariable("var-p")
|
|
223
|
+
expect(changes.expressions?.removed?.length).toBeGreaterThan(0)
|
|
224
|
+
expect(changes.variables?.removed).toHaveLength(1)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Verify tree structure
|
|
228
|
+
|
|
229
|
+
Use `pm.toData().expressions` to inspect the full expression array:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const exprs = pm.toData().expressions
|
|
233
|
+
expect(exprs).toHaveLength(3)
|
|
234
|
+
expect(exprs[0].parentId).toBeNull() // root
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Verify rendered formula
|
|
238
|
+
|
|
239
|
+
Use `pm.toDisplayString()` to check the human-readable form:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
expect(pm.toDisplayString()).toBe("(P AND Q) IMPLIES R")
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Evaluation tests
|
|
246
|
+
|
|
247
|
+
Build an assignment and check evaluation results:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
const assignment: TCoreExpressionAssignment = {
|
|
251
|
+
variables: { "var-p": true, "var-q": false },
|
|
252
|
+
rejectedExpressionIds: [],
|
|
253
|
+
}
|
|
254
|
+
const evalResult = pm.evaluate(assignment)
|
|
255
|
+
expect(evalResult.rootValue).toBe(false)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Root-only operator enforcement
|
|
259
|
+
|
|
260
|
+
`implies` and `iff` must have `parentId: null`. Tests should verify that nesting them throws:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
expect(() =>
|
|
264
|
+
pm.addExpression(
|
|
265
|
+
makeOpExpr("nested-implies", "implies", { parentId: "op-1" })
|
|
266
|
+
)
|
|
267
|
+
).toThrow()
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Commands Reference
|
|
273
|
+
|
|
274
|
+
| Command | Purpose |
|
|
275
|
+
| --------------------- | ----------------------------------------------- |
|
|
276
|
+
| `pnpm run test` | Run all tests (vitest run) |
|
|
277
|
+
| `pnpm run check` | Typecheck + lint + test + build (full pipeline) |
|
|
278
|
+
| `pnpm run typecheck` | tsc --noEmit |
|
|
279
|
+
| `pnpm run lint` | prettier --check + eslint |
|
|
280
|
+
| `pnpm run prettify` | prettier --write (auto-fix formatting) |
|
|
281
|
+
| `pnpm eslint . --fix` | Auto-fix lint errors |
|