Release v2.14.0
Add @cratis/ai: wire Cratis.Arc.ProxyGenerator.Build and publish the generated proxy package
Phase 3b of the Cratis.AI consolidation (plan Section 6) - the generated Arc command/query proxy
package both Direct and Studio will consume the package's read models and commands through.
Cratis.AI.csproj:
- References Cratis.Arc.ProxyGenerator.Build directly (PrivateAssets=all), matching Studio's own
Core.csproj rather than pulling it in transitively through the ASP.NET-oriented "Cratis"
metapackage - the generator itself reflects over the compiled assembly with no ASP.NET Core
hosting involved, so nothing more than Cratis.Arc.Core (already referenced) plus this build-time
tool is needed. - CopyLocalLockFileAssemblies=true - required and non-obvious: the generator resolves Cratis.AI.dll's
dependency closure (Cratis.Chronicle, Cratis.Fundamentals, ...) through a reflection-only
MetadataLoadContext, which needs every referenced assembly physically present next to Cratis.AI.dll
in the output directory. A plain class library does not copy its NuGet dependencies locally by
default (an ASP.NET Core app, which is what Direct's and Studio's own proxy-generating projects
are, does) - without this the generator crashed trying to resolve EventSourceId's base type
from a Cratis.Chronicle it could not find. - CratisProxiesOutputPath points at Source/Cratis.AI.Proxies/generated, a subfolder rather than the
package root: CratisProxiesSkipOutputDeletion=false (deliberate per plan Section 6.3, so a deleted
command cannot leave a stale proxy) wipes its entire output directory on every build, which would
otherwise take the package's own package.json/tsconfig.json/rollup.config.mjs/index.ts with it. - --namespace-root=Cratis.AI=. strips the redundant AI/ folder a literal namespace mapping would
otherwise produce inside a package already named @cratis/ai. - Route prefix: /api/a-i/... via SegmentsToSkip=1, per the plan's own Section 6.4 recommendation -
distinct and collision-proof against either product's own routes. Decision 0004 records the full
reasoning for all of the above, including the alternatives rejected.
RecordAgentSessionUsage's command validator was removed entirely as a direct consequence of getting
this far: Arc's IModelGraphValidator already applies each ConceptAs property's own ConceptValidator
automatically (InputTokensValidator, CpuSecondsValidator, ...), so the command-level rules
duplicating "cannot be negative" were pure redundancy - and, as it turned out, the one thing standing
between this and a working build: the ProxyGenerator translates a validator's property-chain
expression literally, and CostUsd!.Value became a nonsensical c.costUsd.Value access on a
TypeScript property already flattened to a plain number. Validate at the concept, not the command,
for this class of property.
Source/Cratis.AI.Proxies (@cratis/ai): package.json/tsconfig.json/rollup.config.mjs modelled on
Arc's own @cratis/arc package, peer-depending on @cratis/arc, @cratis/arc.react, @cratis/fundamentals
and react per plan Section 6.2. A hand-maintained index.ts barrels the generated tree - the generator
emits one index.ts per generated folder but has no way to know which output path is a package root,
so it does not emit one at the top.
publish.yml:
- verify job now runs a real dotnet build before the generated-proxies drift check, so the check
actually compares a freshly regenerated tree against what is committed rather than the checked-out
tree against itself (a gap the drift gate had from when it was first added with a "does not exist
yet" no-op). - New publish-npm-packages job: rebuilds Cratis.AI, sets @cratis/ai's version to the same release
version cratis/release-action determined, builds the rollup bundle, publishes with npm provenance -
the same OIDC trusted-publishing shape publish-pi already uses. - verify-published now fails the run if Cratis.AI (NuGet) and @cratis/ai (npm) do not publish
together - the two are one artifact split across two registries (plan Section 6.5), and letting one
succeed while the other fails is exactly the version-skew risk #13 exists to prevent.
Also fixes two latent gaps from Phase 1 that only surfaced once a real bundled TypeScript package
existed to exercise them: eslint.config.mjs referenced eslint-plugin-react, which was never added to
package.json; vitest.config.ts's projects glob pointed at Source/JavaScript/* (Arc's own layout, not
this repository's Source/**/*).
Verified: yarn workspace @cratis/ai run ci (clean, lint, build) passes; dotnet build regenerates
Usage/RecordAgentSessionUsage + Usage/Trends/AgentUsageByWeek+AgentUsageByMonth +
Usage/Daily/AgentUsageByDay (1 command, 3 queries) with a clean TypeScript compile; all 109 remaining
.NET specs pass (110 minus the one spec for the now-removed command validator); the existing
Harness.Setup/Pi.Plugin/Verification workspace checks are unaffected.