Skip to content

Commit 8b22e22

Browse files
committed
arch: cleanup / doc
1 parent 15784c3 commit 8b22e22

8 files changed

Lines changed: 169 additions & 77 deletions

File tree

docs/PLAYGROUND.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Playground Test Results
22

3+
> This file is a snapshot report for `test/playground.ts`, not a complete API
4+
> reference. For current user-facing API usage, see [`docs/README.md`](./README.md)
5+
> and the repository [`README.md`](../README.md).
6+
37
This document summarizes the status of various test snippets from
48
`test/playground.ts`.
59

@@ -115,7 +119,8 @@ This document summarizes the status of various test snippets from
115119
**Note:** `.replace({match: 'a', replace: 2})` on `a*x + b` returns `2` instead
116120
of `2*x + b`. The bug is in `parseRulePart` (rules.ts:350) which auto-converts
117121
all single-character symbols to wildcards. So `'a'` becomes `'_a'`, matching ANY
118-
expression rather than the literal symbol `a`. See TODO.md #23.
122+
expression rather than the literal symbol `a`. This behavior is tracked in the
123+
internal backlog.
119124

120125
### Expected Behavior (Not Bugs)
121126

@@ -154,8 +159,8 @@ expression rather than the literal symbol `a`. See TODO.md #23.
154159

155160
**Note:** `isEqual` is for mathematical equality (vs `isSame` for structural
156161
equality). For equations, `isEqual` should check if `(LHS1-RHS1)/(LHS2-RHS2)`
157-
simplifies to a non-zero constant, indicating the same solution set. See TODO.md
158-
#22.
162+
simplifies to a non-zero constant, indicating the same solution set. This
163+
behavior is tracked in the internal backlog.
159164

160165
---
161166

docs/SIMPLIFICATIONS.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
# Simplification Issues Report
22

3-
This document catalogs simplification behaviors that need attention, organized
4-
by priority and category.
3+
> This document is a categorized simplification report and not a full API
4+
> reference. For current user-facing API documentation, see
5+
> [`docs/README.md`](./README.md) and [`README.md`](../README.md).
6+
7+
Checked: 2026-02-01 Compute Engine version (package.json): 0.33.0
8+
9+
This document catalogs historical and current simplification behaviors,
10+
including resolved items and remaining limitations, organized by priority and
11+
category.
512

613
## Summary
714

docs/SIMPLIFY.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
# Simplification status for issue #178
1+
# Simplification Snapshot (Issue #178)
2+
3+
> This file tracks issue-specific simplification snapshots and is not the
4+
> canonical API guide. For current API usage and workflow helper options, see
5+
> [`docs/README.md`](./README.md) and [`README.md`](../README.md).
26
37
Source: cortex-js/compute-engine#178 ("x+x does not simplify to 2x")
48

docs/architecture/CURRENT-ARCHITECTURE.md

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,95 @@ This document captures the implemented architecture after the recent modularizat
1111

1212
## Layering Model
1313

14-
1. Kernel type layer
14+
```
15+
┌─────────────────────────────────────────────────┐
16+
│ 4. Composition root │
17+
│ index.ts (ComputeEngine) │
18+
│ Composes services, exposes public API │
19+
├─────────────────────────────────────────────────┤
20+
│ 3. Runtime services │
21+
│ engine-*.ts │
22+
│ One bounded concern per file │
23+
├─────────────────────────────────────────────────┤
24+
│ 2. Specialized type wrappers │
25+
│ types-*.ts, global-types.ts │
26+
│ Bind kernel generics to concrete types │
27+
├─────────────────────────────────────────────────┤
28+
│ 1. Kernel type layer │
29+
│ types-kernel-*.ts │
30+
│ Generic type contracts (no engine imports) │
31+
└─────────────────────────────────────────────────┘
32+
```
33+
34+
### 1. Kernel type layer
1535
- Files: `types-kernel-*.ts`
1636
- Responsibility: generic type contracts for evaluation/serialization behavior without engine-specific concrete types.
1737
- Rule: no dependency on `ComputeEngine` implementation modules.
1838

19-
2. Specialized type wrappers
39+
### 2. Specialized type wrappers
2040
- Files: `types-*.ts`, `global-types.ts`
2141
- Responsibility: bind kernel generics to concrete compute-engine types (`BoxedExpression`, `IComputeEngine`, etc.).
2242
- Rule: avoid importing runtime implementation modules.
2343

24-
3. Runtime services
44+
### 3. Runtime services
2545
- Files: `engine-*.ts`
2646
- Responsibility: focused implementation concerns (parse entrypoints, startup/bootstrap, configuration lifecycle, numeric config, scope/assumptions/sequences, workflow helpers, validation helpers, extension contracts).
2747
- Rule: services should not become secondary monoliths; each service owns one bounded concern.
2848

29-
4. Composition root
49+
### 4. Composition root
3050
- File: `index.ts` (`ComputeEngine`)
3151
- Responsibility: compose services, expose public API methods, and own lifecycle orchestration.
3252
- Rule: business logic should prefer service modules; `ComputeEngine` should remain an API shell and integration point.
3353

34-
## Service Boundaries (Implemented)
35-
36-
- Startup/bootstrap: `engine-startup-coordinator.ts`, `engine-library-bootstrap.ts`
37-
- Parse defaults/policy: `engine-parse-entrypoint.ts`
38-
- Workflow API helpers: `engine-workflow-entrypoints.ts`
39-
- Validation/error expression entrypoints: `engine-validation-entrypoints.ts`
40-
- Numeric policy/state: `engine-numeric-configuration.ts`
41-
- Runtime limits/verification state: `engine-runtime-state.ts`
42-
- Configuration lifecycle/reset fan-out: `engine-configuration-lifecycle.ts`
43-
- Compilation target registry: `engine-compilation-targets.ts`
44-
- Extension contracts: `engine-extension-contracts.ts`
54+
## Service Inventory
55+
56+
### Startup & Initialization
57+
| File | Responsibility |
58+
|------|---------------|
59+
| `engine-startup-coordinator.ts` | Orchestrates initialization sequence: common numbers, library bootstrap, common symbols |
60+
| `engine-library-bootstrap.ts` | Resolves library entries, topological sort, loads definitions, collects LaTeX dictionaries |
61+
| `engine-common-symbols.ts` | Initializes well-known symbol bindings (True, False, Pi, E, Nothing) |
62+
63+
### Parsing & Workflows
64+
| File | Responsibility |
65+
|------|---------------|
66+
| `engine-parse-entrypoint.ts` | Engine-specific parse defaults, symbol type resolution, boxing of parse results |
67+
| `engine-workflow-entrypoints.ts` | High-level `parseSimplify/parseEvaluate/parseNumeric` combining parse + operation |
68+
69+
### Validation & Errors
70+
| File | Responsibility |
71+
|------|---------------|
72+
| `engine-validation-entrypoints.ts` | Factory functions for error and type-mismatch expressions |
73+
| `engine-extension-contracts.ts` | Runtime contract validation for compilation targets, libraries, and compile options |
74+
75+
### Engine State
76+
| File | Responsibility |
77+
|------|---------------|
78+
| `engine-numeric-configuration.ts` | Precision, tolerance, angular unit, and Decimal.js configuration |
79+
| `engine-runtime-state.ts` | Execution limits (time, iteration, recursion) and verification state |
80+
| `engine-configuration-lifecycle.ts` | Configuration change propagation and reset fan-out |
81+
| `engine-cache.ts` | Expression and rule-set caching with generation-based invalidation |
82+
| `engine-latex-dictionary-state.ts` | LaTeX dictionary indexing and rebuild |
83+
84+
### Scoping & Declarations
85+
| File | Responsibility |
86+
|------|---------------|
87+
| `engine-scope.ts` | Lexical scope push/pop, eval context management, symbol lookup |
88+
| `engine-declarations.ts` | Symbol and operator declaration, type declaration, assignment |
89+
| `engine-assumptions.ts` | Assumption management, `ask()`, `verify()`, `forget()` |
90+
| `engine-sequences.ts` | Sequence declaration, OEIS lookup, recurrence evaluation |
91+
92+
### Expression Construction
93+
| File | Responsibility |
94+
|------|---------------|
95+
| `engine-expression-entrypoints.ts` | Symbol and number expression creation with definition binding |
96+
| `engine-simplification-rules.ts` | Built-in simplification rule initialization |
97+
98+
### Compilation
99+
| File | Responsibility |
100+
|------|---------------|
101+
| `engine-compilation-targets.ts` | Registry for named compilation targets (JavaScript, GLSL, etc.) |
102+
| `engine-type-resolver.ts` | Type resolution callback for parser integration |
45103

46104
## Public Workflow API Policy
47105

@@ -55,10 +113,13 @@ This document captures the implemented architecture after the recent modularizat
55113
- Parse presets: `parseMode = strict | permissive`
56114

57115
Precedence rule across workflow helpers:
58-
- Explicit low-level options win over presets.
116+
- Explicit low-level options always win over presets.
59117
- `parse.strict` overrides `parseMode`
60118
- `evaluate.numericApproximation` overrides `evaluateMode`
61119
- `simplify.strategy` overrides `simplifyMode`
120+
- This is implemented via object spread: the preset sets a default, then `...options.parse` overwrites it.
121+
122+
Note: `simplifyMode: 'trigonometric'` maps to the internal `strategy: 'fu'` (the Fu algorithm for trigonometric simplification, named after Fu, Zhong, and Zeng).
62123

63124
## Extension Contracts (Runtime Guards)
64125

@@ -92,12 +153,14 @@ Rules:
92153

93154
## Guardrails
94155

95-
- Circular dependency budget: `0` (checked in `typecheck` + `check:deps` workflows).
156+
- **Circular dependency budget: `0`** — no cycles of any kind (runtime or type-only). Checked via `npx madge --circular --extensions ts src/compute-engine`.
157+
- ESLint `import/no-restricted-paths` enforces layered dependencies (35 zone rules in `.eslintrc.cjs`). Run with `npm run check:deps`.
96158
- Public type surfaces must not include explicit `any`.
97159
- Contract tests exist for extension seams (`test/compute-engine/extension-contracts.test.ts`).
98160

99161
## Immediate Next Work
100162

101-
1. Keep shrinking `ComputeEngine` orchestration by extracting remaining utility glue.
163+
1. Add tests for library circular dependency detection and compilation target unregistration/re-registration.
102164
2. Expand extension contract tests to additional compile-target families and compile-edge payloads.
103-
3. Keep documentation synchronized between kernel contracts and specialized wrappers.
165+
3. Consider skipping contract validation for built-in compilation targets to reduce startup cost.
166+
4. Keep documentation synchronized between kernel contracts and specialized wrappers.

docs/architecture/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Architecture Docs
2+
3+
This directory contains internal architecture notes and refactor plans.
4+
5+
These documents are intended for maintainers and contributors. They describe
6+
module boundaries, dependency direction, and implementation planning, and are
7+
not a stable public API reference.
8+
9+
Recommended starting points:
10+
11+
- [`CURRENT-ARCHITECTURE.md`](./CURRENT-ARCHITECTURE.md) for the current module
12+
map and extension boundaries.
13+
- [`ZERO-CYCLES-PLAN.md`](./ZERO-CYCLES-PLAN.md) for cycle-elimination status.
14+
- [`PLAN.md`](./PLAN.md) for the consolidated roadmap.

src/compute-engine/engine-library-bootstrap.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,5 @@ export function getLatexDictionaryForDomain(
6767
? STANDARD_LIBRARIES
6868
: STANDARD_LIBRARIES.filter((entry) => entry.name === domain);
6969

70-
const result: LatexDictionaryEntry[] = [];
71-
for (const library of libraries) {
72-
if (library.latexDictionary)
73-
result.push(...(library.latexDictionary as LatexDictionaryEntry[]));
74-
}
75-
76-
return result;
70+
return collectLibraryLatexEntries(libraries);
7771
}

src/compute-engine/engine-workflow-entrypoints.ts

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import type { BoxedExpression } from './global-types';
22
import type { LatexString } from './latex-syntax/types';
33
import type { ParseEntrypointOptions } from './engine-parse-entrypoint';
4+
import type {
5+
WorkflowParseMode,
6+
WorkflowEvaluateMode,
7+
WorkflowSimplifyMode,
8+
WorkflowParseOptions,
9+
WorkflowSimplifyOptions,
10+
WorkflowEvaluateOptions,
11+
WorkflowNumericOptions,
12+
} from './types-engine';
413

514
type WorkflowHost = {
615
parse(
@@ -9,34 +18,13 @@ type WorkflowHost = {
918
): BoxedExpression | null;
1019
};
1120

12-
export type ParseMode = 'strict' | 'permissive';
13-
export type EvaluateMode = 'exact' | 'numeric';
14-
export type SimplifyMode = 'default' | 'trigonometric';
15-
16-
type WorkflowParseOptions = {
17-
parseMode?: ParseMode;
18-
parse?: ParseEntrypointOptions;
19-
};
20-
21-
export type ParseSimplifyOptions = {
22-
parseMode?: ParseMode;
23-
simplifyMode?: SimplifyMode;
24-
parse?: ParseEntrypointOptions;
25-
simplify?: Parameters<BoxedExpression['simplify']>[0];
26-
};
27-
28-
export type ParseEvaluateOptions = {
29-
parseMode?: ParseMode;
30-
evaluateMode?: EvaluateMode;
31-
parse?: ParseEntrypointOptions;
32-
evaluate?: Parameters<BoxedExpression['evaluate']>[0];
33-
};
34-
35-
export type ParseNumericOptions = {
36-
parseMode?: ParseMode;
37-
parse?: ParseEntrypointOptions;
38-
};
39-
21+
/**
22+
* Translate workflow parse-mode preset into low-level parse options.
23+
*
24+
* **Precedence rule:** explicit `parse.strict` overrides `parseMode`.
25+
* For example `{ parseMode: 'permissive', parse: { strict: true } }` results
26+
* in `{ strict: true }` because object-spread puts `parse.*` last.
27+
*/
4028
function getParseOptions(
4129
options?: WorkflowParseOptions
4230
): ParseEntrypointOptions | undefined {
@@ -46,17 +34,32 @@ function getParseOptions(
4634
return { strict, ...options.parse };
4735
}
4836

37+
/**
38+
* Translate workflow evaluate-mode preset into low-level evaluate options.
39+
*
40+
* **Precedence rule:** explicit `evaluate.numericApproximation` overrides
41+
* `evaluateMode`.
42+
*/
4943
function getEvaluateOptions(
50-
options?: ParseEvaluateOptions
44+
options?: WorkflowEvaluateOptions
5145
): Parameters<BoxedExpression['evaluate']>[0] | undefined {
5246
if (options?.evaluateMode === undefined) return options?.evaluate;
5347

5448
const numericApproximation = options.evaluateMode === 'numeric';
5549
return { numericApproximation, ...options.evaluate };
5650
}
5751

52+
/**
53+
* Translate workflow simplify-mode preset into low-level simplify options.
54+
*
55+
* **Precedence rule:** explicit `simplify.strategy` overrides `simplifyMode`.
56+
*
57+
* The `'trigonometric'` mode maps to the `'fu'` strategy, which is the
58+
* Fu algorithm for trigonometric simplification (named after the paper by
59+
* Fu, Zhong, and Zeng).
60+
*/
5861
function getSimplifyOptions(
59-
options?: ParseSimplifyOptions
62+
options?: WorkflowSimplifyOptions
6063
): Parameters<BoxedExpression['simplify']>[0] | undefined {
6164
if (options?.simplifyMode === undefined) return options?.simplify;
6265

@@ -67,7 +70,7 @@ function getSimplifyOptions(
6770
export function parseAndSimplify(
6871
engine: WorkflowHost,
6972
latex: LatexString | null,
70-
options?: ParseSimplifyOptions
73+
options?: WorkflowSimplifyOptions
7174
): BoxedExpression | null {
7275
const parsed = engine.parse(latex, getParseOptions(options));
7376
if (parsed === null) return null;
@@ -77,7 +80,7 @@ export function parseAndSimplify(
7780
export function parseAndEvaluate(
7881
engine: WorkflowHost,
7982
latex: LatexString | null,
80-
options?: ParseEvaluateOptions
83+
options?: WorkflowEvaluateOptions
8184
): BoxedExpression | null {
8285
const parsed = engine.parse(latex, getParseOptions(options));
8386
if (parsed === null) return null;
@@ -87,7 +90,7 @@ export function parseAndEvaluate(
8790
export function parseAndNumeric(
8891
engine: WorkflowHost,
8992
latex: LatexString | null,
90-
options?: ParseNumericOptions
93+
options?: WorkflowNumericOptions
9194
): BoxedExpression | null {
9295
const parsed = engine.parse(latex, getParseOptions(options));
9396
if (parsed === null) return null;

0 commit comments

Comments
 (0)