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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 117 additions & 9 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The [code map](code-map.md) explains responsibility and execution order.

## Setup

From the repository root:
From the repository root in a POSIX shell:

```sh
npm ci
Expand All @@ -21,6 +21,41 @@ npm run build:cli
npx playwright install chromium
```

For Windows 11 x64, use Node 24 and Python 3.11+ with PowerShell 5.1 or 7.
The following commands select an installed Python executable, then use a
repository virtualenv. If `python` is not on PATH, replace the first assignment
with your interpreter's absolute executable path. For a launcher-only install,
use `$env:PYTHON = py -3.11 -c 'import json, sys; print(json.dumps(sys.executable))' | ConvertFrom-Json`.
The JSON capture preserves Unicode executable paths under legacy console encodings.

<!-- docs:repository-setup:start -->
```powershell
$env:PYTHON = Get-Command python -CommandType Application | Select-Object -First 1 -ExpandProperty Source
npm.cmd ci
if ($LASTEXITCODE -ne 0) { throw 'Dependency installation failed.' }
& $env:PYTHON -m venv .venv
if ($LASTEXITCODE -ne 0) { throw 'Python environment creation failed.' }
$env:PYTHON = Join-Path $PWD '.venv\Scripts\python.exe'
& $env:PYTHON -m pip wheel --no-deps ./packages/cso-python --wheel-dir artifacts
if ($LASTEXITCODE -ne 0) { throw 'Python wheel build failed.' }
& $env:PYTHON -m pip install --no-index --find-links artifacts --force-reinstall cs-object
if ($LASTEXITCODE -ne 0) { throw 'Python wheel installation failed.' }
npm.cmd run build:cli
if ($LASTEXITCODE -ne 0) { throw 'CLI build failed.' }
& $env:PYTHON -I -X utf8 -m cso_python bindings examples/two-panel
if ($LASTEXITCODE -ne 0) { throw 'Two-panel binding generation failed.' }
& $env:PYTHON -I -X utf8 -m cso_python bindings examples/section-properties
if ($LASTEXITCODE -ne 0) { throw 'Section binding generation failed.' }
npx.cmd playwright install chromium
if ($LASTEXITCODE -ne 0) { throw 'Chromium installation failed.' }
```
<!-- docs:repository-setup:end -->

`PYTHON` contains one executable path, not `py -3.11` or other command arguments.
The call operator `&` handles paths with spaces. No environment activation or
global execution-policy change is needed. Use `npm.cmd` and `npx.cmd` in these
PowerShell recipes so PowerShell selects the command wrappers explicitly.

Rebuild and reinstall the wheel after Python source changes. Exporting `PYTHON`
selects the installed interpreter for the CLI and test runners. A source/editable
install does not prove wheel contents or behavior outside the checkout.
Expand All @@ -39,6 +74,14 @@ empty states and standalone builds.
Deployment settings live in [vercel.json](../vercel.json); its build context is
the repository root. A local build does not establish a hosted deployment result.

In PowerShell, start the demo with `npm.cmd run dev` or build it with
`npm.cmd run build:demo`. For calculation verification and checked HTML/PDF, use the
[PowerShell CLI examples](../packages/cso-cli/README.md#powershell-51-and-7).

Native automated checks use Windows Server 2025. They provide evidence for the
commands under test. Windows 11 foreground Ctrl+C/restart and human inspection
of delivered reports remain separate qualification steps.

## Checks

Run package behavior tests for the changed project, then the affected
Expand All @@ -54,7 +97,8 @@ access. PDF checks also need Chromium and Poppler.
## Continuous integration

[CI](../.github/workflows/ci.yml) runs on every pull request and pushes to `main`
with Node 24 and Python 3.11 on Ubuntu. It keeps these required check names,
with Node 24 and Python 3.11 on Ubuntu and Windows Server 2025. It keeps these
required Ubuntu job names,
with PR execution selected by the changed files:

- `quality`: dependency audit, lint, typechecking, workspace tests and demo build.
Expand All @@ -63,6 +107,14 @@ with PR execution selected by the changed files:
type/export/browser consumers. Both archive commands are required when this
job runs. Full installed consumers run on main, manual runs and before release.

The `windows-installed` matrix runs the maintained
[installed-user workflow](../tests/integration/installed/windows-user-workflow.ps1)
in PowerShell 5.1 and 7. It checks actual npm archives and the Python wheel in
external paths with spaces and Unicode, including browser/API behavior, checked
HTML/PDF, and owned process teardown and restart. Its two check names,
`windows-installed (powershell-5.1)` and `windows-installed (pwsh-7)`, are not
currently required protection contexts.

[Dependency review](../.github/workflows/dependency-review.yml) adds the required
`dependency-review` check for newly introduced high or critical vulnerabilities,
including development dependencies. The audit in `quality` also checks existing
Expand All @@ -80,12 +132,18 @@ Like other `pull_request` workflows, changes to the workflow itself require revi

CI's `changes` job selects PR checks:

| Changed files | `quality` | `isolation` | `installed-packages` |
| --- | --- | --- | --- |
| Only `.md` files | Skip | Skip | Skip |
| Only examples or integration tests, optionally with Markdown | Run | Skip | Skip |
| Package/app files or recognized dependency/build configuration | Run | Run | Skip |
| CI tooling, workflows or unrecognized paths | Run | Run | Run |
| Changed files | `quality` | `isolation` | `installed-packages` | `windows-installed` |
| --- | --- | --- | --- | --- |
| Only Windows workflow guides listed below | Skip | Skip | Skip | Run |
| Only other `.md` files | Skip | Skip | Skip | Skip |
| Only examples or integration tests, optionally with Markdown | Run | Skip | Skip | Run |
| Package/app files or recognized dependency/build configuration | Run | Run | Skip | Run |
| CI tooling, workflows or unrecognized paths | Run | Run | Run | Run |

Windows guide selection covers `docs/development.md`, `docs/authoring.md`,
`docs/rendering.md`, package README files and initializer template Markdown.
The `run_windows` output selects both native shells, including for these
Markdown-only changes.

The workflow defines the recognized paths. Mixed PRs run every job required by
any changed path. Rename detection is disabled so both old and new paths count,
Expand All @@ -103,6 +161,9 @@ Release publishing still depends on the full reusable CI workflow.

`npm run test:ci` exercises the classifier in temporary Git repositories and
checks the actual job conditions, fallback behavior and release dependencies.
It also [compares the ten published PowerShell blocks](../scripts/check-windows-powershell-docs.test.ts)
with the executed Windows workflow, allowing only line-ending and common
indentation differences.
PR title validation, dependency review and GitHub-managed CodeQL keep their own
triggers.

Expand Down Expand Up @@ -137,11 +198,17 @@ to this pin through all required checks, including ESM/CJS builds, declarations,
CLI/PDF acceptance and browser consumers. Remove the overrides when upstream
ranges permit a patched version and fresh workspace/isolated installs confirm it.

Isolation and installed-package jobs retain logs and evidence for 14 days,
Isolation, installed-package and Windows jobs retain logs and evidence for 14 days,
including generated PDFs and their hashes. Passing automated PDF checks leaves
visual inspection pending. Use the [rendering guide](rendering.md#choose-verification-by-change)
to select HTML or PDF checks and apply its delivery requirements.

Each Windows artifact set retains host versions, command statuses, archive and
binding hashes, reference agreement, HTML/PDF and browser-download evidence,
and port/restart receipts. Evidence is uploaded after success or failure unless
the job is cancelled. Automated termination uses `taskkill /T /F`; Windows 11
foreground Ctrl+C and human PDF inspection remain separate qualifications.

## Test data

Keep the suite concentrated on public behavior and important failures. Package
Expand Down Expand Up @@ -169,6 +236,47 @@ archive paths together in the consumer. Install the Python wheel into its chosen
interpreter. Use the package manifests for versions and peer dependencies.
These commands do not publish to npm or PyPI.

In PowerShell 5.1 or 7, after repository setup, pack the libraries and CLI and
install their archives into a new temporary consumer:

<!-- docs:archive-consumer:start -->
```powershell
$artifacts = Join-Path $PWD 'artifacts'
$utf8 = [System.Text.UTF8Encoding]::new($false)
[Console]::OutputEncoding = $utf8
$packedText = npm.cmd pack --workspace '@cs-object/core' --workspace '@cs-object/react' --workspace '@cs-object/cli' --pack-destination $artifacts --ignore-scripts --json
if ($LASTEXITCODE -ne 0) { throw 'Archive creation failed.' }
$packed = ($packedText -join "`n") | ConvertFrom-Json
$archives = @($packed | ForEach-Object { Join-Path $artifacts $_.filename })
$consumer = Join-Path ([System.IO.Path]::GetTempPath()) ('cso-consumer-' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory $consumer | Out-Null
Push-Location $consumer
try {
npm.cmd init -y
if ($LASTEXITCODE -ne 0) { throw 'Consumer initialization failed.' }
npm.cmd install -- $archives
if ($LASTEXITCODE -ne 0) { throw 'Archive installation failed.' }
& $env:PYTHON -m venv .venv
if ($LASTEXITCODE -ne 0) { throw 'Consumer Python environment creation failed.' }
$env:PYTHON = Join-Path $PWD '.venv\Scripts\python.exe'
& $env:PYTHON -m pip install --no-index --find-links $artifacts cs-object
if ($LASTEXITCODE -ne 0) { throw 'Consumer wheel installation failed.' }
& (Join-Path $PWD 'node_modules\.bin\cso.cmd') --help
if ($LASTEXITCODE -ne 0) { throw 'Installed CLI launch failed.' }
} finally {
Pop-Location
}
```
<!-- docs:archive-consumer:end -->

The archives use the builds produced during repository setup. Skipping the pack
lifecycle scripts keeps the captured output valid JSON. The consumer remains at
`$consumer`; select that directory to use its local CLI. Select the repository
interpreter again when returning to repository work.
This route needs no registry release for the CSO packages. It still downloads
third-party npm dependencies. The [initializer guide](../packages/create-cs-object/README.md)
owns project creation, which uses its declared dependency versions.

## Registry releases

[Release packages](../.github/workflows/release.yml) is a manual GitHub Actions
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
"test:packages": "npm run build:cli && tsx tests/integration/installed/acceptance.ts && npm run test:initializer",
"test:initializer": "tsx tests/integration/installed/initializer-acceptance.ts",
"typecheck": "npm run build:lib && tsc --noEmit --pretty false && npm run typecheck --workspaces",
"lint": "npm run lint --workspaces && biome lint tests scripts/check-library-archives.ts scripts/check-project-isolation.ts scripts/run-python-tests.ts scripts/check-pr-title.test.ts scripts/check-ci.test.ts",
"lint": "npm run lint --workspaces && biome lint tests scripts/check-library-archives.ts scripts/check-project-isolation.ts scripts/run-python-tests.ts scripts/check-pr-title.test.ts scripts/check-ci.test.ts scripts/check-windows-powershell-docs.test.ts",
"format": "biome format --write ./apps/demo/app ./apps/demo/src ./packages/cso-core/src ./packages/cso-react/src ./packages/cso-core/tests ./packages/cso-react/tests ./tests",
"test:library-archives": "tsx scripts/check-library-archives.ts",
"test:python": "tsx scripts/run-python-tests.ts",
"test:projects": "npm run build:cli && npm run test --workspaces",
"test:integration": "vitest run --config vitest.config.ts",
"test:isolation": "tsx scripts/check-project-isolation.ts",
"test:pr-title": "node --test scripts/check-pr-title.test.ts",
"test:ci": "node --test scripts/check-ci.test.ts"
"test:ci": "node --test scripts/check-ci.test.ts scripts/check-windows-powershell-docs.test.ts"
},
"overrides": {
"tsup": {
Expand Down
41 changes: 41 additions & 0 deletions packages/create-cs-object/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,43 @@ cd my-report
npm run dev
```

In PowerShell 5.1 or 7, select Python 3.11+ and run the setup steps explicitly:

```powershell
$env:PYTHON = Get-Command python -CommandType Application | Select-Object -First 1 -ExpandProperty Source
& $env:PYTHON --version
```

<!-- docs:project-create:start -->
```powershell
npm.cmd create cs-object my-report -- --skip-install
if ($LASTEXITCODE -ne 0) { throw 'Project creation failed.' }
Set-Location my-report
```
<!-- docs:project-create:end -->

<!-- docs:project-setup:start -->
```powershell
npm.cmd run setup
if ($LASTEXITCODE -ne 0) { throw 'Project setup failed.' }
```
<!-- docs:project-setup:end -->

<!-- docs:project-dev:start -->
```powershell
npm.cmd run dev -- --port 4173
if ($LASTEXITCODE -ne 0) { throw 'The development server failed.' }
```
<!-- docs:project-dev:end -->

Use an absolute Python executable path for `PYTHON` if the interpreter is not
on PATH. A launcher-only installation can supply that path with
`$env:PYTHON = py -3.11 -c 'import json, sys; print(json.dumps(sys.executable))' | ConvertFrom-Json`.
The JSON capture preserves Unicode executable paths under legacy console encodings.
`PYTHON` is an executable path, not a command such as `py -3.11`.
The project uses its own `.venv`; activation and execution-policy changes are
unnecessary. See the generated project's `README.md` for browser and API usage.

The initializer creates an owned project template, installs its exact CLI
dependency, prepares `.venv`, and installs Chromium. It preserves generated
files after setup failure; run `npm run setup` in the project to retry.
Expand All @@ -25,3 +62,7 @@ through its own local CLI process.

Package tests execute a real npm archive in a temporary consumer. Full runtime
acceptance belongs to the repository's installed integration checks.
Before a registry release, use the repository's
[local archive workflow](../../docs/development.md#local-package-consumers).
An initializer archive alone still installs the dependency versions named by
its template; it does not select sibling archives automatically.
28 changes: 28 additions & 0 deletions packages/create-cs-object/template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Node dependencies, creates a private `.venv`, and installs Chromium for PDF outp
npm run dev
```

In PowerShell 5.1 or 7, use `npm.cmd run dev`. Commands that invoke the installed
CLI directly use `.\node_modules\.bin\cso.cmd`; see
[Check the result](authoring.md#check-the-result).

Open the localhost address printed in the terminal. Edit numeric inputs in the
browser, calculate, and review the report. Download its PDF when needed. Change
formulas in `calculations/report.cso.py`, then calculate again. If you change the declared
Expand Down Expand Up @@ -43,13 +47,37 @@ The result is `{"area":6}`. Use the report ID from `reports.json` in place of
accepts the same body and returns a captured run with report and download links.
Wait for the initial report to load before testing input edits in the browser.

In PowerShell 5.1 or 7, the equivalent request avoids native-shell JSON quoting:

```powershell
$request = @{ inputs = @{ width = 2; height = 3 } } | ConvertTo-Json
Invoke-RestMethod -Uri 'http://127.0.0.1:5173/api/reports/rectangle-area/calculate' -Method Post -ContentType 'application/json; charset=utf-8' -Body $request
```

Use the port printed by your development server, such as `4173` when you select
that port explicitly. The response's `area` property is `6`.

To choose a port, run `npm run dev -- --port 4173`. Use port `0` to select an
available port. Stop the server with Ctrl+C and use the same command to restart.

If setup failed or you used `--skip-install`, run `npm run setup`.
Set `PYTHON` to a Python executable if automatic detection cannot find Python
3.11 or newer. Setup can be run again without replacing calculation files.

In PowerShell, retry with `npm.cmd run setup`. `PYTHON` accepts one absolute
executable path, including a path with spaces. Use
`& $env:PYTHON --version` to inspect it. Setup creates `.venv\Scripts\python.exe`.
You do not need to activate the environment or change an execution policy.

Build the frontend from PowerShell with:

<!-- docs:project-build:start -->
```powershell
npm.cmd run build
if ($LASTEXITCODE -ne 0) { throw 'The frontend build failed.' }
```
<!-- docs:project-build:end -->

Before replacing the starter, update [the brief](brief.md), collect
[references](references/README.md), and read [the authoring notes](authoring.md).
Source-to-document consistency checks that the documented formulas agree with
Expand Down
44 changes: 42 additions & 2 deletions packages/create-cs-object/template/authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ function:
./.venv/bin/python -m cso_python bindings calculations --check
```

In PowerShell 5.1 or 7, use the project's interpreter directly:

<!-- docs:project-bindings:start -->
```powershell
$env:PYTHON = Join-Path $PWD '.venv\Scripts\python.exe'
& $env:PYTHON -I -X utf8 -m cso_python bindings calculations
if ($LASTEXITCODE -ne 0) { throw 'Binding generation failed.' }
& $env:PYTHON -I -X utf8 -m cso_python bindings calculations --check
if ($LASTEXITCODE -ne 0) { throw 'Bindings are stale.' }
```
<!-- docs:project-bindings:end -->

For a file `calculations/geometry.cso.py` with a public function
`rectangle`, a parent in that directory can import and call it:

Expand Down Expand Up @@ -155,6 +167,11 @@ metadata or public output selections. Formula-only edits may leave the
interface current. Generation validates definitions but does not execute
formulas. A missing or stale handle will not regenerate itself.

Save authored Python as UTF-8 with LF line endings. The project's `.gitattributes`
keeps Python and stub files at LF on Git checkout. Generated bindings already
use UTF-8/LF. Source hashes cover exact bytes, so an editor's encoding or newline
change can invalidate a reference even when the formula is unchanged.

Each distinct quantity needs distinct displayed notation. Repeated child
calls qualify child glyphs using their call names. When a reference
deliberately reuses a glyph in separate contexts, set a meaningful
Expand All @@ -172,8 +189,7 @@ returned result in the report. Check that the displayed substitutions and
outputs match the intended engineering method.

From the project root, verify one execution and generate checked HTML with the
project's Python interpreter. These examples use a POSIX shell; on Windows the
interpreter is `.venv/Scripts/python.exe`.
project's Python interpreter. In a POSIX shell:

```sh
PYTHON="$PWD/.venv/bin/python" npx --no-install cso verify calculations/report.cso.py \
Expand All @@ -183,6 +199,30 @@ PYTHON="$PWD/.venv/bin/python" npx --no-install cso html calculations/report.cso
--function calculate --out output/report.html --check-layout --format json
```

For the unchanged rectangle starter, these PowerShell 5.1 and 7 commands verify
width 2 and height 3, then write checked HTML and a PDF:

<!-- docs:project-report:start -->
```powershell
$env:PYTHON = Join-Path $PWD '.venv\Scripts\python.exe'
$cso = Join-Path $PWD 'node_modules\.bin\cso.cmd'
$source = Join-Path $PWD 'calculations\report.cso.py'
& $cso verify $source --function calculate --input width=2 --input height=3 --format json
if ($LASTEXITCODE -ne 0) { throw 'Calculation verification failed.' }
New-Item -ItemType Directory -Force (Join-Path $PWD 'output') | Out-Null
& $cso html $source --function calculate --input width=2 --input height=3 --out (Join-Path $PWD 'output\report.html') --check-layout --format json
if ($LASTEXITCODE -ne 0) { throw 'Checked HTML generation failed.' }
& $cso pdf $source --function calculate --input width=2 --input height=3 --out (Join-Path $PWD 'output\report.pdf') --format json
if ($LASTEXITCODE -ne 0) { throw 'PDF generation failed.' }
```
<!-- docs:project-report:end -->

Use `&` when invoking an executable stored in a variable. These commands use the
project's installed CLI and managed interpreter, including when the project
path contains spaces. Setup installs the matching Chromium used by both report
commands. The [reference recipe](references/README.md#bind-an-independent-case)
shows how to save structured JSON as UTF-8 without a BOM in either PowerShell.

Repeat verification with `--input name=value` for representative and boundary
cases. Check each command's exit status and report diagnostics. Open the HTML
and inspect its content; automated layout checks leave visual inspection pending.
Expand Down
Loading
Loading