Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
38 changes: 15 additions & 23 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,21 @@
],
"permissions": {
"deny": [
"Read(./lib/**)",
"Read(./es/**)",
"Read(./commonjs/**)",
"Read(./dist/**)",
"Read(./languages/**)",
"Read(./typings/**)",
"Read(./docs/api/**)",
"Read(./docs/functions/**)",
"Read(./docs/guide/built-in-functions.md)",
"Read(./docs/.vuepress/dist/**)",
"Read(./docs/.vuepress/api-sidebar.json)",
"Read(./docs/.vuepress/api-sidebar-relative.json)",
"Read(./typedoc/**)",
"Read(./doc/**)",
"Read(./coverage/**)",
"Read(./test-jest/**)",
"Read(./test-jasmine/**)",
"Read(./storage/**)"
]
},
"worktree": {
"symlinkDirectories": [
"node_modules"
"Read(/hyperformula/lib/**)",
"Read(/hyperformula/es/**)",
"Read(/hyperformula/commonjs/**)",
"Read(/hyperformula/dist/**)",
"Read(/hyperformula/languages/**)",
"Read(/hyperformula/typings/**)",
"Read(/hyperformula/coverage/**)",
"Read(/hyperformula/test-jest/**)",
"Read(/hyperformula/test-jasmine/**)",
"Read(/hyperformula/typedoc/**)",
"Read(/hyperformula/storage/**)",
"Read(/docs/functions/**)",
"Read(/docs/.vuepress/dist/**)",
"Read(/docs/.vuepress/api-sidebar.json)",
"Read(/docs/.vuepress/api-sidebar-relative.json)"
]
}
}
2 changes: 1 addition & 1 deletion .claude/skills/changelog-creation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Documentation-only, test-only, and CI or tooling changes take none, and neither

## 4. Write the bullet

Under `## [Unreleased]` in `CHANGELOG.md`, in the section that matches the change, creating the `### ` heading if it is absent. End it with the link from step 3.
Under `## [Unreleased]` in `CHANGELOG.md` at the repository root — one changelog for every package, because they release together on one version. Put it in the section that matches the change, creating the `### ` heading if it is absent. Name the package the entry concerns when the text does not make it obvious. End it with the link from step 3.

## 5. Re-read it as a user would

Expand Down
8 changes: 4 additions & 4 deletions .claude/skills/hyperformula-code-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Always:
|---|---|
| [`DEFINITION-OF-DONE.md`](../../../dev-docs/DEFINITION-OF-DONE.md) | What the change was required to contain |
| [`CODE-STYLE.md`](../../../dev-docs/CODE-STYLE.md) | Style, and which paths are hot enough that complexity matters |
| [`TESTING.md`](../../../dev-docs/TESTING.md#a-test-must-prove-behaviour) | Whether the tests prove anything, or only execute code |
| [`TESTING.md`](../../../hyperformula/dev-docs/TESTING.md#a-test-must-prove-behaviour) | Whether the tests prove anything, or only execute code |

Then the page covering what the diff touches: [`ARCHITECTURE.md`](../../../dev-docs/ARCHITECTURE.md), [`PARSER.md`](../../../dev-docs/PARSER.md), [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md), [`DEPENDENCY-GRAPH.md`](../../../dev-docs/DEPENDENCY-GRAPH.md), [`FUNCTION-CATALOGUE.md`](../../../dev-docs/FUNCTION-CATALOGUE.md), [`I18N.md`](../../../dev-docs/I18N.md).
Then the page covering what the diff touches: [`ARCHITECTURE.md`](../../../hyperformula/dev-docs/ARCHITECTURE.md), [`PARSER.md`](../../../hyperformula/dev-docs/PARSER.md), [`INTERPRETER.md`](../../../hyperformula/dev-docs/INTERPRETER.md), [`DEPENDENCY-GRAPH.md`](../../../hyperformula/dev-docs/DEPENDENCY-GRAPH.md), [`FUNCTION-CATALOGUE.md`](../../../hyperformula/dev-docs/FUNCTION-CATALOGUE.md), [`I18N.md`](../../../hyperformula/dev-docs/I18N.md).

Review in the order below, and stop to report the first serious finding rather than burying it under style notes.

Expand All @@ -29,15 +29,15 @@ Review in the order below, and stop to report the first serious finding rather t

## 3. Completeness of a function change

Check every one of [the five places a function change must touch](../../../dev-docs/INTERPRETER.md#the-five-places-a-function-change-must-touch); most of them fail silently when missed. Plus `sizeOfResultArrayMethod` for anything array-returning, and an explicit `optionalArg` where arity does not express the valid call. Skill `hyperformula-function-dev`.
Check every one of [the five places a function change must touch](../../../hyperformula/dev-docs/INTERPRETER.md#the-five-places-a-function-change-must-touch); most of them fail silently when missed. Plus `sizeOfResultArrayMethod` for anything array-returning, and an explicit `optionalArg` where arity does not express the valid call. Skill `hyperformula-function-dev`.

## 4. Performance

Allocation in a per-cell or per-vertex loop; work that could be hoisted out of the broadcast path; a range expanded into per-cell iteration; anything that widens what a change invalidates; a `ParserWithCaching` change that makes the result depend on something outside the cache key. Ask for `npm run test:performance` on hot-path changes.

## 5. Public API

`src/HyperFormula.ts` and its exported types are the contract. A signature, return-type, or behaviour change is breaking and needs a migration-guide section and an explicit note. JSDoc here is published output — review it as documentation.
`hyperformula/src/HyperFormula.ts` and its exported types are the contract. A signature, return-type, or behaviour change is breaking and needs a migration-guide section and an explicit note. JSDoc here is published output — review it as documentation.

## 6. Process

Expand Down
38 changes: 19 additions & 19 deletions .claude/skills/hyperformula-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
name: hyperformula-dev
paths: src/**
paths: hyperformula/src/**
description: >
Use for ANY work touching the HyperFormula engine in `src/`: fixing bugs, adding features,
Use for ANY work touching the HyperFormula engine in `hyperformula/src/`: fixing bugs, adding features,
changing the public API, working on the parser, the interpreter, the dependency graph,
CRUD operations, configuration options, named expressions, or number and date formats.
Also use for how-to questions about engine internals (how recalculation works, why a formula
returns an error, where a value is coerced). Triggers on file paths under `src/`, or when the
returns an error, where a value is coerced). Triggers on file paths under `hyperformula/src/`, or when the
user describes a symptom in a calculation without naming a file. This is the primary entry
point for engine development — when in doubt, load it.
---
Expand All @@ -17,43 +17,43 @@ Always:

| File | Why |
|---|---|
| [`ARCHITECTURE.md`](../../../dev-docs/ARCHITECTURE.md) | The pipeline, the core modules, and the invariants that hold everywhere in `src/` |
| [`ARCHITECTURE.md`](../../../hyperformula/dev-docs/ARCHITECTURE.md) | The pipeline, the core modules, and the invariants that hold everywhere in `hyperformula/src/` |
| [`CODE-STYLE.md`](../../../dev-docs/CODE-STYLE.md) | Style, and which paths are hot enough that complexity matters |
| [`DEFINITION-OF-DONE.md`](../../../dev-docs/DEFINITION-OF-DONE.md) | What the change must contain before review |

Then the page for the stage you are changing:

| File | For |
|---|---|
| [`PARSER.md`](../../../dev-docs/PARSER.md) | `src/parser/` — formula text to AST, and back |
| [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md) | `src/interpreter/` — AST to value, and built-in functions |
| [`DEPENDENCY-GRAPH.md`](../../../dev-docs/DEPENDENCY-GRAPH.md) | `src/DependencyGraph/` — dependency tracking and recalculation order |
| [`FUNCTION-CATALOGUE.md`](../../../dev-docs/FUNCTION-CATALOGUE.md) | `src/interpreter/functionMetadata/` — function descriptions |
| [`I18N.md`](../../../dev-docs/I18N.md) | `src/i18n/` — function-name translations |
| [`TESTING.md`](../../../dev-docs/TESTING.md) | Writing the test the change needs |
| [`PARSER.md`](../../../hyperformula/dev-docs/PARSER.md) | `hyperformula/src/parser/` — formula text to AST, and back |
| [`INTERPRETER.md`](../../../hyperformula/dev-docs/INTERPRETER.md) | `hyperformula/src/interpreter/` — AST to value, and built-in functions |
| [`DEPENDENCY-GRAPH.md`](../../../hyperformula/dev-docs/DEPENDENCY-GRAPH.md) | `hyperformula/src/DependencyGraph/` — dependency tracking and recalculation order |
| [`FUNCTION-CATALOGUE.md`](../../../hyperformula/dev-docs/FUNCTION-CATALOGUE.md) | `hyperformula/src/interpreter/functionMetadata/` — function descriptions |
| [`I18N.md`](../../../hyperformula/dev-docs/I18N.md) | `hyperformula/src/i18n/` — function-name translations |
| [`TESTING.md`](../../../hyperformula/dev-docs/TESTING.md) | Writing the test the change needs |

## 2. Locate the stage before changing anything

The engine is a pipeline: `CellContentParser` → `parser/` → `GraphBuilder` → `DependencyGraph/` → `Evaluator` → `interpreter/` → `Serialization`.

| Symptom | Stage |
|---|---|
| Does not parse, or parses wrongly | `src/parser/` |
| `getCellFormula` returns something the user never typed | `src/parser/Unparser.ts` |
| A function returns the wrong value or error | `src/interpreter/plugin/` — skill `hyperformula-function-dev` |
| Value right, but stale after an edit | `src/DependencyGraph/`, `src/Evaluator.ts` |
| Wrong after adding or removing rows or columns | `src/dependencyTransformers/`, `LazilyTransformingAstService.ts` |
| Wrong in one language only | `src/i18n/languages/` — skill `i18n-translations` |
| Coercion or comparison is wrong | `src/interpreter/ArithmeticHelper.ts` |
| The public API disagrees with its docs | `src/HyperFormula.ts` |
| Does not parse, or parses wrongly | `hyperformula/src/parser/` |
| `getCellFormula` returns something the user never typed | `hyperformula/src/parser/Unparser.ts` |
| A function returns the wrong value or error | `hyperformula/src/interpreter/plugin/` — skill `hyperformula-function-dev` |
| Value right, but stale after an edit | `hyperformula/src/DependencyGraph/`, `hyperformula/src/Evaluator.ts` |
| Wrong after adding or removing rows or columns | `hyperformula/src/dependencyTransformers/`, `LazilyTransformingAstService.ts` |
| Wrong in one language only | `hyperformula/src/i18n/languages/` — skill `i18n-translations` |
| Coercion or comparison is wrong | `hyperformula/src/interpreter/ArithmeticHelper.ts` |
| The public API disagrees with its docs | `hyperformula/src/HyperFormula.ts` |

A bug that looks like an interpreter problem is often a parser or graph problem. Confirm which before editing. Use the `typescript-lsp` plugin to find a definition or its callers; grep is for text, not symbols.

## 3. Reproduce first

Write the failing test before the fix and watch it fail — skill `test-writing-discipline`. For a calculation bug the smallest reproduction is a two-line `buildFromArray` plus one `getCellValue`.

If `test/hyperformula-tests/` is absent, `npm run test:jest` runs only the smoke tests and reports a clean pass over almost nothing. Run `npm run test:setup-private` first, and after every branch switch.
If `hyperformula/test/hyperformula-tests/` is absent, `npm run test:jest` runs only the smoke tests and reports a clean pass over almost nothing. Run `npm run test:setup-private` first, and after every branch switch.

## 4. Change, then run the fast loop

Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/hyperformula-function-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
---
name: hyperformula-function-dev
paths: src/interpreter/**
paths: hyperformula/src/interpreter/**
description: Use when adding a new built-in spreadsheet function to HyperFormula, changing an existing one's signature, arguments, return type, or error behaviour, or when a function returns the wrong value or the wrong error. Covers the FunctionPlugin contract, runFunction and argument metadata, the function metadata catalogue, translations, and the full end-to-end checklist.
---

## 1. Read the relevant files from `dev-docs/`

| File | Why |
|---|---|
| [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md#built-in-functions) | The plugin contract, `runFunction`, and every argument and function metadata field. Read this before writing any code. |
| [`FUNCTION-CATALOGUE.md`](../../../dev-docs/FUNCTION-CATALOGUE.md) | What the catalogue entry must contain, and the two ways to get it wrong |
| [`I18N.md`](../../../dev-docs/I18N.md) | Where to source a translation, and why an invented one cannot be taken back |
| [`INTERPRETER.md`](../../../hyperformula/dev-docs/INTERPRETER.md#built-in-functions) | The plugin contract, `runFunction`, and every argument and function metadata field. Read this before writing any code. |
| [`FUNCTION-CATALOGUE.md`](../../../hyperformula/dev-docs/FUNCTION-CATALOGUE.md) | What the catalogue entry must contain, and the two ways to get it wrong |
| [`I18N.md`](../../../hyperformula/dev-docs/I18N.md) | Where to source a translation, and why an invented one cannot be taken back |
| [`TESTING.md`](../../../dev-docs/TESTING.md#what-each-kind-of-change-needs) | The list of cases a function change must cover |
| [`DEFINITION-OF-DONE.md`](../../../dev-docs/DEFINITION-OF-DONE.md) | What the change must contain before review |

## 2. Touch all five places

A function is not done until all five agree, and they do not fail the same way — a missing catalogue entry fails the docs build, a parameter-count mismatch only warns on the console, and the rest fail silently.

The list is in [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md#the-five-places-a-function-change-must-touch). Work through it there rather than from a copy; two of the five have their own page, linked from it.
The list is in [`INTERPRETER.md`](../../../hyperformula/dev-docs/INTERPRETER.md#the-five-places-a-function-change-must-touch). Work through it there rather than from a copy; two of the five have their own page, linked from it.

## 3. Declare the two things nothing cross-checks

Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/hyperformula-unit-testing/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
---
name: hyperformula-unit-testing
paths: test/**
description: Use when writing or modifying tests for HyperFormula, or when a change to `src/` needs test coverage. Covers the two suites, fetching the private suite, how to build an engine in a test, and what a function or CRUD change must cover.
paths: hyperformula/test/**
description: Use when writing or modifying tests for HyperFormula, or when a change to `hyperformula/src/` needs test coverage. Covers the two suites, fetching the private suite, how to build an engine in a test, and what a function or CRUD change must cover.
---

## 1. Read the relevant files from `dev-docs/`

| File | Why |
|---|---|
| [`TESTING.md`](../../../dev-docs/TESTING.md) | The two suites, how to write a case, and what each kind of change must cover |
| [`TESTING.md`](../../../hyperformula/dev-docs/TESTING.md) | The two suites, how to write a case, and what each kind of change must cover |
| [`WORKTREES.md`](../../../dev-docs/WORKTREES.md) | Only when working in a linked worktree, where the private suite is absent entirely |

And [`test/README.md`](../../../test/README.md) for how the private suite is fetched and the environment variables it honours.
And [`hyperformula/test/README.md`](../../../dev-docs/README.md) for how the private suite is fetched and the environment variables it honours.

## 2. Attach the private suite before trusting anything

```bash
npm run test:setup-private
```

Run it after every branch switch. Without `test/hyperformula-tests/` the Jest run covers only the smoke tests and reports a clean pass over almost nothing — the most common false signal in this repository. `test:performance`, `test:compatibility` and the benchmarks all resolve into that directory, so without it they fail on a missing path rather than on an assertion; read the error before concluding the code is broken.
Run it after every branch switch. Without `hyperformula/test/hyperformula-tests/` the Jest run covers only the smoke tests and reports a clean pass over almost nothing — the most common false signal in this repository. `test:performance` and `test:compatibility` fail on a missing path rather than an assertion; read the error before concluding the code is broken.

## 3. Write the case from the requirement

Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/i18n-translations/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
name: i18n-translations
paths: src/i18n/**
paths: hyperformula/src/i18n/**
description: Use when adding a built-in function that needs translated names, adding a language pack, or fixing a function name that is wrong in one language. Covers the translation sources, the rules, and what breaks when a key is missing.
---

## 1. Read the relevant files from `dev-docs/`

| File | Why |
|---|---|
| [`I18N.md`](../../../dev-docs/I18N.md) | Why translations are engine input rather than decoration, the rules, and the table of sources to translate from |
| [`PARSER.md`](../../../dev-docs/PARSER.md) | Only when changing separators or error literals — the lexer builds its token set from the language package |
| [`I18N.md`](../../../hyperformula/dev-docs/I18N.md) | Why translations are engine input rather than decoration, the rules, and the table of sources to translate from |
| [`PARSER.md`](../../../hyperformula/dev-docs/PARSER.md) | Only when changing separators or error literals — the lexer builds its token set from the language package |

## 2. Look the name up in a real source

Use the sources in [`I18N.md`](../../../dev-docs/I18N.md#where-to-find-a-translation), in the order listed. **Never invent or machine-translate a function name.** A wrong one ships to every user of that language pack and cannot be changed without breaking their formulas.
Use the sources in [`I18N.md`](../../../hyperformula/dev-docs/I18N.md#where-to-find-a-translation), in the order listed. **Never invent or machine-translate a function name.** A wrong one ships to every user of that language pack and cannot be changed without breaking their formulas.

## 3. Add the key to every language file

Expand All @@ -32,4 +32,4 @@ npm run lint

## Adding a whole language pack

The file, its export in `src/i18n/languages/index.ts`, a key set identical to the other packs, a changelog entry, and `npm run bundle:languages` for the standalone UMD build.
The file, its export in `hyperformula/src/i18n/languages/index.ts`, a key set identical to the other packs, a changelog entry, and `npm run bundle:languages --workspace=hyperformula` for the standalone UMD build.
2 changes: 1 addition & 1 deletion .claude/skills/pr-creation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ npm run lint
npm run test:jest
```

A green Jest run without `test/hyperformula-tests/` covers only the smoke tests. Confirm the suite is attached before calling it green. Do not open a pull request on a red run and describe it as ready.
A green Jest run without `hyperformula/test/hyperformula-tests/` covers only the smoke tests. Confirm the suite is attached before calling it green. Do not open a pull request on a red run and describe it as ready.

## 4. Push and open the pull request

Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/test-writing-discipline/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ When a test is red the default assumption is that the code is wrong. Changing th

## 5. Run it again and read the output

Never claim a test passes because the reasoning is sound. And before treating green as coverage, confirm `test/hyperformula-tests/` is present — `npm run test:setup-private`.
Never claim a test passes because the reasoning is sound. And before treating green as coverage, confirm `hyperformula/test/hyperformula-tests/` is present — `npm run test:setup-private`.

## If you cannot make it pass honestly

Expand Down
Loading
Loading