HF-359: Restructure the repository as a monorepo - #1758
Merged
sequba merged 10 commits intoSep 1, 2026
Conversation
Implements the migration steps recorded in dev-docs/MONOREPO.md. - src/, test/ and the whole engine toolchain (tsconfig, jest, karma, webpack, babel, .config/, typedoc) move into hyperformula/, which becomes the published package and carries its own README, CHANGELOG, LICENSE and .nvmrc. - The root package.json becomes a private workspace root listing hyperformula and hyperformula-ui, with fan-out scripts. Linting is the deliberate exception: it still runs once from the root over the whole repository, so nothing between packages falls through the gap. - docs/ becomes its own package, installed separately with `npm run docs:install`, so the VuePress 1.x tree never reaches an engine install. It takes ownership of its deployment: wrangler.jsonc and worker/ move under it. - hyperformula-ui/ is created as a placeholder; the package is imported from the formula-builder repository separately. - Every .nvmrc says 22, and each package keeps its own CHANGELOG.md in the existing Keep a Changelog form. Three things the move forced, none of them cosmetic: The built-in-functions generator moved to docs/script/. It uses @vuepress/shared-utils for slugs, and that package requires markdown-it-emoji and an older lru-cache major without declaring either, relying on vuepress to hoist them. Outside a full VuePress tree it cannot load at all, so the generator has to live where that tree is. Three paths in the portal were written from the old repository root and broke when VuePress started building from docs/ as its own package: the code-snippet plugin fell back to process.cwd() and looked for docs/docs/examples/, graph.vue imported the engine bundle from ../../../dist, and dest wrote the site to docs/docs/. All three are now anchored explicitly. The engine dev-docs pages stay in the single root dev-docs/ rather than being split into a package-level copy as the plan sketched. Two directories fragment the single source of truth and force every page to know which scope it was written from. Verified end to end: npm ci, lint (0 errors, 54011 warnings - the exact pre-move baseline), jest (502 suites, 6232 passed), tsc --noEmit, bundle-all including the publish-package check, the function-docs generator, typedoc, and the full portal build (217 pages) plus the Cloudflare asset step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
Task linked: HF-359 Add formula builder core to hyperformula repo |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
hyperformula-docs | 480123c | Sep 01 2026, 10:37 AM |
Eleven findings, verified against the tree before acting. The portal was publishing internal agent instructions. VuePress sweeps every markdown file under docs/, so AGENTS.md and its CLAUDE.md symlink were built into /AGENTS.html and a byte-identical /CLAUDE.html, sitemap and search index included, with links pointing outside the site. Both are excluded now, and the rebuilt site no longer contains them. The PostToolUse hook gained the report it was missing and lost three latent faults. It rewrites the file underneath the agent, which invalidates the line numbers the agent is holding; on the path where every error was auto-fixed it used to exit 0 in silence, and the next Edit would fail its modified-since-read check for no visible reason. It now says what it changed and asks for a re-read. ESLint is invoked as `node node_modules/eslint/bin/eslint.js` from the project directory rather than through `npx` with no cwd: that fixes resolution of both the binary and .eslintignore (ESLint 8 reads it relative to the working directory, so a hook running elsewhere would lint and auto-fix deliberately excluded paths), removes the shell whose unquoted argv would split a checkout path containing a space, and drops a process from every edit. The report is flushed by setting process.exitCode instead of calling process.exit, which does not wait for asynchronous writes to a pipe. The deny rules used the `./` form, which anchors at the current directory. The `/` form anchors at the settings source, which is what was meant. `npm run test:compatibility` pointed at test/compatibility/test-compatibility.sh, a path that exists in neither repository. The script is in the private suite, at test/hyperformula-tests/compatibility/. Pre-existing; the review surfaced it through a contradiction in TESTING.md, which is corrected too. Cloudflare deploy credentials are no longer copied into worktrees. Every subagent-isolation worktree was receiving a deploy token it has no use for, for the convenience of the one maintainer who runs wrangler. Also: ARCHITECTURE.md placed absolutizeDependencies.ts in src/parser/ when it is at the source root, and described config defaults as living in ConfigParams.ts when that file is an interface declaration and the values are in Config.defaultConfig; DEFINITION-OF-DONE.md and the changelog skill disagreed on when an entry is required; and the hook's header announced two deliberate choices while listing more. Verified: lint 0 errors, jest 502 suites / 6232 passed, portal rebuilt (agent pages absent from the output and the sitemap), and the hook exercised across auto-fix-only, unfixable-error, already-clean, eslintignored, malformed-input and non-lintable-extension paths. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`docs/api/` and `docs/guide/built-in-functions.md` were on the agent deny list alongside the build artifacts, while dev-docs/FUNCTION-CATALOGUE.md links straight into both of them. An agent following that link hit a permission refusal with no explanation. They are generated, but they are not artifacts: they are the API reference and the function reference, and reading them to answer a question is the right move. The deny list is about bundles, declarations, coverage and the compiled site. Editing either file is still pointless — the build regenerates them — and that is stated where the rule lives rather than enforced by blocking reads. Two stale claims fell out of the same pass. AGENT-TOOLING.md and WORKTREES.md both still documented `worktree.symlinkDirectories` as a current setting; it was removed when the repository became a workspace. WORKTREES.md now records why it must not come back, including that `npm ci` inside a worktree whose `node_modules` is a symlink installs through it and silently rewrites the main checkout's dependency tree. WORKTREES.md also still said `.dev.vars` was copied into worktrees automatically, which stopped being true when the deploy credentials were taken out of `.worktreeinclude`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`npm run test:browser` executed all 6232 specs successfully in both browsers and then exited 1 anyway, because Chrome reported "Some of your tests did a full page reload!" during teardown. The failure predates this branch - it reproduces on the pre-move tree - but it was intermittent there and would have made the CI job flaky. The cause is `client.clearContext: false` in the shared Karma base config. Karma has to be allowed to clear its context iframe when a run finishes; prevented from doing so, it sees the page still there and reports it as a reload after the results are already in. `concurrency: 1` was the obvious first guess and is wrong. It does not remove the error, it doubles the wall-clock time, and by making Chrome's teardown the last thing that happens it turns an intermittent failure into a deterministic one: three of three runs exited 1 rather than one of two. That determinism was useful for testing the real fix, and is the reason this commit does not carry it. `clearContext: false` does belong in `.config/karma/debug.js`, which is what the option is for: `singleRun` is false there, a human is watching, and the kjhtml results page has to survive between runs. It is set explicitly there now rather than inherited. Verified: three consecutive runs at exit 0, zero ERROR lines, `TOTAL: 12464 SUCCESS`, ~31s - unchanged from the parallel timing. The debug config still resolves to `clearContext: false`, `singleRun: false`, `kjhtml`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings 80753c5 from feat/hf-359-monorepo-agent-setup, and resolves the four files both branches touched. AGENTS.md takes the base's resolution outright: the routing table is gone, since it now lives in dev-docs/README.md. dev-docs/README.md keeps that table, with the entries this branch changed - the engine source is hyperformula/src/, the private test suite README moved with it, and there is no longer a separate monorepo page to link. STRUCTURE.md is the interesting one. The base merged MONOREPO.md into it because both files carried a tree and a reader could not tell which was current. That argument still holds here, but the content is different: on this branch the move has happened, so the tree is the monorepo and what MONOREPO.md held is a record rather than a plan. It becomes three closing sections - what the move still owes, what it decided, and the two pre-existing problems it uncovered. MONOREPO.md is deleted, and its last two references, in CHANGELOG.md and hyperformula-ui/README.md, now point at the section that answers them. WORKTREES.md needed no resolution beyond this branch's version: it had already stopped referring to MONOREPO.md when the symlink section was rewritten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings 83eb116 from feat/hf-359-monorepo-agent-setup. Two conflicts, both resolved in favour of the removal. script/claude/post-tool-use.mjs was deleted on the base and rewritten here, in the review round that made it report its own edits and invoke ESLint directly. The file goes; the reasoning behind that rewrite is preserved only in the history of the branch. dev-docs/AGENT-TOOLING.md keeps this branch's settings table - which draws the line between build artifacts and generated documentation - minus the `hooks` row, and loses the section describing the hook. Neither side's remaining extra row survives: `worktree.symlinkDirectories` was already removed here when the repository became a workspace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eighteen review findings, each verified against the tree before and after. The worst was silent. Every delegating root script dropped its flag arguments: `npm run test:ci -- --coverage` reached the workspace as bare `jest --forceExit`, so CI has been uploading nothing to Codecov while staying green. Demonstrated with `npm run test:jest -- --listTests`, which ran all 6232 tests instead of listing them. Every delegating script now ends with `--`, and `test:ci --coverage` writes hyperformula/coverage at 97.42%. The release script was never adapted. It read and wrote ./package.json - now the private root manifest with no version - so a freeze would have bumped the wrong file, skipped HT_RELEASE_DATE, and found no changelog. It now resolves the package through PKG_DIR, and a dry run produces the right version, dates and changelog section. A third path the review did not catch turned up in that dry run: the private test suite check still pointed at test/hyperformula-tests. check:licenses both failed outright and, if forced to pass, checked nothing: license-checker reads <start>/node_modules, and npm hoists, so from hyperformula/ it sees an empty tree and from the root a manifest with no dependencies - zero packages either way. Replaced with script/check-licenses.mjs, which takes the production set from `npm ls --omit=dev` and the licence data from a full license-checker run. It resolves 3 dependencies and fails when the allowlist is tightened, which was tested rather than assumed. Also: performance-report.md was written inside the workspace and read from the root; code-examples-generator.sh kept repo-root-relative paths after moving to docs/, so it processed zero files and exited 0; docs:build:cf never installed the portal, which is the command Cloudflare runs; docs:install used `npm install` against a committed lockfile; the licence-header rule resolved against the working directory, so linting from inside the package threw on every file; coverage globbed the AGENTS.md files in src/; the .npmignore un-ignore for the logo matched nothing after the move; test:jest and test:ci named ../node_modules paths that only hold while npm hoists - NODE_ICU_DATA is dropped outright, since Node has shipped full ICU since v13 and .nvmrc pins 22. hyperformula-ui came out of the workspaces array. npm silently ignores an entry with no package.json, so it bought nothing, and three documents claimed the workspace existed - one promising it would "resolve once the package lands", when in fact `npm ci` would fail against this lockfile. It goes back in the same change that adds the package. The documentation followed the code: the public building guide named six root scripts that no longer exist and two arg-passing forms that were broken, the portal README still told developers to install docs dependencies with a root `npm install`, and dev-docs, two skills and .worktreeinclude each pointed at something this branch had moved or deleted. Verified: lint 0 errors, jest 502 suites / 6232 passed, tsc --noEmit, bundle-all with the publish check, the licence gate positive and negative, a release dry run, the docs generator, and the full portal build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three structural changes, all following the same rule: a thing lives with whatever owns it, and exactly one place holds each fact. dev-docs/ now exists at two levels. The repository level keeps what applies everywhere - the definition of done, code style, testing standards, documentation rules, build and release, pull requests, worktrees, the agent setup. hyperformula/dev-docs/ holds the engine's internals: architecture, the parser, the interpreter, the dependency graph, the function catalogue, translations, its test suites and its own build steps. This reverses a call made during the migration, which kept one directory on the grounds that two would fragment the single source of truth. That conflated a single source with a single directory: splitting by ownership is not duplication, and keeping every package's internals at the root would have made the root a dumping ground the moment hyperformula-ui lands. Three pages were genuinely mixed and were split rather than moved. TESTING keeps what a change must prove and how a case is written at the root, and takes the suites, the private one, and the per-change coverage into the package. BUILD keeps installing the workspace, generating the documentation, deploying the portal and cutting a release, and takes the intermediate lib/ build and packaging down. CODE-STYLE keeps style and TypeScript, and the hot-path table becomes hyperformula/dev-docs/PERFORMANCE.md. script/ splits three ways, which the callers decided rather than judgement: every script had exactly one caller and the caller named its owner. check-file, check-publish-package and if-ne-env go to hyperformula/script/; prepare-cf-assets joins the generator in docs/script/; release/ and check-licenses.mjs stay, because they span the packages and the sibling repositories. Twelve call sites stop reaching across a package boundary, and two scripts stop resolving paths through ../hyperformula and ../docs - a smell the move introduced and this removes. examples/ is deleted. Its three PNGs were byte-identical duplicates of files in docs/.vuepress/public/, which is what the site actually serves through $withBase; the remaining five files were referenced nowhere in the repository, in any config, workflow or package script. It was not moved under docs/ because docs/examples/ already exists and is a different thing - the runnable examples embedded in the guides. Verified: lint 0 errors, jest 502 suites / 6232 passed, the licence gate, bundle-all through the relocated engine scripts with the publish check, and the full portal build including build:cf through the relocated prepare-cf-assets. Every relative link in AGENTS.md, both dev-docs levels, the skills and the READMEs resolves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings a000d8f from feat/hf-359-monorepo-agent-setup. Nine files conflicted, because the audit corrected pages that this branch had since moved or split. The corrections were carried to wherever the content now lives rather than resolved by picking a side. ARCHITECTURE.md, INTERPRETER.md, FUNCTION-CATALOGUE.md and I18N.md are in hyperformula/dev-docs/ here, so the two file-location fixes, the single authoritative list of the five places a function change must touch, the loud-versus-silent split, the dropped docs/api link and the separators correction all landed there. TESTING.md and BUILD.md are split between the two levels on this branch, so each half took the part of the fix that belonged to it. Three link depths changed with the files: the skills now point at hyperformula/dev-docs/ for INTERPRETER, FUNCTION-CATALOGUE and I18N. One pre-existing defect surfaced while resolving: dev-docs/TESTING.md pointed at the package's testing page as `TESTING.md`, which from that file is itself. Fixed. test:compatibility was already corrected here, in the same way the audit recommends, so the base's change to it merged as a no-op. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reverses the per-package cadence this branch had built. CHANGELOG.md returns to the repository root as the single history for every package - the file keeps its identity, since it was only moved into hyperformula/ by this branch in the first place - and the index that replaced it is gone. Getting that changelog into the published tarball took three attempts, because npm will not do it the obvious ways. A `prepack` script that copies the file in runs too late: npm resolves the pack file list before the hook, so the copy is on disk and absent from the tarball. A symlink to ../CHANGELOG.md is excluded outright. What works is an explicit `copy-changelog` step in front of anything that packs, so it is wired into verify:publish-package and into the release script, and the copy is git-ignored. That fix uncovered a second monorepo gap in release.sh, which the earlier pass missed because it only corrected the paths the script reads. Step 7 ran `npm publish` at the repository root, where the manifest is now private and npm refuses to publish. It publishes the workspace now. The decision itself is recorded in dev-docs/STRUCTURE.md with what it costs: a release cuts every published package at the same version whether or not its code moved, in exchange for one number that identifies the state of the whole repository. hyperformula-ui no longer gets a changelog of its own when it lands, and its version moves in step with the engine's - the release script bumps one manifest today and will need the second in that same change. Verified: the tarball carries CHANGELOG.md again (Publish package check: OK), a release dry run finds the root file and inserts the version section, lint 0 errors, jest 502 suites / 6232 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sequba
marked this pull request as ready for review
September 1, 2026 10:49
sequba
merged commit Sep 1, 2026
72001ee
into
feat/hf-359-monorepo-agent-setup
28 of 30 checks passed
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/hf-359-monorepo-agent-setup #1758 +/- ##
=================================================================
Coverage 97.32% 97.32%
=================================================================
Files 195 195
Lines 15739 15739
Branches 3390 3390
=================================================================
Hits 15318 15318
Misses 421 421
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Turns the repository into a monorepo (HF-359). Stacked on #1757 — review that first; this branch is based on it.
No changes under
hyperformula/src/. Every file there is byte-identical to its old location atsrc/; git records the moves as renames throughout, so history follows. The published package's name, version, entry points andexportsmap are unchanged, and the publish-package check confirms the tarball contents.The layout
docs/left the workspace. VuePress 1.x and its--openssl-legacy-providertree must never reach an engine install.npm run docs:installinstalls it; CI installs it before building the portal.wrangler.jsoncandworker/moved underdocs/, and the asset directory is now./.vuepress/dist..nvmrc(all22) andCHANGELOG.md. The root changelog is an index.src/andtest/moved together, the depth from a spec to the package root is unchanged.Everything lives with what owns it
Three directories are scoped by ownership rather than by convenience:
dev-docs/hyperformula/dev-docs/— architecture, parser, interpreter, dependency graph, function catalogue, i18n, performance, its suites, its buildscript/release/,check-licenses.mjshyperformula/script/— build checks;docs/script/— the generator and the Worker assetsThree
dev-docspages were genuinely mixed and were split, not moved:TESTING(what a change must prove stays; the suites go down),BUILD(workspace, deploy and release stay; the intermediate build and packaging go down), andCODE-STYLE(style stays; the hot-path table becomeshyperformula/dev-docs/PERFORMANCE.md).The
script/split was decided by the callers, not by judgement: every script had exactly one caller and the caller named its owner. Twelve call sites stopped reaching across a package boundary, and two scripts stopped resolving paths through../hyperformula/and../docs/.examples/at the root is deleted: three of its PNGs were byte-identical duplicates ofdocs/.vuepress/public/, which is what the site actually serves through$withBase, and the remaining five files were referenced nowhere in the repository, in any config, workflow or package script. It was not moved underdocs/, becausedocs/examples/already exists and is a different thing — the runnable examples embedded in the guides.Three things the move forced
The built-in-functions generator moved to
docs/script/. It uses@vuepress/shared-utilsfor slugs, and that packagerequire()smarkdown-it-emojiand an olderlru-cachemajor without declaring either, relying onvuepressto hoist them. Outside a full VuePress tree it throws on load, so the generator has to live where that tree is.Three portal paths were written from the old repository root and broke once VuePress built from
docs/as its own package. All three are now anchored explicitly rather than depending on cwd:process.cwd()docs/docs/examples/, so every guide with an example failed to compilegraph.vue../../../dist/hyperformula.fulldist/at the repository root that no longer existsdestdocs/.vuepress/dist/docsdocs/docs/One decision was reversed. The migration first kept a single
dev-docs/, on the grounds that two directories would fragment the single source of truth. That conflated a single source with a single directory — splitting by ownership is not duplication, and keeping every package's internals at the root would have made the root a dumping ground the momenthyperformula-uilands.How did you test your changes?
Everything below was run on this branch, and re-run after each review round:
npm cinpm run lintnpm run test:jestnpm run test:ci -- --coveragehyperformula/coveragenpm run test:browsernpm run verify:typingstsc --noEmitcleannpm run bundle-allPublish package check: OKnpm run check:licensesnpm run release code-freeze …(dry run)npm run docs:generate-function-docsnpm --prefix docs run build:cf_headersand_redirectscopiedEvery relative Markdown link in
AGENTS.md, bothdev-docs/levels, the skills and the READMEs was resolved against the filesystem. All resolve.What the reviews found
Two rounds, 36 findings. What they caught, and what I got wrong:
Flag arguments were being swallowed. Every delegating root script dropped them, so
npm run test:ci -- --coveragereached the workspace as barejest --forceExitand CI had been uploading nothing to Codecov while staying green. Demonstrated withnpm run test:jest -- --listTests, which ran all 6232 tests instead of listing them.The release script was never adapted. It read and wrote
./package.json— now the private root manifest with noversion. A dry run then surfaced a third path the review had not caught: the private test suite check still pointed attest/hyperformula-tests.check:licenseswas checking nothing.license-checkerreads<start>/node_modules, and npm hoists, so fromhyperformula/it saw an empty tree and from the root a manifest with no dependencies — zero packages either way, passing vacuously. Replaced withscript/check-licenses.mjs, which takes the production set fromnpm ls --omit=devand the licence data from a fulllicense-checkerrun.The portal was publishing internal agent instructions. VuePress sweeps every markdown file under
docs/, sodocs/AGENTS.mdand itsCLAUDE.mdsymlink were being built into/AGENTS.htmland a byte-identical/CLAUDE.html, sitemap and search index included.npm run test:browserexited non-zero after passing. All 6232 specs passed in both browsers and always did; Chrome then reportedSome of your tests did a full page reload!during teardown. The cause wasclient.clearContext: falsein the Karma base config, and it reproduced on the pre-move tree, so it predates this branch.concurrency: 1was the obvious first guess and is wrong — it does not remove the error, it doubles wall-clock time, and it turns an intermittent failure into a deterministic one. That determinism was what made the real fix testable, but it is not in the branch.Also fixed: the report path in
performance.yml,code-examples-generator.shsilently processing zero files,docs:build:cfnever installing the portal,docs:installusingnpm installagainst a committed lockfile, the licence-header rule resolving against the working directory,hyperformula-uilisted as a workspace with nopackage.json, a dead.npmignorerule, and a dozen documentation pages naming commands or paths this branch had moved.One finding was rejected on measurement — the claim that the type-aware ESLint program build risks the hook's 60 s timeout. Measured at 0.91 s and 1.06 s. That hook has since been removed anyway, at the author's request.
Two pre-existing problems the move uncovered
The source language packs have never been linted. The old ignore list carried a bare
languagesentry meant for the build output. An unanchored pattern matches a directory of that name at any depth, so it also excludedsrc/i18n/languages/— and thesort-keysoverride that targets exactly those files has therefore never run. Anchoring the build-output entry exposed 881 violations across 19 translation files. Confirmed by lintingsrc/i18n/languages/enGB.tson the pre-move tree, where ESLint reportsFile ignored because of a matching ignore pattern.They are excluded again in
.eslintignore, deliberately and with a comment explaining why, so this branch keeps the exact pre-move lint baseline. Sorting 19 translation files is a change of its own — and reordering translation entries is precisely what the i18n guidance tells contributors not to do casually.npm run test:compatibilitywas broken for everyone. It pointed attest/compatibility/test-compatibility.sh, a path that exists in neither repository; the script ships with the private suite. Fixed here, since the branch had to touch it anyway.Not done, on purpose
CI path filtering. A naive
paths:filter on a workflow that branch protection lists as a required check leaves the check permanently pending and makes pull requests unmergeable. Doing it safely needs the required-checks list, which lives in repository settings rather than in the tree, plus thedorny/paths-filter-and-single-gate shape the Handsontable monorepo uses. The CI paths are all updated; only the filtering is outstanding.Importing
hyperformula-ui— left for the teammate who owns the formula-builder move. It is deliberately not in theworkspacesarray until then: npm silently ignores an entry with nopackage.json, and the lockfile has to be regenerated when the real package lands either way.Both are recorded in
dev-docs/STRUCTURE.mdunder "What the move still owes".Types of changes
Repository structure and tooling. The published package is unchanged.
Related issues:
Checklist:
dev-docs/at both levels,docs/README.mdand the public building guide are updated in this change.🤖 Generated with Claude Code
Note
Medium Risk
Large CI, release, and docs-build path changes can break merges or deployments even though the published engine package is unchanged; incorrect workspace or portal wiring would surface as green CI with missing coverage or failed doc builds.
Overview
Restructures the repository into an npm workspaces monorepo: the calculation engine lives under
hyperformula/(withsrc/andtest/moved there unchanged),docs/stays a separate install vianpm run docs:install, andhyperformula-ui/is a placeholder for a later import.The private root fans out build and test scripts with
--workspace=hyperformula; ESLint stays at the repo root and now points TypeScript athyperformula/tsconfig.json. CI workflows,.gitignore, and the private test checkout path move tohyperformula/test/hyperformula-tests/; docs and publish workflows adddocs:installbeforedocs:build.Documentation and agent tooling are retargeted to the new paths: root
README.mdbecomes a monorepo overview,dev-docs/is split (repo-wide vshyperformula/dev-docs/), Claude skills and.claude/settings.jsondeny lists use/hyperformula/...paths, andworktree.symlinkDirectoriesfornode_modulesis removed. The VuePress portal is fixed for building fromdocs/(bundle import paths, snippet plugin root,dest, exclusion ofAGENTS.md/CLAUDE.mdfrom the site).Tooling follow-ups in the diff:
.eslintignorere-anchors build outputs and temporarily re-excludes sourcei18n/languagesafter exposing long-standingsort-keysdebt;.worktreeincludestops auto-copying secrets and build artifacts.Reviewed by Cursor Bugbot for commit 480123c. Bugbot is set up for automated code reviews on this repo. Configure here.