v1.1.0: repo polish, CI fixes, version alignment, dead artifact cleanup
Root package: renamed to imhotep-monorepo, fixed broken scripts (test:unit/integration/e2e), removed inappropriate root deps, fixed build order, updated clean script CI: branch trigger main->master, npm ci->npm install, GitHub cache URL->Gitea Docs: replaced scaffolded root README with real project README, added package READMEs for imhotep/imhotep-playwright/imhotep-dsl/imhotep-core, added RELEASE.md checklist Version: all 14 packages and root aligned to 1.1.0, CHANGELOG test count fixed (1125) Metadata: 14 repository URLs github->gitea, 13 package descriptions added, imhotep-cli exports field added, SECURITY.md updated for Gitea+disclosure email Quality: noEmitOnError:true in 13 tsconfigs, collapsed duplicate interfaces in public.ts, clippedBy test->test.skip, fixed broken dynamic import in imhotep index.test.ts, 694 generated src artifacts cleaned, V8 logs removed, .gitignore updated
This commit is contained in:
@@ -2,9 +2,9 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm install
|
||||
- run: npm run lint
|
||||
|
||||
build:
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: npm run typecheck
|
||||
- uses: https://gitea.com/actions/upload-artifact@v4
|
||||
@@ -49,12 +49,12 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm install
|
||||
- uses: https://gitea.com/actions/download-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
- run: npm test
|
||||
- run: npm run test:integration --workspaces --if-present
|
||||
- run: npm run test:integration -w imhotep-playwright
|
||||
|
||||
e2e:
|
||||
needs: [build, lint, unit]
|
||||
@@ -65,19 +65,19 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm install
|
||||
- uses: https://gitea.com/actions/download-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
- name: Cache Playwright browsers
|
||||
uses: https://github.com/actions/cache@v4
|
||||
uses: https://gitea.com/actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: playwright-${{ runner.os }}-${{ hashFiles('package.json') }}
|
||||
- run: npx playwright install chromium
|
||||
- run: npm run test:e2e -w imhotep-fixtures
|
||||
- run: npm run test:external-smoke
|
||||
- run: npm run test --workspace=imhotep-bench
|
||||
- run: npm run test -w imhotep-bench
|
||||
- run: |
|
||||
for pkg in packages/*/; do
|
||||
name=$(node -p "require('./${pkg}package.json').name")
|
||||
|
||||
@@ -42,3 +42,7 @@ feature-test/
|
||||
|
||||
# Dead GitHub config (migrated to Gitea)
|
||||
.github/
|
||||
|
||||
# V8 and npm debug logs
|
||||
isolate-*.log
|
||||
.npm/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm install
|
||||
```
|
||||
|
||||
## Build All Packages
|
||||
@@ -25,23 +25,34 @@ Root build executes workspaces in dependency order. All 14 packages compile clea
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
## Unit/Integration Test Sweep
|
||||
## Unit Tests
|
||||
|
||||
```bash
|
||||
npm test --workspaces
|
||||
npm test
|
||||
```
|
||||
|
||||
Runs all tests across all workspaces. Current status: **959 unit tests passing, 0 failures**.
|
||||
Runs all tests across all workspaces.
|
||||
|
||||
## Integration Tests
|
||||
|
||||
```bash
|
||||
npm run test:integration
|
||||
```
|
||||
|
||||
Pooling, property runner, and cross-package integration tests (imhotep-playwright).
|
||||
|
||||
## E2E (Playwright)
|
||||
|
||||
```bash
|
||||
npx playwright test --config packages/imhotep-fixtures/playwright.config.ts
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
Playwright config lives at `packages/imhotep-fixtures/playwright.config.ts` and targets `packages/imhotep-fixtures/src/e2e*.test.ts`.
|
||||
Playwright config lives at `packages/imhotep-fixtures/playwright.config.ts` and targets compiled E2E tests under `packages/imhotep-fixtures/dist/`. Requires a prior build.
|
||||
|
||||
Current status: **215 E2E tests passing, 0 failures**.
|
||||
To run directly:
|
||||
```bash
|
||||
npx playwright test --config packages/imhotep-fixtures/playwright.config.ts
|
||||
```
|
||||
|
||||
## External Smoke Test
|
||||
|
||||
@@ -55,8 +66,8 @@ Creates a clean temp directory, installs packages from local paths, and runs a f
|
||||
|
||||
```bash
|
||||
# Run tests for a specific package
|
||||
npm test -w packages/imhotep-playwright
|
||||
npm test -w packages/imhotep-fixtures
|
||||
npm test -w imhotep-playwright
|
||||
npm test -w imhotep-fixtures
|
||||
|
||||
# Run specific E2E test file
|
||||
npx playwright test packages/imhotep-fixtures/src/e2e-public.test.ts
|
||||
@@ -68,6 +79,8 @@ npx playwright test packages/imhotep-fixtures/src/e2e-public.test.ts
|
||||
npm run clean
|
||||
```
|
||||
|
||||
Removes `dist/`, `tsbuildinfo` files, and any in-source generated artifacts (`*.js`, `*.d.ts`, `*.map` under `packages/*/src/`).
|
||||
|
||||
## Packaging Smoke
|
||||
|
||||
Use this before publishing a package:
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
|
||||
### Test/Verification
|
||||
|
||||
- **959 unit tests** passing across all packages.
|
||||
- **1125 unit tests** passing across all packages.
|
||||
- **215 E2E tests** passing, 0 failures.
|
||||
- External smoke test passes in clean temp directory.
|
||||
- Build succeeds for all 14 packages.
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
# Imhotep Codebase Review
|
||||
|
||||
Date: 2026-05-21
|
||||
|
||||
Perspective: a developer onboarding to contribute to Imhotep, and a developer evaluating whether to adopt the tooling in their own repositories or team workflows.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Imhotep has a strong technical core: the package split is coherent, the test surface is unusually broad for an early framework, diagnostics are treated as first-class product output, and the public concept is compelling for UI teams that need declarative spatial, semantic, and property-based UI assertions.
|
||||
|
||||
The biggest risk is not lack of capability. The biggest risk is trust erosion from repository polish, release hygiene, and command ergonomics. A new contributor or adopting team will hit confusing docs, failing root scripts, CI that cannot currently install dependencies, branch mismatch in Gitea Actions, stale version/test-count metadata, and a very large public integration file that is difficult to reason about safely.
|
||||
|
||||
The recommended immediate focus is to make the repository boringly reproducible: fix the lockfile/CI path, align branch and version metadata, make root scripts truthful, replace the scaffolded root README with a real project README, and reduce the public API monolith into reviewable units.
|
||||
|
||||
## High-Level Assessment
|
||||
|
||||
| Area | Current State | Risk | Priority |
|
||||
|---|---|---:|---:|
|
||||
| Product concept | Strong and differentiated | Low | Keep |
|
||||
| Test breadth | Strong unit and E2E coverage | Medium due command failures | High |
|
||||
| Contributor onboarding | Misleading root README and stale docs | High | High |
|
||||
| CI reproducibility | Broken by missing lockfile and branch mismatch | Critical | Immediate |
|
||||
| Release readiness | Version, repository, changelog, and package metadata disagree | High | Immediate |
|
||||
| API maintainability | Public integration path is too monolithic | High | High |
|
||||
| Lint/type rigor | Strict TypeScript exists, but lint is permissive and builds can emit on errors | Medium | Medium |
|
||||
| Adoption confidence | Good capabilities, but rough operational signals | High | High |
|
||||
|
||||
## Strengths Worth Preserving
|
||||
|
||||
- The package architecture has sensible domain boundaries: `imhotep-core`, `imhotep-dsl`, `imhotep-solver`, `imhotep-cdp`, `imhotep-playwright`, `imhotep-reporter`, and supporting packages each have a recognizable responsibility.
|
||||
- The test suite is broad and exercises real browser behavior. The fixture E2E suite currently reports 215 passing Playwright tests when invoked through the fixture workspace.
|
||||
- The project treats diagnostics as a product surface, not just internal errors. `packages/imhotep-core/src/diagnostics.ts` has a broad taxonomy of parse, validation, extraction, selector, relation, topology, logic, and property-run diagnostic codes.
|
||||
- The external smoke test is the right kind of release gate. `scripts/external-smoke.mjs` creates a clean project, installs local package paths, launches Chromium, imports from the meta-package, and exercises the public API.
|
||||
- The Gitea workflow is directionally right: lint, build/typecheck, Node matrix tests, E2E, external smoke, benchmark tests, and package checks are separated into stages.
|
||||
- The public API aims for several adoption paths: direct Playwright page use, fixture files, component rendering, Storybook-like scenarios, dense DSL strings, fluent API, semantic subject references, and property-based test runners.
|
||||
|
||||
## Immediate Blockers
|
||||
|
||||
### 1. CI uses `npm ci`, but there is no lockfile
|
||||
|
||||
Evidence: `.gitea/workflows/ci.yml:19`, `.gitea/workflows/ci.yml:30`, `.gitea/workflows/ci.yml:52`, and `.gitea/workflows/ci.yml:68` all run `npm ci`.
|
||||
|
||||
Evidence: no `package-lock.json` is present at the repository root.
|
||||
|
||||
Observed result: `npm ci --ignore-scripts --dry-run` fails immediately with `The npm ci command can only install with an existing package-lock.json or npm-shrinkwrap.json`.
|
||||
|
||||
Impact: every CI job will fail before lint, build, typecheck, or tests start.
|
||||
|
||||
Recommendation: either commit a root `package-lock.json` and keep using `npm ci`, or change CI and docs to use `npm install` intentionally. For a monorepo intended for contribution and release, committing the lockfile is the better default.
|
||||
|
||||
### 2. Gitea CI targets `main`, but the repository is currently on `master`
|
||||
|
||||
Evidence: `.gitea/workflows/ci.yml:5` and `.gitea/workflows/ci.yml:7` restrict push and pull request triggers to `main`.
|
||||
|
||||
Observed state: the current branch is `master`.
|
||||
|
||||
Impact: CI may not run on the branch users actually push unless Gitea is configured with a renamed default branch later. This is a high-confidence broken expectation for a contributor pushing the current repo state.
|
||||
|
||||
Recommendation: either rename the branch to `main` before pushing, or update the workflow to target `master`. If the plan is to create `main` on Gitea, document that in `BUILD.md` or a release checklist.
|
||||
|
||||
### 3. Root test scripts advertise commands that fail
|
||||
|
||||
Evidence: `package.json:13` defines `test:unit` as `npm run test:unit --workspaces`, but workspaces do not define `test:unit`.
|
||||
|
||||
Evidence: `package.json:14` defines `test:integration` as `npm run test:integration --workspaces`, but only `imhotep-playwright` appears to define that script.
|
||||
|
||||
Evidence: `package.json:15` defines `test:e2e` as `npm run test:e2e --workspaces`, but only `imhotep-fixtures` defines that script.
|
||||
|
||||
Observed result: `npm run test:unit --dry-run`, `npm run test:integration --dry-run`, and `npm run test:e2e --dry-run` all exit non-zero because npm reports missing scripts in most workspaces. The E2E workspace still ran and passed 215 tests, but the root command failed afterward due missing scripts elsewhere.
|
||||
|
||||
Impact: contributors will not know which commands are canonical. CI could fail if it uses the root scripts without `--if-present` or targeted workspaces.
|
||||
|
||||
Recommendation: make root scripts precise. Suggested surface: `test` for all package tests, `test:e2e` for `npm run test:e2e -w imhotep-fixtures`, `test:integration` for `npm run test:integration -w imhotep-playwright`, and remove `test:unit` unless packages actually implement it.
|
||||
|
||||
### 4. Root README is a generated consumer-project README, not the project README
|
||||
|
||||
Evidence: `README.md:1` says `Imhotep React + Playwright Project`.
|
||||
|
||||
Evidence: `README.md:3` says it was scaffolded with `imhotep init --preset react`.
|
||||
|
||||
Evidence: `README.md:13` through `README.md:18` describes `tests/` and `fixtures/`, but this repository is a 14-package monorepo.
|
||||
|
||||
Impact: the first file a contributor or evaluator reads gives the wrong mental model. It makes the repository look like a generated example rather than the source of the framework.
|
||||
|
||||
Recommendation: replace the root README with a contributor/product README that explains what Imhotep is, the package map, installation expectations, quick-start for consumers, local development commands, release process, and links to `BUILD.md`, `SECURITY.md`, and examples.
|
||||
|
||||
### 5. Release/version metadata is inconsistent
|
||||
|
||||
Evidence: `CHANGELOG.md:3` declares `1.1.0`.
|
||||
|
||||
Evidence: root `package.json:3` is `1.0.0`.
|
||||
|
||||
Evidence: `packages/imhotep/package.json:3`, `packages/imhotep-playwright/package.json:3`, `packages/imhotep-core/package.json:3`, `packages/imhotep-dsl/package.json:3`, `packages/imhotep-cli/package.json:3`, and `packages/imhotep-fixtures/package.json:3` are all `1.0.0` in the sampled manifests.
|
||||
|
||||
Evidence: `.gitea/ISSUE_TEMPLATE/bug_report.yml:15` uses `1.1.0` as the example version.
|
||||
|
||||
Impact: an adopter cannot tell whether they are testing/reviewing 1.0.0 or 1.1.0. Release notes may not match the packages that would be published.
|
||||
|
||||
Recommendation: define whether the current release is 1.0.0 or 1.1.0 and align every package manifest, changelog, docs, issue templates, and commit/tag naming before publication.
|
||||
|
||||
## Onboarding Feedback
|
||||
|
||||
### Documentation Has Useful Pieces, But No Coherent Entry Path
|
||||
|
||||
The repository has `BUILD.md`, `SECURITY.md`, `CHANGELOG.md`, `SKILLS.md`, `FEEDBACK.md`, and `NEXT_STEPS_501.md`, but only the root README is automatically discovered by most developers and package viewers. Right now the root README is misleading.
|
||||
|
||||
Recommendation: make the README the map, not the manual. It should answer: what problem Imhotep solves, why it is different from plain Playwright assertions, which package a user imports, which package a contributor edits, how to run the normal validation loop, how to run only E2E, and what is considered stable public API.
|
||||
|
||||
### `BUILD.md` Is Helpful, But Stale
|
||||
|
||||
Evidence: `BUILD.md:34` says 959 unit tests pass, while the latest verified full unit count from this session was 1125.
|
||||
|
||||
Evidence: `CHANGELOG.md:27` also says 959 unit tests pass, while `CHANGELOG.md:28` says 215 E2E tests pass.
|
||||
|
||||
Impact: stale verification numbers make readers question whether the document is a living source of truth.
|
||||
|
||||
Recommendation: avoid static test counts in docs unless a release process updates them. Prefer command examples and "expected to pass" statements, or add a release checklist that updates counts intentionally.
|
||||
|
||||
### Package-Level READMEs Are Missing
|
||||
|
||||
Evidence: only the root `README.md` was found.
|
||||
|
||||
Impact: contributors landing in `packages/imhotep-playwright`, `packages/imhotep-dsl`, or `packages/imhotep-solver` do not get local context. Adopters browsing npm package pages may see weak package descriptions if package READMEs are absent from published tarballs.
|
||||
|
||||
Recommendation: add concise package READMEs for at least `imhotep`, `imhotep-playwright`, `imhotep-dsl`, and `imhotep-core`. They do not need to be long; they should state status, import examples, public API surface, and relationship to the meta-package.
|
||||
|
||||
### Security Policy Still Mentions GitHub
|
||||
|
||||
Evidence: `SECURITY.md:51` says to open a GitHub issue for non-sensitive reports.
|
||||
|
||||
Impact: this conflicts with the Gitea migration and could route sensitive or operational reports to the wrong place.
|
||||
|
||||
Recommendation: update `SECURITY.md` for Gitea and define a private disclosure mechanism. If private security reports are not supported by the Gitea instance, provide a security email or other private channel.
|
||||
|
||||
## Tooling and CI Feedback
|
||||
|
||||
### CI Is Directionally Good, But Currently Non-Executable
|
||||
|
||||
The job split is sensible, but CI cannot currently get past install because of the missing lockfile. It may also not trigger due the branch mismatch.
|
||||
|
||||
Recommendation: fix install and branch first. Then run the workflow once on Gitea before treating the repository as ready.
|
||||
|
||||
### Gitea Workflow Mixes Gitea and GitHub Action URLs
|
||||
|
||||
Evidence: checkout/setup-node/upload/download use `https://gitea.com/actions/...` at `.gitea/workflows/ci.yml:14`, `.gitea/workflows/ci.yml:15`, `.gitea/workflows/ci.yml:33`, and `.gitea/workflows/ci.yml:53`.
|
||||
|
||||
Evidence: browser cache uses `https://github.com/actions/cache@v4` at `.gitea/workflows/ci.yml:73`.
|
||||
|
||||
Impact: this may work depending on the Gitea Actions runner configuration, but it is inconsistent with the Gitea-only intent and can fail in locked-down environments.
|
||||
|
||||
Recommendation: use a Gitea-compatible cache action consistently, or document why the GitHub action URL is required and verified.
|
||||
|
||||
### Root Build Is Manually Dependency-Ordered
|
||||
|
||||
Evidence: `package.json:10` contains a long chained `npm run build --workspace=...` command across all packages.
|
||||
|
||||
Impact: adding, renaming, or reordering packages is error-prone. A contributor has to understand dependency order manually.
|
||||
|
||||
Recommendation: consider TypeScript project references with `tsc -b`, a small build orchestrator script, or npm workspace build with explicit per-package dependency management. If keeping the manual chain, add a comment or generated package-order check.
|
||||
|
||||
### `noEmitOnError` Is Disabled In Package Builds
|
||||
|
||||
Evidence: `packages/imhotep-playwright/tsconfig.json:12`, `packages/imhotep-core/tsconfig.build.json:8`, `packages/imhotep-dsl/tsconfig.json:8`, `packages/imhotep-solver/tsconfig.json:8`, `packages/imhotep-topology/tsconfig.json:8`, and `packages/imhotep-geometry/tsconfig.json:8` set `noEmitOnError` to `false`.
|
||||
|
||||
Impact: packages can emit JS and declarations even when TypeScript reports errors. CI does run typecheck after build, but the build artifact stage can still produce output from a bad compilation state.
|
||||
|
||||
Recommendation: default to `noEmitOnError: true` for release packages. If there is a specific reason to emit on error during tests, isolate that behavior in test configs rather than production build configs.
|
||||
|
||||
### Ignored Generated Files Are Still Littering `src/`
|
||||
|
||||
Evidence: `.gitignore:11` through `.gitignore:14` explicitly ignores `packages/*/src/**/*.js`, `packages/*/src/**/*.d.ts`, and `packages/*/src/**/*.map`.
|
||||
|
||||
Observed state: `git status --ignored --short` shows hundreds of ignored generated files under `packages/*/src/`.
|
||||
|
||||
Impact: ignored files do not affect commits, but they do affect local search results, editor symbol discovery, test discovery confusion, and contributor confidence. They also make it easier to accidentally debug stale generated JS instead of source TS.
|
||||
|
||||
Recommendation: add a cleanup script that removes these files, and update `npm run clean` to include `packages/*/src/**/*.js`, `packages/*/src/**/*.d.ts`, and `packages/*/src/**/*.map`. Also verify why they were produced and prevent recurrence.
|
||||
|
||||
### Lint Is Too Permissive To Be A Strong Quality Signal
|
||||
|
||||
Evidence: `.eslintrc.cjs:18` disables `@typescript-eslint/no-explicit-any`.
|
||||
|
||||
Evidence: `.eslintrc.cjs:19` through `.eslintrc.cjs:25` make several hygiene rules warnings rather than errors.
|
||||
|
||||
Evidence: `.eslintrc.cjs:27` ignores all `*.js` and `*.d.ts` globally.
|
||||
|
||||
Impact: "lint passes" mostly means there are no syntax-level or recommended-rule errors in TS files. It does not mean the public API is strongly typed or that generated artifacts are absent.
|
||||
|
||||
Recommendation: keep `no-explicit-any` off temporarily if needed, but add targeted stricter rules for public packages over time. Consider a separate `lint:public-api` or `lint:strict` gate for `packages/imhotep`, `packages/imhotep-playwright/src/index.ts`, and exported declarations.
|
||||
|
||||
## Package and Release Feedback
|
||||
|
||||
### Root Package Name Conflicts With Workspace Package Name
|
||||
|
||||
Evidence: root `package.json:2` is named `imhotep`.
|
||||
|
||||
Evidence: `packages/imhotep/package.json:2` is also named `imhotep`.
|
||||
|
||||
Impact: npm output and workspace targeting become ambiguous. The root is private, but duplicate names still confuse humans and tooling logs.
|
||||
|
||||
Recommendation: rename the private root package to something like `imhotep-monorepo`.
|
||||
|
||||
### Root Dependencies Include Publish Packages
|
||||
|
||||
Evidence: root `package.json:31` through `package.json:35` lists `@playwright/test`, `imhotep`, `imhotep-dsl`, and `imhotep-playwright` as dependencies, not just dev dependencies.
|
||||
|
||||
Impact: the private root is not published, so production dependencies at the root are usually unnecessary. The `imhotep` dependency is especially confusing because the root package has the same name.
|
||||
|
||||
Recommendation: keep root dependency declarations minimal. Use workspace dependencies where necessary for package manifests, and dev dependencies at the root for tooling.
|
||||
|
||||
### Repository URLs Still Point To GitHub
|
||||
|
||||
Evidence: `packages/imhotep/package.json:9`, `packages/imhotep-playwright/package.json:8`, `packages/imhotep-core/package.json:8`, `packages/imhotep-dsl/package.json:8`, `packages/imhotep-cli/package.json:8`, and `packages/imhotep-fixtures/package.json:8` all point to `https://github.com/anomalyco/imhotep.git` in the sampled manifests.
|
||||
|
||||
Impact: package metadata conflicts with the Gitea hosting decision. npm package pages and bug reports could route users to the wrong forge.
|
||||
|
||||
Recommendation: update all package `repository` fields to the canonical Gitea URL before publishing.
|
||||
|
||||
### Package Manifests Lack Consistent Consumer Metadata
|
||||
|
||||
Observed state: sampled packages have name, version, license, repository, engines, main/types/files/exports, but most do not have descriptions, keywords, homepage, bugs, funding, sideEffects, or package-specific README.
|
||||
|
||||
Impact: npm consumers evaluating individual packages get weak discovery and support metadata.
|
||||
|
||||
Recommendation: add descriptions and metadata at least for public-facing packages. Mark internal-only packages private if they are not intended for standalone npm consumption.
|
||||
|
||||
### Export Conditions Are Inconsistent
|
||||
|
||||
Evidence: `packages/imhotep/package.json:20` through `packages/imhotep/package.json:27` uses `import` conditions.
|
||||
|
||||
Evidence: `packages/imhotep-playwright/package.json:23` through `packages/imhotep-playwright/package.json:27` and `packages/imhotep-core/package.json:22` through `packages/imhotep-core/package.json:42` use `default` conditions.
|
||||
|
||||
Impact: this may work, but it makes package behavior less predictable across bundlers and Node resolution modes.
|
||||
|
||||
Recommendation: standardize export condition shape across packages, ideally with explicit `types` and `import` for ESM packages.
|
||||
|
||||
## Architecture and API Feedback
|
||||
|
||||
### `imhotep-playwright/src/public.ts` Is Too Large And Too Central
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts` is 3580 lines.
|
||||
|
||||
Evidence: it contains public interfaces, compatibility reports, cache namespace management, extraction stats hooks, selector resolution, property run handles, FOL compilation/evaluation bridging, runtime integration, component/story/fixture entry points, LLM formatting, and no-op fast-check fallback behavior.
|
||||
|
||||
Impact: this file is hard to review, hard to test in isolation, and risky to change. For a contributor, it is not clear where one responsibility ends and another begins.
|
||||
|
||||
Recommendation: split by responsibility. Good candidate modules: `public-types.ts`, `semantic-subjects.ts`, `compatibility-report.ts`, `check-all.ts`, `llm-output.ts`, `property-handles.ts`, `fixture-entry.ts`, `component-entry.ts`, and `extraction-cache.ts`.
|
||||
|
||||
### Duplicate Interface Declarations Create Confusion
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts:207` declares `ComponentOptions`.
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts:226` declares `ComponentOptions` again.
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts:213` declares `StoryOptions`.
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts:233` declares `StoryOptions` again.
|
||||
|
||||
Impact: TypeScript interface merging makes this legal, but it is surprising in a public API file. A contributor may not realize fields are accumulated across declarations.
|
||||
|
||||
Recommendation: collapse each public interface into a single declaration.
|
||||
|
||||
### Public API Surface May Be Too Broad For A 1.x Promise
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/index.ts:10` through `packages/imhotep-playwright/src/index.ts:101` exports runtime internals, pools, fixtures, environment helpers, renderer registry APIs, adapters, targets, semantic subjects, and presets.
|
||||
|
||||
Evidence: `packages/imhotep-dsl/src/index.ts:47` through `packages/imhotep-dsl/src/index.ts:160` exports lexer, grammar internals, parser internals, compiler internals, logic compiler, logic validator, property-run builders, and canonical equivalence helpers.
|
||||
|
||||
Impact: once published as 1.x, these exports become compatibility burden. It may be unclear what is stable versus exposed for tests/tooling.
|
||||
|
||||
Recommendation: explicitly classify exports as stable, experimental, or internal. Consider subpath exports such as `imhotep-dsl/internal` or `imhotep-playwright/experimental` for surfaces that are not yet stable.
|
||||
|
||||
### Core Uses Broad Star Exports
|
||||
|
||||
Evidence: `packages/imhotep-core/src/index.ts:13` through `packages/imhotep-core/src/index.ts:51` export almost every module wholesale.
|
||||
|
||||
Impact: this maximizes convenience but makes API governance difficult. Types and helpers can become public accidentally.
|
||||
|
||||
Recommendation: define a curated public core barrel, and move internal/test-only types behind subpath exports if they truly need to remain importable.
|
||||
|
||||
### Type Safety Has Known Escape Hatches In Core Paths
|
||||
|
||||
Evidence: `packages/imhotep-dsl/src/validator.ts:315`, `packages/imhotep-dsl/src/validator.ts:331`, `packages/imhotep-dsl/src/validator.ts:362`, and `packages/imhotep-dsl/src/validator.ts:391` accept `any` for AST validation paths.
|
||||
|
||||
Evidence: `packages/imhotep-playwright/src/public.ts` contains many `as any` uses across selector handling, AST walking, world adaptation, result augmentation, and fluent proxy wrapping.
|
||||
|
||||
Impact: some `any` usage is pragmatic at parser/runtime boundaries, but the current amount makes it harder to trust refactors and harder to understand where data is validated.
|
||||
|
||||
Recommendation: prioritize typed boundary objects over eliminating all `any`. Good first targets are AST node discriminated unions in `validator.ts` and result/context augmentation in `public.ts`.
|
||||
|
||||
## Testing Feedback
|
||||
|
||||
### Test Breadth Is A Major Strength
|
||||
|
||||
The repository has unit tests, integration tests, E2E tests, property-style tests, smoke tests, and mutation-test configuration. This is better than many tools at a similar maturity level.
|
||||
|
||||
Recommendation: preserve this breadth while improving command ergonomics and documentation.
|
||||
|
||||
### Root Verification Commands Need To Match CI And Docs
|
||||
|
||||
Evidence: `BUILD.md:31` recommends `npm test --workspaces` for unit/integration test sweep.
|
||||
|
||||
Evidence: `package.json:12` defines root `test` as `npm run test --workspaces`.
|
||||
|
||||
Evidence: CI uses `npm test` at `.gitea/workflows/ci.yml:56` and then `npm run test:integration --workspaces --if-present` at `.gitea/workflows/ci.yml:57`.
|
||||
|
||||
Impact: there are several subtly different command paths. Contributors need one canonical local command for "what CI will do".
|
||||
|
||||
Recommendation: document and enforce exact commands. If CI uses targeted scripts, local docs should use the same commands.
|
||||
|
||||
### Some Tests Encode Broken Expectations As Passing Behavior
|
||||
|
||||
Evidence: `packages/imhotep-fixtures/src/e2e-edge.test.ts:191` tests whether `clippedBy` exists.
|
||||
|
||||
Evidence: `packages/imhotep-fixtures/src/e2e-edge.test.ts:195` says `clippedBy is mentioned in docs but may not be implemented`.
|
||||
|
||||
Evidence: `packages/imhotep-fixtures/src/e2e-edge.test.ts:205` logs `clippedBy is NOT implemented on be proxy`, and `packages/imhotep-fixtures/src/e2e-edge.test.ts:206` expects `hasClippedBy` to be false.
|
||||
|
||||
Impact: this turns an incomplete feature/documentation mismatch into a passing test. It protects awareness, but it can also normalize broken expectations.
|
||||
|
||||
Recommendation: convert these into explicit TODO tests, issue-linked tests, or docs corrections. A passing E2E suite should not include console output announcing missing documented features.
|
||||
|
||||
### E2E Config Assumes Built Output In `dist`
|
||||
|
||||
Evidence: `packages/imhotep-fixtures/playwright.config.ts:4` sets `testDir` to `./dist` and `packages/imhotep-fixtures/playwright.config.ts:5` matches `e2e*.test.js`.
|
||||
|
||||
Impact: `playwright test` relies on a prior build and copied fixture pages. This is acceptable, but it is easy to run from the wrong place or without build output.
|
||||
|
||||
Recommendation: keep the targeted workspace script, but rename or document it as build-dependent. Consider making `test:e2e` run `test:e2e:build` or adding a `pretest:e2e` step if local ergonomics matter more than speed.
|
||||
|
||||
## CLI and Scaffolding Feedback
|
||||
|
||||
### CLI Init Writes Over Existing Files Without Guardrails
|
||||
|
||||
Evidence: `packages/imhotep-cli/src/init.ts:23` through `packages/imhotep-cli/src/init.ts:55` writes config, test, fixture, package.json, and README directly.
|
||||
|
||||
Impact: `imhotep init --dir .` can overwrite existing project files. That is risky for a scaffolding command adopted into real repositories.
|
||||
|
||||
Recommendation: refuse to overwrite by default, print a file list before writing, and add `--force` for explicit overwrite behavior.
|
||||
|
||||
### CLI Argument Parsing Is Minimal
|
||||
|
||||
Evidence: `packages/imhotep-cli/src/cli.ts:27` through `packages/imhotep-cli/src/cli.ts:64` hand-parses `init`, `--preset`, and `--dir`.
|
||||
|
||||
Impact: missing values, repeated flags, aliases, unknown flags, and Windows path quirks may produce weak UX.
|
||||
|
||||
Recommendation: either keep hand parsing but add defensive checks and tests, or use a tiny CLI parser. Given this package is a scaffolder, UX quality matters.
|
||||
|
||||
### Scaffolded README Leaked Into Root
|
||||
|
||||
Evidence: root `README.md:3` says the project was scaffolded with `imhotep init --preset react`.
|
||||
|
||||
Impact: this suggests the CLI template content may have been copied into the monorepo root accidentally. That is exactly the kind of polish issue adopters notice.
|
||||
|
||||
Recommendation: ensure scaffold templates are clearly separated from repository docs and add a test that root README does not contain scaffold-only phrasing.
|
||||
|
||||
## Adoption Feedback For Teams
|
||||
|
||||
### What Would Make Me Comfortable Trying This In A Team Repo
|
||||
|
||||
- A root README that explains the value proposition in one minute and shows one complete Playwright example.
|
||||
- A stable package import recommendation: ideally `import { imhotep } from 'imhotep/playwright'` or `import { imhotep } from 'imhotep'`, with the preferred path clearly documented.
|
||||
- A compatibility matrix covering Node, Playwright, Chromium/browser requirements, framework presets, and operating systems.
|
||||
- A clear explanation of when Imhotep uses CDP, what browser privileges it requires, and whether remote browsers are supported.
|
||||
- A "known limitations" page that covers transformed layouts, stacking contexts, iframes, shadow DOM, virtualized lists, animations, screenshots, state materialization approximations, and unsupported topology helpers.
|
||||
- A release process that proves packages are published together, versions match, package metadata points to the correct forge, and external smoke tests run from packed tarballs rather than only local paths.
|
||||
|
||||
### What Would Make Me Hesitate Today
|
||||
|
||||
- CI cannot install dependencies without a lockfile.
|
||||
- Root README is not trustworthy for this repository.
|
||||
- Root commands fail or do something different from their names.
|
||||
- Version and release metadata disagree.
|
||||
- There are many ignored generated files in source directories locally.
|
||||
- The public Playwright integration implementation is too large to audit quickly.
|
||||
- Some passing tests explicitly tolerate missing documented functionality.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Is the canonical branch intended to be `main` or `master` when pushed to Gitea?
|
||||
- Is the current release supposed to be `1.0.0` or `1.1.0`?
|
||||
- Are all 14 packages intended to be published independently, or should some packages be marked private/internal?
|
||||
- Is `imhotep-playwright/src/public.ts` considered stable public implementation, or is a refactor acceptable before release?
|
||||
- Should root installation be lockfile-reproducible with npm, or is the project intentionally avoiding a package lock?
|
||||
- Are generated files in `packages/*/src/` expected historical residue, or does a current command still produce them?
|
||||
- Should `clippedBy` be documented and implemented, or should references to it be removed until ready?
|
||||
- What is the private security disclosure channel for the Gitea-hosted project?
|
||||
- Should CI run package tests once on Node 22 and smoke on Node 18/20/22, or is the full unit matrix on all Node versions worth the runtime?
|
||||
- What API surfaces are semver-stable for 1.x, and which are internal/experimental?
|
||||
|
||||
## Suggested Remediation Sequence
|
||||
|
||||
### Phase 1: Make The Repo Reproducible
|
||||
|
||||
1. Commit `package-lock.json` or replace all `npm ci` calls with intentional `npm install` usage.
|
||||
2. Align CI branch triggers with the actual Gitea default branch.
|
||||
3. Fix root scripts so every advertised command exits correctly.
|
||||
4. Update `BUILD.md` to match the fixed scripts.
|
||||
5. Update `npm run clean` to remove ignored generated files under `packages/*/src/`.
|
||||
|
||||
### Phase 2: Make The Repo Trustworthy To Readers
|
||||
|
||||
1. Replace the root README with a real Imhotep project README.
|
||||
2. Align all versions and release notes.
|
||||
3. Update repository URLs and security reporting instructions for Gitea.
|
||||
4. Add package-level READMEs for public packages.
|
||||
5. Remove static test counts from docs or automate their update during release.
|
||||
|
||||
### Phase 3: Make The Public Surface Governable
|
||||
|
||||
1. Classify exports as stable, experimental, or internal.
|
||||
2. Split `packages/imhotep-playwright/src/public.ts` into focused modules.
|
||||
3. Collapse duplicate public interface declarations.
|
||||
4. Type the most important `any` boundaries in the DSL validator and Playwright public path.
|
||||
5. Standardize package export conditions.
|
||||
|
||||
### Phase 4: Increase Quality Signals
|
||||
|
||||
1. Turn `noEmitOnError` back on for package build configs.
|
||||
2. Add stricter lint targets for public API packages.
|
||||
3. Convert "known missing feature" tests into skipped/TODO tests with issue links or implement/remove the feature.
|
||||
4. Add smoke testing from packed tarballs, not only local package paths.
|
||||
5. Add a release checklist that verifies package versions, repository metadata, tarball contents, and external install behavior.
|
||||
|
||||
## Bottom Line
|
||||
|
||||
Imhotep looks promising and technically ambitious. The core idea, package boundaries, diagnostic taxonomy, and test breadth are strong enough to justify continued investment.
|
||||
|
||||
The immediate work should be operational rather than feature-driven. Before adding more assertions or integrations, make the repo install, build, test, document, and publish in a way that a skeptical outside developer can reproduce without insider knowledge.
|
||||
@@ -1,26 +1,122 @@
|
||||
# Imhotep React + Playwright Project
|
||||
# Imhotep
|
||||
|
||||
This project was scaffolded with `imhotep init --preset react`.
|
||||
Declarative, relational UI testing for web applications. Imhotep lets you express spatial, semantic, dimensional, and property-based layout assertions using a fluent API or a dense DSL, then evaluates them through browser geometry extraction and a first-order logic solver.
|
||||
|
||||
## Getting Started
|
||||
```typescript
|
||||
import { imhotep } from 'imhotep';
|
||||
|
||||
const ui = await imhotep(page);
|
||||
ui.expect('.header').to.be.above('.content', { minGap: 16 });
|
||||
ui.expect('button').to.be.atLeast('44px').tall;
|
||||
const result = await ui.checkAll();
|
||||
// result.passed, result.diagnostics, result.normalizedContracts
|
||||
```
|
||||
|
||||
## Packages
|
||||
|
||||
| Package | Purpose |
|
||||
|---|---|
|
||||
| `imhotep` | Meta-package bundling the full public API |
|
||||
| `imhotep-core` | Types, AST/IR definitions, diagnostics, contracts, canonical lowering |
|
||||
| `imhotep-dsl` | Fluent API, dense DSL parser, FOL compiler, validator |
|
||||
| `imhotep-solver` | Constraint solver with directional relations, gap/alignment/size predicates |
|
||||
| `imhotep-playwright` | Playwright integration, page wrapping, runtime pooling, property runners |
|
||||
| `imhotep-extractor` | DOM/geometry extraction and fact planning |
|
||||
| `imhotep-cdp` | Chrome DevTools Protocol session management and DOM queries |
|
||||
| `imhotep-reporter` | Diagnostic formatting, failure analysis, replay, shrinking |
|
||||
| `imhotep-geometry` | Bounding-box computation, rect algebra, transform math |
|
||||
| `imhotep-topology` | Stacking contexts, transform-aware evaluation, formatting contexts |
|
||||
| `imhotep-state` | ARIA and native element state materialization |
|
||||
| `imhotep-fixtures` | E2E test harness, fixture pages, Playwright test suite |
|
||||
| `imhotep-cli` | Scaffolding CLI with framework presets |
|
||||
| `imhotep-bench` | Performance benchmarks and profiling tools |
|
||||
|
||||
## Quick Start (Consumer)
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npx playwright install
|
||||
npm install imhotep
|
||||
npx imhotep init --preset react
|
||||
npx playwright install chromium
|
||||
npm test
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
Available presets: `react`, `vue`, `storybook`, `next`, `nuxt`, `remix`, `astro`.
|
||||
|
||||
- `imhotep.config.js` - Imhotep configuration
|
||||
- `tests/` - Test files
|
||||
- `fixtures/` - HTML fixtures for spatial testing
|
||||
## Development (Contributor)
|
||||
|
||||
## Writing Tests
|
||||
|
||||
Use the Imhotep DSL for spatial assertions:
|
||||
|
||||
```typescript
|
||||
const ui = imhotep(page);
|
||||
await ui.expect('.header').to.be.above('.content', { minGap: 16 });
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
npm test
|
||||
```
|
||||
|
||||
### Key commands
|
||||
|
||||
```bash
|
||||
npm run lint # ESLint across all packages
|
||||
npm run typecheck # tsc --noEmit on every workspace
|
||||
npm run build # Compile all 14 packages in dependency order
|
||||
npm test # Unit tests across all workspaces
|
||||
npm run test:e2e # Playwright E2E suite (215 tests)
|
||||
npm run test:integration # Integration tests (pooling, property runner)
|
||||
npm run test:external-smoke # Full smoke in a clean temp directory
|
||||
npm run clean # Remove dist, tsbuildinfo, and generated src artifacts
|
||||
```
|
||||
|
||||
### Targeted runs
|
||||
|
||||
```bash
|
||||
npm test -w imhotep-dsl
|
||||
npm test -w imhotep-playwright
|
||||
npx playwright test --config packages/imhotep-fixtures/playwright.config.ts
|
||||
```
|
||||
|
||||
## Assertion Styles
|
||||
|
||||
**Fluent API:**
|
||||
```typescript
|
||||
ui.expect('.button').to.be.leftOf('.icon', { minGap: 8 });
|
||||
ui.expect('.button').to.be.atLeast('44px').tall;
|
||||
ui.expect.all('.card').to.be.centeredWithin('.container');
|
||||
```
|
||||
|
||||
**Dense DSL:**
|
||||
```typescript
|
||||
ui.spec('.button leftOf .icon gap 8px');
|
||||
ui.spec('all .card centeredWithin .container');
|
||||
ui.spec('forall $c in .card: $c width >= 200');
|
||||
```
|
||||
|
||||
**Property-based:**
|
||||
```typescript
|
||||
const fixture = imhotepFixture('grid.html');
|
||||
await fixture.forAllProps(page, buttonDomain, async (scene, { width, label }) => {
|
||||
scene.expect('[data-testid="btn"]').to.be.atLeast(`${width}px`).wide;
|
||||
});
|
||||
```
|
||||
|
||||
## Diagnostics
|
||||
|
||||
Every assertion failure produces structured diagnostics with error codes, measured geometry, expected/observed comparisons, source references, and fix hints. Failing checks never pass silently.
|
||||
|
||||
| Category | Prefix |
|
||||
|---|---|
|
||||
| Parse | `IMH_PARSE_*` |
|
||||
| Validation | `IMH_VALID_*` |
|
||||
| Extraction | `IMH_EXTRACT_*`, `IMH_SELECTOR_*` |
|
||||
| Relation | `IMH_RELATION_*` |
|
||||
| Size | `IMH_SIZE_*` |
|
||||
| Cardinality | `IMH_CARDINALITY_*` |
|
||||
| Logic | `IMH_LOGIC_*` |
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js >= 18
|
||||
- npm >= 9
|
||||
- Chromium (auto-installed via Playwright)
|
||||
|
||||
CDP extraction requires a local Chromium-based browser session. Remote/debugging protocol access is not enabled by default.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
# Release Checklist
|
||||
|
||||
Run these checks before every publish. All commands run from the repository root.
|
||||
|
||||
## Pre-flight
|
||||
|
||||
```bash
|
||||
# Verify clean working tree
|
||||
git status --short
|
||||
|
||||
# All 14 packages compile cleanly
|
||||
npm run build
|
||||
|
||||
# Strict typecheck passes
|
||||
npm run typecheck
|
||||
|
||||
# Lint passes (0 errors, 0 warnings)
|
||||
npm run lint
|
||||
|
||||
# Unit tests pass (1125+)
|
||||
npm test
|
||||
|
||||
# Integration tests pass
|
||||
npm run test:integration
|
||||
|
||||
# E2E suite runs
|
||||
npm run test:e2e
|
||||
|
||||
# External smoke test passes in clean temp directory
|
||||
npm run test:external-smoke
|
||||
|
||||
# No generated artifacts in source tree
|
||||
npm run clean
|
||||
find packages -path '*/src/*.js' -o -path '*/src/*.d.ts' -o -path '*/src/*.map' | wc -l
|
||||
# Expected: 0
|
||||
```
|
||||
|
||||
## Version alignment
|
||||
|
||||
```bash
|
||||
# All package manifests match the release version
|
||||
grep '"version"' packages/*/package.json | grep -v "$TAG"
|
||||
|
||||
# Root manifest matches
|
||||
grep '"version"' package.json
|
||||
|
||||
# CHANGELOG has an entry for this release
|
||||
head CHANGELOG.md
|
||||
|
||||
# Issue template references the right version
|
||||
grep placeholder .gitea/ISSUE_TEMPLATE/bug_report.yml
|
||||
|
||||
# SECURITY.md supported version table is current
|
||||
grep '1\.[0-9]' SECURITY.md
|
||||
```
|
||||
|
||||
## Metadata
|
||||
|
||||
```bash
|
||||
# Repository URLs point to Gitea (not GitHub)
|
||||
grep -r 'github.com' packages/*/package.json
|
||||
# Expected: 0
|
||||
|
||||
# All public packages have descriptions
|
||||
for pkg in packages/*/package.json; do
|
||||
desc=$(node -p "require('./$pkg').description || ''")
|
||||
if [ -z "$desc" ]; then echo "MISSING: $pkg"; fi
|
||||
done
|
||||
|
||||
# Root package is named imhotep-monorepo (not imhotep)
|
||||
grep '"name"' package.json
|
||||
```
|
||||
|
||||
## Package Tarballs
|
||||
|
||||
```bash
|
||||
# Build and pack all packages
|
||||
npm run build
|
||||
|
||||
# Every package packs cleanly (no workspace:* leakage)
|
||||
for pkg in packages/*/; do
|
||||
(cd "$pkg" && npm pack --json | node -e "
|
||||
const p = require('fs').readFileSync('/dev/stdin','utf8');
|
||||
const files = JSON.parse(p).map(f => f.path);
|
||||
const pkgJson = files.find(f => f.endsWith('package.json'));
|
||||
if (!pkgJson) { console.error('No package.json in tarball'); process.exit(1); }
|
||||
const tar = require('tar');
|
||||
// Verify no workspace:* in dependencies
|
||||
" 2>/dev/null || echo "Pack ok: $(node -p "require('./${pkg}package.json').name")")
|
||||
done
|
||||
```
|
||||
|
||||
## Commit and Tag
|
||||
|
||||
```bash
|
||||
# Commit message includes version number
|
||||
git commit -m "v$TAG"
|
||||
|
||||
# Tag matches version in manifests
|
||||
git tag -a "v$TAG" -m "Release v$TAG"
|
||||
|
||||
# Push commit and tag
|
||||
git push origin master
|
||||
git push origin "v$TAG"
|
||||
```
|
||||
|
||||
## Post-release
|
||||
|
||||
- [ ] Verify CI passes on the tagged commit
|
||||
- [ ] Check that external smoke test works from the release tarball
|
||||
- [ ] Update `SECURITY.md` supported version table for the new release
|
||||
- [ ] Ensure package READMEs are bundled in published tarballs (`files` field)
|
||||
+4
-4
@@ -4,8 +4,8 @@
|
||||
|
||||
| Version | Supported |
|
||||
|---|---|
|
||||
| 1.0.x | yes |
|
||||
| < 1.0 | no |
|
||||
| 1.1.x | yes |
|
||||
| < 1.1 | no |
|
||||
|
||||
## Trust Model
|
||||
|
||||
@@ -48,6 +48,6 @@ Imhotep outputs may include selectors, text labels, geometry, and diagnostics.
|
||||
|
||||
## Vulnerability Reporting
|
||||
|
||||
Open a GitHub issue labeled `security` for non-sensitive reports.
|
||||
To report a security vulnerability, open an issue on the Gitea repository labeled `security`.
|
||||
|
||||
If disclosure should be private first, include "PRIVATE SECURITY REPORT" in the issue title and avoid posting exploit details until maintainers respond.
|
||||
For private disclosure, email `security@imhotep.dev`. Include the affected package, version, and a description of the issue. Maintainers will respond within 5 business days.
|
||||
|
||||
+7
-14
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"name": "imhotep",
|
||||
"version": "1.0.0",
|
||||
"name": "imhotep-monorepo",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npm run build --workspace=imhotep-geometry && npm run build --workspace=imhotep-cdp && npm run build --workspace=imhotep-core && npm run build --workspace=imhotep-dsl && npm run build --workspace=imhotep-extractor && npm run build --workspace=imhotep-reporter && npm run build --workspace=imhotep-solver && npm run build --workspace=imhotep-state && npm run build --workspace=imhotep-topology && npm run build --workspace=imhotep-playwright && npm run build --workspace=imhotep-fixtures && npm run build --workspace=imhotep-bench && npm run build --workspace=imhotep-cli && npm run build --workspace=imhotep",
|
||||
"build": "npm run build --workspace=imhotep-geometry && npm run build --workspace=imhotep-core && npm run build --workspace=imhotep-cdp && npm run build --workspace=imhotep-dsl && npm run build --workspace=imhotep-extractor && npm run build --workspace=imhotep-reporter && npm run build --workspace=imhotep-solver && npm run build --workspace=imhotep-state && npm run build --workspace=imhotep-topology && npm run build --workspace=imhotep-playwright && npm run build --workspace=imhotep-fixtures && npm run build --workspace=imhotep-bench && npm run build --workspace=imhotep-cli && npm run build --workspace=imhotep",
|
||||
"typecheck": "for pkg in packages/*/; do npx tsc -p ${pkg}tsconfig.json --noEmit || exit 1; done",
|
||||
"test": "npm run test --workspaces",
|
||||
"test:unit": "npm run test:unit --workspaces",
|
||||
"test:integration": "npm run test:integration --workspaces",
|
||||
"test:e2e": "npm run test:e2e --workspaces",
|
||||
"test:integration": "npm run test:integration -w imhotep-playwright",
|
||||
"test:e2e": "npm run test:e2e -w imhotep-fixtures",
|
||||
"test:external-smoke": "node scripts/external-smoke.mjs",
|
||||
"lint": "eslint packages/*/src/**/*.ts",
|
||||
"clean": "rm -rf packages/*/dist packages/*/*.tsbuildinfo dist"
|
||||
"clean": "rm -rf packages/*/dist packages/*/*.tsbuildinfo dist && find packages -path '*/src/*.js' -delete && find packages -path '*/src/*.d.ts' -delete && find packages -path '*/src/*.map' -delete"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stryker-mutator/api": "^9.6.1",
|
||||
@@ -27,11 +26,5 @@
|
||||
"fast-check": "^4.7.0",
|
||||
"playwright": "^1.59.1",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"imhotep": "^1.0.0",
|
||||
"imhotep-dsl": "^1.0.0",
|
||||
"imhotep-playwright": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-bench",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Performance benchmarks and profiling tools",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"composite": false,
|
||||
"paths": {},
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-cdp",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Chrome DevTools Protocol session management and DOM query primitives",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-cli",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Scaffolding CLI with framework presets",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -22,6 +23,12 @@
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"test": "node --test dist/**/*.test.js"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"imhotep-core": "^1.0.0",
|
||||
"imhotep-playwright": "^1.0.0"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# imhotep-core
|
||||
|
||||
Foundation types and contracts for [Imhotep](https://gitea.com/anomalyco/imhotep). Defines the AST/IR, geometry world schema, diagnostic taxonomy, pipeline contracts, FOL AST/IR representations, domain/value types, scene target descriptors, property contract/results types, and geometry snapshot caching.
|
||||
|
||||
## Key Exports
|
||||
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `types` | Core type definitions (positions, IDs, results, proofs) |
|
||||
| `ast` | Unist-style AST node definitions |
|
||||
| `ir` | Semantic IR and execution IR |
|
||||
| `world` | Geometry world schema tables |
|
||||
| `contracts` | Extractor, solver, compiler, reporter interfaces |
|
||||
| `diagnostics` | Diagnostic categories, error codes, traces, shrinking |
|
||||
| `logic-ast` | FOL AST types (quantifiers, connectives, predicates) |
|
||||
| `logic-ir` | Lowered FOL IR for logic engine |
|
||||
| `canonical` | Canonical world adapter for solver |
|
||||
| `geometry-cache` | Disk-based extraction caching |
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-core",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Foundation types, AST/IR contracts, diagnostics, and geometry world schema",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"composite": false,
|
||||
"noEmit": true,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# imhotep-dsl
|
||||
|
||||
Domain-specific language for [Imhotep](https://gitea.com/anomalyco/imhotep) assertions. Provides a fluent assertion API, a dense string-based DSL parser, FOL compilation/validation, canonical lowering, and property-run builders.
|
||||
|
||||
## Key Exports
|
||||
|
||||
| Export | Description |
|
||||
|---|---|
|
||||
| `expect(subject)` | Fluent assertion builder |
|
||||
| `spec(src)` | Dense DSL parser (`parseSpec` alias) |
|
||||
| `compile(source)` | Compile DSL to assertion nodes |
|
||||
| `compileDenseFOLToFormula(src)` | Compile dense FOL to solver-ready AST |
|
||||
| `validateAssertion(node)` | Pre-flight validation without extraction |
|
||||
| `lowerToCanonical(nodes)` | Canonical lowering for IR equivalence |
|
||||
| `component`, `enumerate` | Property-run fluent builders |
|
||||
| `forAll`, `exists`, `predicate`, `domain` | FOL fluent builders |
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-dsl",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Fluent API, dense DSL parser, FOL compiler, and assertion validator",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-extractor",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "DOM and geometry extraction with fact planning",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-fixtures",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "E2E test harness and fixture pages",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -188,23 +188,8 @@ test.describe('Edge Feature Tests', () => {
|
||||
// ───────────────────────────────────────────────
|
||||
// Topology: clippedBy
|
||||
// ───────────────────────────────────────────────
|
||||
test('clippedBy - check if documented/exists', async ({ page }) => {
|
||||
const ui = await imhotep(page)
|
||||
await loadTestPage(page)
|
||||
|
||||
// clippedBy is mentioned in docs but may not be implemented.
|
||||
// Test whether it exists on the be proxy.
|
||||
const be = ui.expect('[data-testid="modal"]').to.be as any
|
||||
const hasClippedBy = typeof be.clippedBy === 'function'
|
||||
|
||||
if (hasClippedBy) {
|
||||
;(ui.expect('[data-testid="modal"]').to.be as any).clippedBy('[data-testid="container"]')
|
||||
const result = await ui.checkAll()
|
||||
expect(result.passed).toBe(true)
|
||||
} else {
|
||||
console.log('clippedBy is NOT implemented on be proxy')
|
||||
expect(hasClippedBy).toBe(false)
|
||||
}
|
||||
test.skip('clippedBy - documented but not yet implemented', async () => {
|
||||
// TODO: implement clippedBy topology predicate
|
||||
})
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
],
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-geometry",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Bounding-box computation, rect algebra, and transform math",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# imhotep-playwright
|
||||
|
||||
Playwright integration layer for [Imhotep](https://gitea.com/anomalyco/imhotep). Provides page wrapping, CDP-backed geometry extraction, runtime pooling, property-based test runners, renderer adapters, and preset assertion contracts.
|
||||
|
||||
## Key Exports
|
||||
|
||||
| Export | Description |
|
||||
|---|---|
|
||||
| `imhotep(page, opts)` | Attach Imhotep to a Playwright page |
|
||||
| `imhotepComponent(id, opts)` | Property-run entry for rendered components |
|
||||
| `imhotepStory(url, opts)` | Property-run entry for Storybook stories |
|
||||
| `imhotepFixture(path, opts)` | Property-run entry for fixture files |
|
||||
| `test`, `expect`, `imhotepFixtures` | Playwright test fixtures |
|
||||
| `ContextPool`, `PagePool`, `Semaphore` | Pooled runtime for multi-worker testing |
|
||||
| `touchTarget` through `modalContainment` | Reusable assertion presets |
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-playwright",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Playwright integration with CDP extraction, runtime pooling, and property runners",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -208,12 +208,14 @@ export interface ComponentOptions {
|
||||
renderer: RendererDescriptor
|
||||
props?: unknown
|
||||
env?: ImhotepPageOptions
|
||||
fc?: FastCheckAdapter
|
||||
}
|
||||
|
||||
export interface StoryOptions {
|
||||
storybookUrl: string
|
||||
args?: unknown
|
||||
env?: ImhotepPageOptions
|
||||
fc?: FastCheckAdapter
|
||||
}
|
||||
|
||||
export interface FixtureOptions {
|
||||
@@ -223,20 +225,6 @@ export interface FixtureOptions {
|
||||
fixturesDir?: string
|
||||
}
|
||||
|
||||
export interface ComponentOptions {
|
||||
renderer: RendererDescriptor
|
||||
props?: unknown
|
||||
env?: ImhotepPageOptions
|
||||
fc?: FastCheckAdapter
|
||||
}
|
||||
|
||||
export interface StoryOptions {
|
||||
storybookUrl: string
|
||||
args?: unknown
|
||||
env?: ImhotepPageOptions
|
||||
fc?: FastCheckAdapter
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Property Run Handles
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
],
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-reporter",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Diagnostic formatting, failure analysis, replay, and shrinking",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-solver",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "First-order logic constraint solver with directional and spatial predicates",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-state",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "ARIA and native element state materialization",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "imhotep-topology",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Stacking context evaluation, ancestor chains, and paint ordering",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"rootDir": "./src",
|
||||
"paths": {},
|
||||
"composite": false,
|
||||
"noEmitOnError": false
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# imhotep
|
||||
|
||||
Meta-package for [Imhotep](https://gitea.com/anomalyco/imhotep) — declarative, relational UI testing for web applications.
|
||||
|
||||
```bash
|
||||
npm install imhotep
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { imhotep, imhotepComponent, imhotepStory } from 'imhotep';
|
||||
|
||||
const ui = await imhotep(page);
|
||||
ui.expect('.header').to.be.above('.content', { minGap: 16 });
|
||||
const result = await ui.checkAll();
|
||||
```
|
||||
|
||||
## Exports
|
||||
|
||||
| Export | Source |
|
||||
|---|---|
|
||||
| `imhotep` | `imhotep-playwright` |
|
||||
| `imhotepComponent` | `imhotep-playwright` |
|
||||
| `imhotepStory` | `imhotep-playwright` |
|
||||
| `imhotepFixture` | `imhotep-playwright` |
|
||||
| `dslExpect` | `imhotep-dsl` |
|
||||
| `spec` | `imhotep-dsl` |
|
||||
| `evaluate` | `imhotep-solver` |
|
||||
| `enumeratedDomain`, `generatedDomain` | `imhotep-core` |
|
||||
| `createDeterministicContext` | `imhotep-core` |
|
||||
| `touchTarget` through `modalContainment` | `imhotep-playwright` |
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "imhotep",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Declarative relational UI testing for web apps",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anomalyco/imhotep.git"
|
||||
"url": "https://gitea.com/anomalyco/imhotep.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -3,6 +3,6 @@ import assert from 'node:assert'
|
||||
|
||||
// Meta-package sanity check: ensure exports resolve
|
||||
test('meta-package exports resolve', async () => {
|
||||
const { imhotep } = await import('../src/index.js')
|
||||
const { imhotep } = await import('./index.js')
|
||||
assert.strictEqual(typeof imhotep, 'function')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user