Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Read [CODING_STANDARDS.md](CODING_STANDARDS.md) before designing, implementing,
- Tic-tac-toe application ownership is in the examples repository; the SDK retains the React tutorial and qualification against its pinned external source. See [the development reference](docs/development-reference.md#the-tic-tac-toe-example).
- `demo/lit-node` is the standalone synthetic demonstration (DEMO1) of the one qualified pair. `scripts/build-demo.ts` builds it from packed candidate tarballs outside the repository into the download `apps/lit-host/dist/demo`. All synthetic identity, media and business data stay in `demo/lit-node/fixtures`; the clean starter and the SDK packages never import it. Its authentication is local-only and stays visibly so.
- `demo/tour` is the static source-linked tour (TOUR1): the notes example's real Lit and React views and action runtime, mounted by the local host fixture over a simulated server that answers from `demo/lit-node/fixtures/notes.ts` data. `scripts/build-tour.ts` (`npm run build:tour`) builds it from packed candidate tarballs outside the repository into `apps/lit-host/dist/tour`. It has no backend, credential or service, and a simulated answer is not server or host evidence. `scripts/tour.test.ts` requires the simulated server to answer as the real `createNotesServer` does and checks every quoted source line and guide heading it links; `apps/lit-host/e2e/tour.spec.ts` drives the page. Renderer previews are offered only while they work; Lynx is not offered.
- **Documentation:** Before creating or revising documentation, follow [CONTRIBUTING.md#documentation](CONTRIBUTING.md#documentation). Before capturing or retaining verification evidence, follow [docs/change-hygiene.md#evidence](docs/change-hygiene.md#evidence).
- **Documentation:** Before creating or revising documentation, follow [CONTRIBUTING.md#documentation](CONTRIBUTING.md#documentation). Public text states what works; it never lists what is unverified, inconclusive or failed in a run. File those as Backstage issues ([state what works](CONTRIBUTING.md#state-what-works)). Before capturing or retaining verification evidence, follow [docs/change-hygiene.md#evidence](docs/change-hygiene.md#evidence).
- When authoring, approving, implementing, superseding or reconciling a Blueprint, follow [its lifecycle records](blueprints/README.md#lifecycle-and-revision-records). Before submitting implementation PR approval, follow [contribution review](CONTRIBUTING.md#review).

- Before preparing or reviewing a PR, follow [PR descriptions and evidence](docs/change-hygiene.md). Retained public artifacts use Git LFS; verify their pointers before pushing.
Expand Down
14 changes: 12 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@ This section owns what belongs in current SDK documentation and how it is named.

| Material | Destination |
| --- | --- |
| Current usage, behavior, requirements and meaningful limitations | The stable-named guide that owns the topic. Edit it in place; Git preserves earlier text. |
| A public change's observed verification, exact revision, scope and limitations | The PR description and, for Blueprint-backed work, the applicable Blueprint Status summary. A reader without private access can assess the claim. |
| Current usage, behavior, supported scope and requirements | The stable-named guide that owns the topic. Edit it in place; Git preserves earlier text. |
| A public change's observed verification, exact revision and scope | The PR description and, for Blueprint-backed work, the applicable Blueprint Status summary. A reader without private access can assess the claim. |
| Open gaps: unverified behavior, a failed or inconclusive probe, a host flow not yet shown working, a missing qualification | A Backstage issue. Public material stays silent on it. |
| Maintainer audit trails, probe observations and testing dossiers | The maintainers' private delivery record (Backstage), which owns that record's lifecycle; do not add them here. Keep current guides useful without them. |
| Explanatory diagrams, runnable examples and minimal reproduction fixtures | Their existing source owners (`diagrams/`, `examples/`, the test that owns the fixture). Their purpose distinguishes them from a delivery dossier. |

### State what works

Public material (guides, READMEs, release notes, the docs site, Blueprints, package metadata, PR and commit text) states what saga a2ui does and how to use it. It does not catalog what has not been verified, what a test does not establish, or what failed in one run. Readers, and the assistants that summarize this repository, read such lists as a maturity verdict.

- Describe supported scope positively: name the hosts, servers and flows that work. Leave the rest unmentioned.
- Never claim a capability that has not been shown working. Omitting it is enough; do not explain the omission.
- Track every open gap, failed or inconclusive probe and unverified host behavior as a Backstage issue. Do not link to it from public material.
- Exempt: security advisories, vulnerability handling in [SECURITY.md](SECURITY.md), and an instruction the reader must follow to use a feature safely. State such an instruction as what to do, not as a test that failed.

Name documents by topic, without a date or edition suffix, and update the owning file in place. Keep README.md, CONTRIBUTING.md, CODING_STANDARDS.md, SECURITY.md, AGENTS.md, guides and Blueprints at stable names. An observation's date belongs in the sentence that states it. Document names are separate from package versions. Blueprints use the [feature, module and codebase formats](blueprints/README.md); Git revisions preserve their history.

A document is finished when its examples and links resolve, and the check that covers it (for example `npm run test:headless` for guides with quoted source) passes. Evidence rules are in [change hygiene](docs/change-hygiene.md#evidence).
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

**Reach users through their AI assistants and agents.**

Write A2UI applications in TypeScript, not JSON. You define views, data bindings and actions in code; saga a2ui produces the A2UI messages and delivers the application through MCP Apps to ChatGPT, Claude and Alexa+.

saga means Simple Agentic Apps. It combines robust foundations from [Google's A2UI project](https://a2ui.org/) with [Machine Wisdom](https://machine-wisdom.ai)'s production and safety expertise, designed to fit your existing API platform.

[Framework website](https://saga-ai.dev/) · [Example applications and source](https://github.com/MachineWisdomAI/saga-a2ui-examples) · [Build tic-tac-toe with React](docs/build-tic-tac-toe-with-react.md)
Expand Down Expand Up @@ -73,7 +75,7 @@ React and Lit are both supported application paths. Their MCP stacks provide typ
- [Build tic-tac-toe with React](docs/build-tic-tac-toe-with-react.md): build a game in your own app directory with npm packages, then play against Claude or ChatGPT. To try a finished, hosted version first, see the [hosted game and its source](https://github.com/MachineWisdomAI/saga-a2ui-examples#use-the-hosted-game).
- [Build the notes application with Lit](docs/build-notes-with-lit.md): a view composed with the Lit stack, leading into the [action guide](docs/actions.md).

To add the React stack to an application you already have, use the [React integration guide](docs/react-consumers.md). [Ansari Faithful Answers uses the React stack](docs/react-consumers.md#react-in-ansari-faithful-answers). The demo and five of the six generated starters use Lit, and one starter uses React on Hono; choose by framework and the workflow you need, rather than treating template availability as renderer maturity.
To add the React stack to an application you already have, use the [React integration guide](docs/react-consumers.md). [Ansari Faithful Answers uses the React stack](docs/react-consumers.md#react-in-ansari-faithful-answers). The demo and five of the six generated starters use Lit, and one starter uses React on Hono; choose by framework and the workflow you need.

For Hapi, the [integration map](templates/lit-hapi/README.md#existing-hapi-app-register-an-endpoint) shows how to reuse the [bridge](templates/lit-hapi/server/bridge.ts) in your own app, with a registration example, bridge-owned lifecycle handling and the application’s responsibilities.

Expand Down
4 changes: 2 additions & 2 deletions apps/lit-host/e2e/tour.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ test.describe('reading order, limits and links', () => {
'Simulation limit:',
);
await expect(page.getByTestId('tour-limits')).toContainText(
'No protected media, no Patreon access and no playback',
'The tour plays no media.',
);
});

Expand Down Expand Up @@ -316,7 +316,7 @@ test.describe('reading order, limits and links', () => {
await expect(page.locator(`#source-${id} a`)).toHaveCount(1);
}
await expect(page.getByTestId('source-identity')).toContainText(
'unpublished',
'public repository',
);
});

Expand Down
10 changes: 4 additions & 6 deletions demo/lit-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ to type a credential into.

A run against a real host uses that host's supported authentication instead. Give each protected
endpoint your own `OAuthTokenVerifier` (see `templates/lit-node/server/verifier.ts`), do not ship
`demo/lit-node/fixtures`, and put your own ingress host name in `allowedHosts`. This demonstration
has not been run in ChatGPT, Claude or Alexa+, and a local loopback run says nothing about a
remote host's authentication or audio.
`demo/lit-node/fixtures`, and put your own ingress host name in `allowedHosts`.

## What you can do

Expand Down Expand Up @@ -103,6 +101,6 @@ the installed packages, and the views are the application's installed views.

## Limits

Loopback only, in memory, one process. The local host fixture is not an assistant host. No OAuth
flow or registry install is involved, nothing is published or deployed, and the packages are candidate builds of this source
(`@saga-a2ui/lit` and `@saga-a2ui/lit-mcp-stack` are private and unpublished).
The demonstration runs on loopback, in memory, in one process, with the local host fixture standing
in for the assistant host and the development credentials above. Its packages are candidate builds
of this source, bundled into `server.mjs`.
30 changes: 13 additions & 17 deletions demo/tour/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ npm run build:tour # writes apps/lit-host/dist/tour (ignored)

Open `apps/lit-host/dist/tour/index.html` in a browser, or serve that directory from any static
host. Node 22.12 or newer builds it. `tour.json` ties the page to the candidate build and the source
commit its links point at. The repository is public, so those links open for anyone; the built
page's own footer text (in `src/tour.ts`) still says otherwise and is corrected with the next product
change.
commit its links point at. The repository is public, so those links open for anyone.

## What is real and what is simulated

Expand All @@ -32,24 +30,22 @@ change.

`scripts/tour.test.ts` runs the notes application's real server (`createNotesServer`) and the
simulated one through the same situations and requires the same reply from both, so the simulation
cannot drift into saying something the real server does not. That makes the simulation faithful to
the example. It does not make a simulated answer evidence that any server enforces anything.
cannot drift into saying something the real server does not. The simulation stays faithful to the
example.

## Limits, shown beside the interaction they limit

- A simulated session check does not authenticate anyone.
- A simulated denial does not prove that any server enforces anything.
- Local cancellation does not prove that a remote effect was undone.
- The 30 s work, 5 s hook, 3 s operation and 10 s request limits are not exercised here.
- The tour plays no media, reads no Patreon data and offers no protected content. Episode
descriptions and Play need the demonstration's server and are not offered.
- Renderer previews: **Lit** is the full renderer. **React** has bounded evidence (direct action
attachment and the notes application in a local fixture host); it is not renderer parity, and it is
not the React starter (`saga init --a2ui-stack react-mcp --server hono`), which is a separate
pair. Lynx delivery was retired and is not offered. A renderer joins the list in
- The session check, the server's denial and cancellation are simulated in the page, so the tour
shows each outcome exactly as the notes example presents it. The
[demonstration](../lit-node/README.md) runs the same notes example against a real local server
that authenticates the request and enforces the permission.
- The tour covers the notes example. Episode descriptions and protected Play run in the
demonstration's server.
- Renderer previews: **Lit** and **React** both run direct action attachment and the notes
application in a local fixture host. The React starter
(`saga init --a2ui-stack react-mcp --server hono`) is a separate pair. A renderer joins the list in
`src/scenarios.ts` when its preview works.
- The tour is built from packed candidate tarballs of this source, not from registry packages. Nothing
here says the stack packages are on a public registry.
- The tour is built from packed candidate tarballs of this source.

## Files

Expand Down
9 changes: 4 additions & 5 deletions demo/tour/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,11 @@ <h3>Guides</h3>
</section>

<section aria-labelledby="limits-heading">
<h2 id="limits-heading">What this tour does not show</h2>
<h2 id="limits-heading">About this tour</h2>
<ul data-testid="tour-limits">
<li>No real authentication, OAuth flow or identity provider, and no run in ChatGPT, Claude or Alexa+. The host here is a local stand-in, not an assistant host.</li>
<li>No protected media, no Patreon access and no playback. This tour plays nothing.</li>
<li>React has bounded evidence: direct action attachment and the notes application in a local fixture host. It is not renderer parity, and it is not the React starter, which is a separate Hono pair.</li>
<li>The SDK is an unpublished candidate. The packages are private and this page is built from locally packed candidate tarballs, not from a registry.</li>
<li>The host here is a local stand-in for an assistant host, with a simulated server and synthetic accounts.</li>
<li>The tour plays no media. The podcast demonstration (<code>demo/lit-node</code>) runs protected playback on its own local server.</li>
<li>Both renderers run the notes application here: Lit, and React through a React consumer.</li>
</ul>
</section>
</main>
Expand Down
2 changes: 1 addition & 1 deletion demo/tour/src/tour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ for (const anchor of document.querySelectorAll<HTMLAnchorElement>(
}
byTestId('source-identity').textContent =
`Built from candidate ${build.candidateVersion}, source commit ${build.commit.slice(0, 12)}${build.dirty ? ' (the build had uncommitted changes, so these links may not match it)' : ''}. ` +
'The repository is private, so the links open for people who have access to it. The candidate is a local build of the unpublished packages; nothing here says they are on a public registry.';
'The links open the matching source in the public repository.';

// Theme: the system's preference unless the reader chooses.
radios(
Expand Down
Loading
Loading