Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ca1db40
fix: askr outdated/update/upgrade crash on ESM directory import (#151)
smiggleworth Sep 29, 2026
69c012e
docs: require a changelog section with every version bump
smiggleworth Sep 29, 2026
7773bac
fix: serialize concurrent skills sync and retry transient Windows ren…
smiggleworth Sep 29, 2026
b98aead
chore(deps): bump the other-minor-and-patch group across 1 directory …
dependabot[bot] Oct 1, 2026
7b61765
fix(ssg): copy the live output folder under the directory lock for --…
smiggleworth Oct 2, 2026
e849f66
ci: drop the redundant main-branch check from the publish workflow (#…
smiggleworth Oct 2, 2026
7946dcc
fix(cli): encode every registry path separator (#160)
smiggleworth Oct 3, 2026
58ac365
fix: correct analyzer false positives and benchmark qualification (#170)
smiggleworth Oct 9, 2026
74ea2de
fix(templates): import shared icon prop types from core (#172)
smiggleworth Oct 9, 2026
1e9f221
refactor(api): minimize SSG exports and reduce analyzer work (#174)
smiggleworth Oct 10, 2026
0262778
perf(analyze): reuse indexed syntax nodes across rules (#175)
smiggleworth Oct 10, 2026
3fd1072
fix: preserve originals across failed CLI file updates (#176)
smiggleworth Oct 10, 2026
4f2efc8
fix: recover interrupted directory publication (#177)
smiggleworth Oct 10, 2026
d5cee64
fix: guard generated directory ownership and recovery (#178)
smiggleworth Oct 10, 2026
5f8098a
fix: preserve filesystem lock ownership during recovery (#179)
smiggleworth Oct 10, 2026
751ed86
fix: retry Windows lock scans during owner handoff (#180)
smiggleworth Oct 10, 2026
538726e
fix: retry readonly lock observations during Windows handoff (#181)
smiggleworth Oct 10, 2026
1ec1965
fix: classify lock reads and dispose rejected OpenAPI bodies (#182)
smiggleworth Oct 10, 2026
d96e3c9
feat(analyze): diagnose missing operation cancellation signals (#183)
smiggleworth Oct 10, 2026
3a26783
feat(analyze): enforce explicit access declarations on protected regi…
smiggleworth Oct 10, 2026
7a5251c
chore(deps): bump the other-minor-and-patch group across 1 directory …
dependabot[bot] Oct 12, 2026
91c4ce0
chore(deps-dev): bump the askr-packages group across 1 directory with…
dependabot[bot] Oct 12, 2026
636a492
feat(cli): add provider auth scaffolds
smiggleworth Oct 12, 2026
1c2b8e3
fix: correct generated provider launchers and asset roots (#189)
smiggleworth Oct 13, 2026
5e15ca4
fix(bench): enforce analyzer benchmark result budgets (#193)
smiggleworth Oct 13, 2026
54f1ea3
chore(release): prepare CLI 0.5.0 candidate graph (#188)
smiggleworth Oct 14, 2026
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
64 changes: 42 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: "lts/*"
node-version: "24.21.0"
cache: npm
- name: Setup qualified npm
shell: bash
run: |
npm install --global npm@12.0.1
test "$(node --version)" = "v24.21.0"
test "$(npm --version)" = "12.0.1"
- name: Install dependencies
run: npm ci
- name: Audit production and development dependencies
Expand All @@ -39,7 +45,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: ["lts/*"]
node: ["24.21.0"]

steps:
- name: Checkout repository
Expand All @@ -50,6 +56,12 @@ jobs:
with:
node-version: ${{ matrix.node }}
cache: npm
- name: Setup qualified npm
shell: bash
run: |
npm install --global npm@12.0.1
test "$(node --version)" = "v24.21.0"
test "$(npm --version)" = "12.0.1"
- name: Install dependencies
run: npm ci

Expand All @@ -60,24 +72,14 @@ jobs:
- name: Format check
run: npm run fmt --if-present -- --check

- name: Lint
run: npm run lint
- name: Full release checks
run: npm run check

- name: Build
run: npm run build
- name: Installed typed-client cancellation contract
run: npm run test:analyze-cancellation

- name: Test
run: npm run test:coverage

- name: Type checks
run: |
npm run typecheck --if-present
npm run test:types --if-present

- name: Package contract
run: |
npm run test:publint
npm run pack:check
- name: Installed protected-registry access contract
run: npm run test:analyze-access

packed-templates:
name: Packed template integration (Node LTS)
Expand All @@ -89,15 +91,21 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: "lts/*"
node-version: "24.21.0"
cache: npm
- name: Setup qualified npm
shell: bash
run: |
npm install --global npm@12.0.1
test "$(node --version)" = "v24.21.0"
test "$(npm --version)" = "12.0.1"
- name: Install dependencies
run: npm ci
- name: Verify packed CLI against every template
run: npm run test:templates

peer-floor:
name: Packed Askr peer floor (0.4.0)
name: Packed Askr peer floor (0.5.0)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
Expand All @@ -106,8 +114,14 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: "lts/*"
node-version: "24.21.0"
cache: npm
- name: Setup qualified npm
shell: bash
run: |
npm install --global npm@12.0.1
test "$(node --version)" = "v24.21.0"
test "$(npm --version)" = "12.0.1"
- name: Install dependencies
run: npm ci
- name: Verify the minimum supported Askr peer
Expand All @@ -123,8 +137,14 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: "lts/*"
node-version: "24.21.0"
cache: npm
- name: Setup qualified npm
shell: bash
run: |
npm install --global npm@12.0.1
test "$(node --version)" = "v24.21.0"
test "$(npm --version)" = "12.0.1"
- name: Install dependencies
run: npm ci
- name: Run deterministic CLI performance gate
Expand Down
9 changes: 1 addition & 8 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@ on:
workflow_dispatch:

jobs:
release-branch:
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Require main release branch
run: test "$GITHUB_REF" = 'refs/heads/main'

ci:
uses: ./.github/workflows/ci.yml
permissions:
contents: read

publish:
needs: [release-branch, ci]
needs: [ci]
uses: askrjs/actions/.github/workflows/publish-package.yml@main
permissions:
contents: write
Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Add regression tests with every behavior change. Use Vitest’s `test`/`describe

Use imperative, conventional commit subjects such as `fix: ...`, `test: ...`, `ci: ...`, or `chore: ...`. Keep commits focused. Pull requests should explain the behavior change, identify validation commands and results, link the relevant issue, and call out workflow, package, or release implications. Do not publish packages or create tags without explicit authorization.

Any change to the `version` field in `package.json`, whether a release, prerelease, or patch bump, must include a matching `## <version>` section in `CHANGELOG.md` in the same commit or pull request. Date the section and list breaking changes (with migration notes), deprecations, additions, and fixes. Move entries from `Unreleased` into the new version section rather than leaving them there. Do not publish or tag a version whose changelog section is missing. Check with `npm run test:changelog` (also part of `npm run check`), which fails unless `CHANGELOG.md` has a `## [Unreleased]` heading and a `## [<version>] - YYYY-MM-DD` section for the current version.

## Configuration and Security

Do not commit credentials, generated `dist/` output, temporary tarballs, or local `node_modules/`. Preserve `package-lock.json` whenever dependency manifests change. Prefer `npm ci` for reproducible CI installs and review npm script-install warnings before approving new dependencies.
Expand Down
108 changes: 108 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,114 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.5.0] - 2026-10-12

### Added

- Generate Auth0, Microsoft, Google and Apple provider sessions with
`askr create --auth` and `askr add auth`, using explicit HTTPS origins
and typed client bindings.

- Add opt-in `askr/route-access-policy` analysis for exact protected registry
file/export identities. Warn when a statically known leaf has no native
`auth` requirement or non-empty `policies`, including inherited access.

- Extend `askr/data-cancellation` to canonical typed Fetch clients and ad hoc request functions, checking each request against its own operation signal while preserving unknown/spread inputs and warning severity.

### Breaking

- Retain only `SitemapConfig` and `SsgOutputReportConfig` from the SSG type
entrypoint. Derive supporting configuration shapes from those owners. Generated
report implementation types are private; the documented JSON artifact remains.
See [all eleven export decisions and migration notes](docs/0.5.0-api.md).

### Fixed

- Wire generated provider servers to the configured HTTPS origin and canonical
host, include Node types in generated provider projects, and serve built assets
from the production directory while excluding server bundles and Vite manifests.

- Dispose rejected or redirected OpenAPI response bodies, including header
validation and redirect-limit failures. Stop streaming unused bodies after
reporting an error. Keep normal complete responses and load limits unchanged.
- Keep lock preflight errors separate from rename contention so a denied
observation cannot silently admit a transaction. Preserve the existing
bounded retry for Windows lock observations and propagate other failures.

- Retry a denied lock-directory scan during Windows publication handoff within
the existing wait bound. Also retry denied owner-record reads and lock
observations while a prior owner removes them. Retain the native error when
denial persists and preserve the owner. Avoid rejecting contenders during
normal lock handoff.

- Prepare file and directory locks with unique owner records before publishing
them. Recover only the observed dead owner so delayed stale-lock recovery
cannot delete a successor's lock and allow overlapping updates. Preserve
ambiguous lock contents and junctions; report failed private-stage cleanup.

- Publish generated OpenAPI clients through the same recoverable directory
swap as other commands. Keep complete published output when backup cleanup
fails, clean partial stages, and report retained stages after cleanup failure.
Recheck project destination ownership under the publication lock so concurrent
creates cannot replace each other's projects or unrelated files. Print project
creation success only after publication completes.

- Record directory publication before moving the original tree. Recover an
interrupted create, skills or SSG swap before the next locked operation;
finish failed backup cleanup on retry. Reject file and symbolic-link targets,
preserve permission errors, and retain ambiguous recovery trees for inspection.

- Save original file copies before replacing any files, retain copies that cannot
be restored, and report recovery paths. Manifest edits use the shared guarded
writer so unrelated edits made after planning are preserved. Clean partial
staging writes, reject filesystem permission errors, and preserve existing
POSIX permission bits while respecting the umask for new files.

- Reuse the syntax-fact index's node order across analyzer rules instead of
repeatedly walking each syntax tree. Preserve diagnostics, source fixes and
fresh bindings when a file changes, with the existing benchmark budgets.

- Compile analyzer exclusions once per workspace and reuse the existing syntax
call index when collecting state declarations, preserving the matcher and
diagnostic contracts without increasing benchmark budgets.

- Generate starter-kit icon prop types from the owning core icon entrypoint,
preparing templates for the Lucide 0.5 public helper/type contraction.

- Wire the analyzer budget reporter into benchmark mode, initialize benchmark
fixtures through global setup, and reject failed, missing, non-finite, or
sample-free measurements. Fixture assertion failures now fail the benchmark
command instead of yielding a successful `NaN` comparison.
- Retain the analyzer's strict local performance targets and establish a
measured GitHub-hosted Ubuntu envelope against the pre-fix implementation.
- Refresh `http-cache-semantics` to 4.3.0 and `source-map-js` to 1.2.2 within
their existing dependency ranges; the clean-install dependency audit is clear.
- Consolidate the analyzer's `askr/no-hardcoded-theme-token` documentation into
one entry covering token and color policies
([#166](https://github.com/askrjs/askr-cli/issues/166)).
- Recognize plural test filenames, test directories, module extensions, and
Windows paths when exempting color fixtures. Other analyzer rules still run
in those files ([#167](https://github.com/askrjs/askr-cli/issues/167)).
- Follow synchronous workspace registry factories and imported callback helpers
without treating unresolved callable arguments as definite violations. Keep
timer and event callbacks outside registry ownership, and resolve local source
imports through symlinked project paths
([#168](https://github.com/askrjs/askr-cli/issues/168)).
- `askr outdated`, `askr update`, and `askr upgrade` no longer crash with
`ERR_UNSUPPORTED_DIR_IMPORT` when loading npm configuration under Node ESM
([#150](https://github.com/askrjs/askr-cli/issues/150)).
- Concurrent `askr skills sync` runs against the same project no longer fail
intermittently on Windows. The live `skills/` tree is now copied, updated, and
swapped under a single directory lock, and the swap retries transient
`EPERM`/`EBUSY`/`EACCES` rename errors. Concurrent `askr skills install`
runs without `--force` now admit exactly one install into an empty target
([#153](https://github.com/askrjs/askr-cli/issues/153)).
- `askr ssg --incremental` copies the live output folder into its staging
folder under the directory lock, so concurrent incremental builds into one
folder can no longer stage from a half-swapped tree or race the final swap.
The lock is held only for the copy, not for site generation
([#155](https://github.com/askrjs/askr-cli/issues/155)).

## [0.4.0] - 2026-09-28

### Changed
Expand Down
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const staticConfig = {
};
```

The sitemap config types are available from `@askrjs/cli/ssg` for projects that
`SitemapConfig` and `SsgOutputReportConfig` are available from `@askrjs/cli/ssg` for projects that
want an explicit annotation.

Successful and incrementally skipped concrete routes are included by default.
Expand All @@ -156,8 +156,15 @@ and enforces the sitemap protocol limits of 50,000 URLs and 50 MB per file.
Larger sites receive deterministic sitemap chunks plus a sitemap index. It also
creates or updates `robots.txt` while preserving unrelated directives and tracks
owned files so stale chunks and previous output paths are removed. Full and
incremental builds publish through a sibling staging directory, so route output,
metadata, assets, and sitemap artifacts change together or not at all.
incremental builds publish route output, metadata, assets and sitemap artifacts
as one complete tree through a sibling staging directory.
If a process exits between publication renames, the next build restores the old
output or finishes cleanup of the completed output before copying it. A recovery
conflict stops the build and names the record and original backup for inspection.
See the [SSG recovery boundary](docs/ssg.md) for details.
OpenAPI client generation uses the same publication recovery. Project creation
checks that its destination is still missing or empty under the publication lock,
so a concurrent create cannot replace an already published project.

## OpenAPI artifacts

Expand Down Expand Up @@ -212,6 +219,11 @@ lockfile, installs packages, runs lifecycle scripts, or edits overrides,
resolutions, catalogs, or `packageManager` metadata. See the
[update command reference](./docs/update.md) for policy and output details.

Writes save original copies before replacement and reject manifests changed
since planning. If restoring a failed replacement also fails, the error names
the preserved recovery copy and target to restore before retrying. See the
reference for recovery after process termination.

## Agent skills

Install the bundled Askr skills into a project:
Expand Down Expand Up @@ -251,3 +263,6 @@ Templates are stored in `templates/`.
## Docs

- [CLI docs](./docs/README.md)

The 0.5 SSG surface keeps those two configuration types. See the
[complete export decisions and migration guide](docs/0.5.0-api.md) for supporting-type replacements.
Loading
Loading