Repository navigation
feat(website): one spec declares a site, composes it and checks any server (FD-4683) - #445
Open
williamloo-scale wants to merge 28 commits into
Open
williamloo-scale wants to merge 28 commits into
williamloo-scale wants to merge 28 commits into
Conversation
…and checks any server (FD-4683) agentenv_protocol.website.spec models a site as one TOML declaration ([site], [source], [data], [users], [roles], [routes], [state], [clock], [[uses]], extends) with validation, extends overlays, uses composition, card params, from_card, from_environment, a multi env name table and a JSON Schema and CLI. WebsiteEnvironment can be declared with @website(spec=...) and builds its website/v1 card through the spec; conformance takes --spec. Notes now declares itself from website.toml; examples/website/specs shows a replayed Slack overlay and an SSO component. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
env.toml takes spec = "website.toml" or an inline [spec] table: the env takes its environment_name and health path from the spec when the env.toml leaves them out, refuses one that differs, stores the spec's domains, and refuses a live or replay source, which a server image can't serve. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
williamloo-scale
marked this pull request as ready for review
November 3, 2026 00:24
# Conflicts: # packages/agentenv-protocol/src/agentenv_protocol/website/conformance.py # src/agent_env/env/envs/website.py
…as no website/v1 ready (FD-4683) A deploy and the conformance check read readiness from the card, so a spec whose health path differs from the card's is the spec check's to report; the health check passes on ready. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s session as declared (FD-4683) to_dict() and overlays keep a JSON Schema as it is, a mounted component's schema file stays its own, a class's acting_user is checked against the current_user its seeds leave in load order, the spec check compares the card's session_path and requires a declared state and clock, spec_routes fails an advertised OpenAPI document that can't be read, the JSON Schema takes the false that removes an inherited entry, and a spec is read with tomli where tomllib is missing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in #428's and #443's review fixes beside this branch's spec checks: conformance runs the spec checks with the others and checks X-Universe-Now last; a card now names a route by the path it is served at, converter included, so the spec check compares paths with any converter dropped. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es, its spec or not (FD-4683)
A card built from the site's spec named a route by the spec's template
(/files/{rest}), so the gateway matched one segment of a nested route
and its triggers missed /files/a/b. website/v1's params are still the
spec's, but each route's path is now the one the class serves it at,
converters and all; a spec read back from the card keeps its template.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…claims, and its check probes typed parameters (FD-4683)
spec_routes probes a path parameter with a value the converter on the
card's route takes (a UUID for uuid, else 0), so a working
/items/{id:uuid} is no longer reported missing. false now removes an
OpenAPI operation through extends and overlay: a removed route stays a
false through the merge, and a resolved spec no longer keeps
routes.openapi, its operations being in routes.ops. An OpenAPI document
of the wrong shape or naming two operations alike is a SpecError, the
name table refuses two sites claiming one pattern at a kind that lost
it, and the JSON Schema takes an overlay's partial route table.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tion (FD-4683)
A routes.ops table naming an operation of the routes.openapi document, such as
add_item = { roles = ["staff"] } in an extends file, is now written over the
document's operation before the spec is validated, instead of failing for a
missing method and path. Changing its method or path is still refused.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… shows it (FD-4683) For a card that offers no OpenAPI document, a route only the OPTIONS probe can check (a non-GET route, or a GET route with path parameters) is now served only when that OPTIONS answers below 500 with an Allow listing its method. A catch-all's 200 without Allow, a 500, or an Allow that doesn't list the method leaves the route unverified, which makes the check a warning (a failure with --strict) rather than a pass; a 404 still fails it. An Allow that omits the method isn't taken as proof it's missing, because Starlette lists only the first matching route's methods when several routes share a path. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # packages/agentenv-protocol/src/agentenv_protocol/website/environment.py
…y does (FD-4683) A resolved spec keeps its declaration as written, extends merged but uses not yet mounted, and overlay() merges into that, so a [[uses]] of the same as replaces the mounted component instead of clashing with its routes. Equality still compares only the resolved site. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…its context (FD-4683) Spec paths accept every character RFC 3986 allows in a path (sub-delims, '@', percent-escapes), so a WebsiteEnvironment serving /api/users/@me derives a spec and starts as before. An image source's default context is rebased with its Dockerfile when an overlay in another folder inherits it, the same as an explicit context = ".". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(FD-4683) The package supports Python 3.10, which has no tomllib; the spec loader already falls back to tomli, so it is now a dependency there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…and may act as a component's persona (FD-4683) A site's acting_user is now checked only after its components' personas are merged, so it may be one only a component declares. A component route mounted under a prefix keeps its trailing slash: /items/ under /auth is /auth/items/ and / is /auth/. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Comment on lines
+577
to
+580
| elif key == "uses" and not at: | ||
| kept = {_use_id(u): u for u in merged.get("uses", [])} | ||
| kept.update({_use_id(u): copy.deepcopy(u) for u in value}) | ||
| merged["uses"] = list(kept.values()) |
There was a problem hiding this comment.
Mistyped specs crash validation
A file containing extends = "base.toml" and uses = 1 reaches this loop before _validated() and raises TypeError. An inherited data.collections = [1] in another folder similarly crashes _rebased() at .values().
The CLI and bundle authoring catch only SpecError, so authors get a traceback instead of an error naming the bad field. Check these types before merging and rebasing, or turn these failures into SpecError.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/agentenv-protocol/src/agentenv_protocol/website/spec/__init__.py
Line: 577-580
Comment:
**Mistyped specs crash validation**
A file containing `extends = "base.toml"` and `uses = 1` reaches this loop before `_validated()` and raises `TypeError`. An inherited `data.collections = [1]` in another folder similarly crashes `_rebased()` at `.values()`.
The CLI and bundle authoring catch only `SpecError`, so authors get a traceback instead of an error naming the bad field. Check these types before merging and rebasing, or turn these failures into `SpecError`.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.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.
Stacked on #444.
A website spec: one TOML file declares a site, composes from parts, and checks any server against it. Design:
docs/website-spec.md.agentenv_protocol.website.specreads[site],[source],[data],[users],[roles],[routes.ops],[state],[clock],[[uses]]andextends, with validation, overlays, composition, card params,from_card,from_environment, a JSON Schema and a CLI (validate,show,show --card).@website(spec="website.toml"): the class is refused when its@apiroutes aren't the spec's, and its card is built from the spec. Notes now declares itself this way.spec = "website.toml"or an inline[spec]; the env takes its name, health path and domains from it.conformance --specchecks a server's card and routes against the spec; those checks are required.examples/website/specs/: a replayed Slack overlay, an intranet, and an SSO component.Live and replay sources,
served_byandmodels = "mcp:..."are modelled in the spec but not deployable from env.toml yet.Test
Unit suite: 12,793 passed (one GitHub-clone test from main, which hangs on the local machine on main too, deselected).
🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge, with a non-blocking error-reporting issue for malformed specs.Fix with agent prompt
Summary
Adds one website spec for declarations, overlays, components, cards, bundle authoring, and conformance checks.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR TOML[Website spec] --> Resolve[Merge overlays and components] Resolve --> Spec[Resolved spec] Spec --> SDK[Check SDK class] SDK --> Card[Serve website card] Spec --> Bundle[Read env name, health and domains] Spec --> Check[Check any server] Card --> CheckReviews (7) · Last reviewed commit: "Merge wloo/website-sdk-followups into wl..." · Reviewed by Greptile