ci: switch to pnpm; deps to npm registry; clear lint debt#5
Merged
Conversation
[LAW:one-source-of-truth] pnpm is the canonical package manager (pnpm-lock.yaml). package-lock.json was a duplicate, stale lockfile breaking every CI run since at least 2026-04-26. Changes: - release.yml: actions/setup-node@v4 + pnpm/action-setup@v4; install with `pnpm install --frozen-lockfile`; replace `npm run`/`npm ci` with pnpm equivalents in both `test` and `release` jobs. - package.json: replace file:../go-template-js with ^0.3.0 and file:../rich-js with @promptctl/rich-js@^0.2.0 (both now published). Drop placeholder optionalDependencies — scripts/release.mjs already injects them with the real version at publish time, so keeping PLACEHOLDER entries in source was a duplicate source of truth. - pnpm-lock.yaml: regenerated. package-lock.json: deleted.
Import-only rename to match the registry-published package name. Replaces the local `rich-js` alias (pointing at `file:../rich-js`) with the canonical scope. Also threads through: - jest.config.js moduleNameMapper + transformIgnorePatterns - src/themes/rich-js-theme-data.d.ts ambient module declaration Adapts to @promptctl/go-template-js@0.3.0: - Set `missingKey: "error"` in createCcCandybarEngine. 0.3.0's default policy returns the literal string "<no value>" for missing scope fields; callers (SourceRegistry, segments) depend on the prior MissingFieldError contract to drive varDefault/defaultEmptyValue. [LAW:no-defensive-null-guards] enforces the throw at the boundary. - src/themes/oklch.ts: write the JS-representable value (1.0000000095444297, not 1.0000000095444298) so no-loss-of-precision lint stops firing.
Bring lint to zero errors so CI's lint step passes.
- eslint.config.mjs: add missing Node globals (NodeJS, BufferEncoding,
setTimeout/clearTimeout/setInterval/clearInterval) to the manual
allowlist. These have been firing as `no-undef` errors across daemon
and segments code for weeks.
- src/utils/claude.ts: PrunedRaw and UsageCounts intentionally stay as
`type` aliases (not `interface`) so they remain structurally
assignable to `Record<string, unknown>` at the extractModelId
boundary in segments/pricing.ts. The
@typescript-eslint/consistent-type-definitions rule is disabled
per-declaration with a comment explaining the load-bearing reason.
- src/segments/pricing.ts: replace inline `import("...").PrunedRaw`
with a top-level `import type { PrunedRaw }` now that the type-alias
is preserved upstream.
- Prettier autoformat sweep across dsl-loader, daemon/server,
template-engine/index, schema-validator (pre-existing drift).
There was a problem hiding this comment.
Pull request overview
Restores green CI by switching the workflow to pnpm (matching the canonical pnpm-lock.yaml), replacing file:../sibling deps with published @promptctl/* versions, and clearing the lint debt that was hidden behind the install failure. The refactor renames the rich-js import specifier to @promptctl/rich-js everywhere and adapts to the new go-template-js 0.3.0 default by setting missingKey: "error" so existing MissingFieldError-driven flows keep working.
Changes:
- CI: workflow uses
pnpm/action-setup@v4+pnpm install --frozen-lockfile;package-lock.jsonremoved; siblingfile:..deps replaced with@promptctl/go-template-js@^0.3.0and@promptctl/rich-js@^0.2.0; placeholderoptionalDependenciesdropped (re-injected byscripts/release.mjs). - Refactor: all
rich-jsimports/types/jest mappings renamed to@promptctl/rich-js;createCcCandybarEnginepinsmissingKey: "error"to preserve throw-on-missing behavior;oklch.tsliteral adjusted to a JS-representable value. - Lint: eslint globals extended with
BufferEncoding/NodeJS/timer functions;PrunedRaw/UsageCountskept astypealiases with explanatory comment and rule-disable; inlineimport()type replaced with top-levelimport type; prettier autoformat sweep.
Reviewed changes
Copilot reviewed 23 out of 27 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/release.yml | Adds pnpm setup, switches install/lint/build/test/protocol-check commands to pnpm in both jobs. |
| package.json | Replaces sibling file:.. deps with registry versions; removes placeholder optionalDependencies. |
| pnpm-lock.yaml | Updated entries for @promptctl/go-template-js@0.3.0 and @promptctl/rich-js@0.2.0. |
| jest.config.js | Rewrites moduleNameMapper and transformIgnorePatterns to the scoped package path. |
| eslint.config.mjs | Registers Node-typing/timer globals to silence pre-existing no-undef errors. |
| src/template-engine/engine.ts | Splits imports; sets missingKey: "error" to retain throw-on-missing semantics under go-template-js 0.3.0. |
| src/template-engine/{layout,colors,cells,index}.ts | Renamed imports + prettier reformat. |
| src/themes/{palette-registry,cascade,oklch,rich-js-theme-data.d.ts} | Renamed module specifiers; oklch.ts literal trimmed to a JS-exact value. |
| src/render/strip.ts, src/demo/app.ts, src/var-system/sources.ts | Renamed imports plus minor formatting. |
| src/segments/pricing.ts, src/utils/claude.ts | Replaces inline import() type with top-level import type; documents the type-vs-interface requirement with an eslint-disable. |
| src/utils/schema-validator.ts, src/daemon/server.ts, src/config/dsl-loader.ts | Prettier reformatting; NodeInfo switched to interface. |
| test/{colors,segment-cells,segment-colors,segment-layout}.test.ts | Updated import specifiers to @promptctl/rich-js. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
GitHub-hosted macOS runners (especially x86_64 macos-13) have been
queueing for hours and blocking PR checks. All four targets — darwin-{x64,arm64}
and linux-{x64,arm64} — now build on ubuntu-latest using cargo-zigbuild,
which uses zig as the cross-linker and supplies the macOS SDK stubs
needed for libc+libSystem-only binaries like this one.
The rust-client crate has no macOS framework deps (Cargo.toml: serde,
serde_json, libc); cargo-zigbuild handles it cleanly.
No more macOS runners in this workflow.
brandon-fryslie
added a commit
that referenced
this pull request
Jun 10, 2026
…y by type (cje) (#100) Sheriff finding #5 [LAW:no-silent-failure]: a time var declaring cache: watch_file / depends_on / key / never passed the loader, then renderDsl silently coerced it to the default 1s TTL — the config's stated meaning replaced with no diagnostic. TimeVarDecl.cache narrows to TtlCacheDecl, so the illegal form is unrepresentable past the load boundary [LAW:types-are-the-program]. The loader's TIME_FIELDS uses a ttl-only OneOfPresentSchema sharing CACHE_SCHEMA's own ttl arm — one declaration source feeding both the validator and the emitted JSON schema (regenerated). The render-time 'ttl' in guard and the orphaned follow-up-ticket comment delete; the TTL mapping is total. Closes brandon-config-validation-cje. Co-authored-by: elton-prawn <264370887+elton-prawn@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CI on
mainhas been red since at least 2026-04-26. Three layered issues:npm cifails — workflow uses npm but the canonical lockfile ispnpm-lock.yaml.package-lock.jsonhad been stale since May 11 (every dep update since then went only into the pnpm lockfile).file:../siblingdeps —package.jsonpointed@promptctl/go-template-jsandrich-jsat sibling directories that only exist on the maintainer's laptop, so even a pnpm install can't resolve them on CI.[LAW:one-source-of-truth]is the structural diagnosis: two lockfiles, two package-name aliases for the same package, two sources of optionalDependencies truth.Changes (three commits)
ci:Switch workflow topnpm/action-setup@v4+pnpm install --frozen-lockfile+pnpm run ...in bothtestandreleasejobs. Deletepackage-lock.json. Replacefile:../deps with registry versions (@promptctl/go-template-js@^0.3.0,@promptctl/rich-js@^0.2.0). Drop placeholderoptionalDependenciesfrom source —scripts/release.mjsalready injects them with the real version at publish time.refactor:Renamerich-js→@promptctl/rich-jsacross imports/types/jest config. Adapt to@promptctl/go-template-js@0.3.0: setmissingKey: "error"increateCcCandybarEngine(0.3.0 changed the default policy to return"<no value>"instead of throwingMissingFieldError). Fixoklch.ts:40to use the JS-representable literal.chore(lint):Add Node globals to eslint config; preservePrunedRaw/UsageCountsastypealiases (load-bearing for structural assignability atextractModelId); replace inlineimport()type with top-levelimport type; prettier autoformat sweep.Test plan
Local verification on
bf/ci-pnpm-and-deps:pnpm install --frozen-lockfilesucceedspnpm run lint→ 0 errors (1 warning, pre-existing, in loader.ts:425)pnpm run typecheck→ cleanpnpm test→ 30/30 suites, 653/653 tests passpnpm run build→ cleanpnpm run check:protocol→PROTOCOL_VERSION=2 (TS and Rust agree)gh pr checks)bf/single-daemon-flockand confirm PR fix(daemon): enforce single-daemon invariant via atomic bind() (kz8.1) #4 goes greenFollow-up
bf/single-daemon-flock(PR fix(daemon): enforce single-daemon invariant via atomic bind() (kz8.1) #4) is parked pending this fix; rebase will pick up CI parity automatically.PrunedRaw/extractModelIdstructural-typing escape is a[LAW:types-are-the-program]exception that should be untangled in a follow-up — tightenextractModelIdto takePrunedRawand drop the deadentry.model_idbranch.