Repository navigation
Conversation
Replace the scattered homepage snippets with one type-checked app.ts whose regions walk model, release, command, audit, open work, and storage + HTTP in order. CI runs it to produce every output, including a real in-process HTTP read and per-layer line counts shown by a new StackMap component. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add EntityType.assert(id, values, options?) to build typed assert operations for a whole entity, validTo on Attribute.assertion, and GraphConstraint.pinned(release) to derive configSnapshot and enforce from one release. Attribute.use now keeps a literal cardinality in its type so cardinality-many uses take arrays. Rewrite the homepage command and story snippets with the helpers; every scenario output except line counts is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e-helpers # Conflicts: # docs/snippets/home/site-safety/app.ts # docs/snippets/home/site-safety/output/stack.json # docs/snippets/home/site-safety/story.ts
Mention Placement.assert and GraphConstraint.pinned in the command copy, shorten the pinned comment so it fits the code block, and refresh the homepage screenshots for the shorter command region. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Attribute definitions gain .required(), .many(), and .unique(), and EntityType.make accepts aliased fields directly, treating a bare definition as an optional single-valued use. Both forms compile to identical nodes. Type.where and Type.not build Datalog pattern and negation clauses by alias with typed constants. Rewrite the homepage model and open-work regions with them and refresh the homepage screenshots. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
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.
What
EntityType.assert(id, values, options?)returnsReadonlyArray<TransactAssertOp>. Values are keyed by TypeScript alias and typed by their attribute, and every op is tagged with the entity type. Cardinality-many uses take an array and get one op per element. The function is pure, so ops from several entities andretracts can still go into onetransact.validToonAttribute.assertionand the handles. Bounds must be finite, and the interval[validFrom, validTo)must not be empty.GraphConstraint.pinned(release)returnsEffect<{ configSnapshot, enforce }>from a single release, so the pinned id and the enforced rules can't come from different releases.Attribute.usenow records a literal cardinality in its type (Use<D, C>,CardinalityOf<O>)..required(),.many()and.unique(), each accepting the remaining options (.required({ unique: true })).EntityType.make(name, fields)takes aliased fields directly, and a bare definition is an optional single-valued use. The{ attributes }form still works, and both forms produce identical node cids (tested).Type.where(entity, patterns)/Type.not(entity, patterns)build Datalog pattern andnotclauses by alias. Values are variables or constants typed by the attribute; refs become typedrefconstants. Datetime, JSON and blob constants throw, because Datalog has no constant form for them.Payoff
The homepage snippets are rewritten with the helpers, and the homepage screenshots are refreshed.
app.tsgoes from 116 to 104 lines: model 22 → 18, command 24 → 17, derive 26 → 25.story.tsgoes from 100 to 76. The timeline, audit, rejection, open-work and HTTP outputs are byte-identical, so the helpers produce exactly the ops and queries that were written by hand.Design choices
undefinedis skipped. Requiredness is a property of the entity's state after the transaction, andenforcechecks it atomically. Incremental writes such as addingtrainedForto an existing worker must not have to restatename. Allowing| undefinedexplicitly keeps conditional fields usable underexactOptionalPropertyTypes.EntityId, not branded per target type. AReferenceTargetconstraint catches a wrong target at commit.assert,whereandnotare now reserved aliases, alongsideentityType,schema,nodeand the others. This is a minor breaking change..required().unique()), becauseUsealready hasrequiredanduniquefields. Combinations go through options instead.Not in this PR (recommended follow-ups)
Effect.all(types.map(t => t.nodes)).flat()fails withDuplicateObjectErrorwhenever two entity types share a global attribute, for exampleEmployerandEmployerSummaryin the configuration docs.Type.decode(facts)). Move HTTP'sencodeEntitysemantics into core and have HTTP reuse them. Typing it well needs a literalrequiredonUse.Open questions
assertthe right name, compared withassertionsorfacts?createthat requires the required aliases ship next toassert?AssertionOptionsaccept| undefined?GraphConstraint.pinnedthe right name and location? Should it be memoized per root cid?Checks
pnpm check,pnpm pack:checkandpnpm test:e2epass. A Changeset for@triplex-build/triplex(minor) is included.🤖 Generated with Claude Code
Open workspace in Conductor