Skip to content

Mecatl Studio maintainability: design alignment, agent contract, test coverage, app structure, and configuration #1774

Description

@peppescg

User story

As an engineer — and as a coding agent — picking up Mecatl Studio after the in-repo bootstrap
stack has landed, I want the app to look like the approved design, carry its own agent
contract
, be covered by browser and unit proofs, sit in a folder structure that scales
past the skeleton
, and expose one coherent configuration surface, so that Studio is
maintainable by the whole team instead of only by its author.

Companion to #1736. That story brings Studio into the repository as apps/ and ships its
image; this one makes the result maintainable. It does not block #1736's stack (#1746–#1752) —
it starts as that stack lands, axis by axis.

Scope

1. Align Studio UI and design (UX, UI, components, colors, CSS)

2. Agent contract for apps/

  • apps/AGENTS.md (with the repo's CLAUDE.md symlink convention) as the lean correction
    file
    for the TypeScript workspace — in the spirit of the root AGENTS.md, not a second copy
    of the docs: the pnpm-workspace commands, the contracts → committed openapi.json →
    generated-client drift rule, the BFF security invariants (sealed HttpOnly cookies,
    double-submit CSRF, same-origin check, rate limiting with trusted proxy hops, the
    STUDIO_IMAGE=1 / STUDIO_ALLOW_UNAUTHENTICATED=1 refusals), and the standing
    "published @stacklok-oss/mecatl-sdk only, never sdk/typescript" rule.
  • A pointer to it from the root AGENTS.md (the root file stays lean).
  • Skills under .claude/skills/ for the recurring Studio loops — e.g. add a surface
    (contracts schema → BFF route → regenerate client → web feature → proofs) and touch Studio
    configuration
    . Held to the same bar as the existing skills (to-acceptance-plan,
    plan-orchestrate, test-writer).
  • Rules / markdown instructions for the conventions that are currently tribal: TanStack
    file-route layout, feature-folder boundaries, "no fetch outside lib/api-client", the
    Hono route + Zod schema + problem-details shape, and the Biome formatting contract.
  • Acceptance: an agent given "add surface X" follows the contract without reading the tree.

3. Cover the app with e2e and unit tests

  • Browser e2e with Playwright, reusing the conventions already in the repo
    (sdk/typescript/e2e/browser/playwright.config.ts) and the playwright: resolver already
    wired in .actrace.yml, so the proofs are citable from acceptance plans.
  • Journeys: unauthenticated → login → workspace; chat send → streamed run → mid-run controls;
    capability-gated schedules empty state; knowledge inventory; settings; global search and the
    shortcuts reference; connection-lost banner; a rejected CSRF mutation.
  • Unit/component gaps above the BFF suite. test(studio): integration suite over the real SDK against mecated --mock #1767 gives 7 integration tests over the real
    SDK against a spawned mecated --mock, and the bootstrap gives 26 server proofs — but only
    3 web proofs (auth-gate, connection-status-banner, api-client). Bring apps/web to
    real coverage with Vitest + Testing Library as the feature stacks land.
  • CI: a Playwright job (or an extension of the studio job) with cached browsers and
    failure artifacts, offline by default (mock runtime, no live provider, no network).
  • Decide: is there an enforced coverage floor, or are named proofs per acceptance criterion
    the only gate?

4. Rethink the app folder structure

  • The bootstrap layout — apps/{contracts,server,web}, with
    web/src/{components/{shell,ui},features,lib,routes} — was sized for a skeleton. Five
    feature stacks (Studio chat: sessions, streamed runs, controls, chat workspace #1747–Studio global search palette and keyboard-shortcuts reference #1751) land on top of it.
  • Questions to settle: feature-sliced vs layer-first in apps/web; where domain hooks and
    shared state live; whether apps/contracts stays one package or splits schemas from the
    generated client; whether the BFF's routes/ + mecatl/ + auth/ split holds at five
    surfaces; and whether the workspace stays apps/ now that it holds exactly one app.
  • Deliverable: a short structure decision, then the move as one mechanical PR with no
    behavior change
    , so the diff stays reviewable — done before the e2e work lands, so the
    proofs are not written against paths that are about to move.

5. Look at all the configuration

  • apps/.env.example against the real MECATL_* (target) / STUDIO_* (Studio-owned) matrix:
    every variable documented once, with default, required-ness, and the fail-closed behaviour
    (e.g. RFC 9728 discovery when MECATL_RESOURCE_URL is absent).
  • apps/Dockerfile (Chainguard node pinned by digest), apps/docker/mecated.Dockerfile,
    apps/docker-compose.yml, apps/.dockerignore: layer caching, non-root, healthcheck,
    image-only refusals, and who refreshes the digest pin.
  • apps/README.md reconciled with the user-docs/building/deployment/studio.md page (docs(user-docs): Mecatl Studio web UI deployment page #1765) —
    one source of truth, not a drifting duplicate.
  • apps/package.json scripts vs apps/Taskfile.yml vs root task studio:*: one entry point
    per action, no third way to run the same thing.
  • apps/biome.json, tsconfig.base.json, .node-version, .npmrc, the pnpm workspace and
    lockfile policy; and a re-read of the studio CI job and the publish-studio release job
    against whatever the four axes above change.

6. Release and deploy automation

  • Every v* release of mecak8s must produce and roll out the matching Studio UI. Today
    publish-studio runs on the tag with needs: guard only — a sibling of the mecak8s image,
    coupled to nothing, and deployed by nothing; the mecak8s chart does not know Studio exists.
  • Release train: publish-studio joins the ordered train the chart job already relies on
    (needs: [guard, publish-mecak8s], "publish the chart only after its default image tag
    exists"), signed and attested like its siblings. The SDK ordering is the risk to settle —
    Studio builds against the published @stacklok-oss/mecatl-sdk.
  • Deploy surface: Studio Deployment + Service + Ingress in external mode against the in-cluster
    mecak8s Service, off by default, with the image selected by the chart's existing
    digest / tag / v<chart-version> convention so a chart release deploys the matching UI
    with no values edit.
  • Version pins: studio.image.tag joins the release pin set (Chart.yaml version/appVersion,
    image.tag, the cut-release bump list) so a chart can never ship a stale UI.
  • Rollout: GitOps auto-sync, a deploy workflow, or a release-opened values PR — the actual
    "automatic deploy" decision; everything above only makes it possible.

Steps

Delivered as sub-issues. Ordering: contract and configuration first (cheap, unblocks everyone),
structure before tests (so proofs are not written against paths that are about to move),
release/deploy once there is a UI worth shipping. Design alignment is active as
its own stream under #1736.

#1776 supersedes the empty placeholders #1769, #1770, and #1771; #1778 subsumes or hands off
#1772 (README screenshots).

Delivery

Same acceptance-plan spine as #1736, classified per docs/development-process.md at plan time
rather than asserted here. Expected shape: the agent contract and the configuration sweep look
Routine/Cleanup (no behaviour, contract, or interface change); the folder rethink is Bounded
with a structure decision and a no-behaviour-change move; the e2e coverage is Bounded (new
named proofs, reusing the playwright: / vitest: ac-trace resolvers); design alignment is
Bounded per surface where it changes UI alone. #1845 may be Architectural because it
changes the public auth/status boundary;
the release and deploy automation is Architectural (it changes the release artifact set, the
published chart's contract, and the deployment surface).

Open questions and resolved design decisions

  • Design sign-off is resolved: maintainers review desktop/mobile screenshots and the key interaction flow per surface; Studio design review and parity tracking #1779 records completion.
  • Design primitives are resolved for this batch: keep local controls and tokens; no external UI-kit dependency.
  • Playwright in the existing studio CI job or its own? Enforced coverage floor or not?
  • Does the workspace stay apps/, or become studio/?
  • Is Studio part of the mecak8s chart or its own chart, and what rolls the new version out —
    GitOps auto-sync, a deploy workflow, or a values PR?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    WebUIApplies to the WebUI interfacedevexenhancementNew feature or requestux

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions