Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
171 commits
Select commit Hold shift + click to select a range
3d0159f
chore(studio): import Atrium UI (filtered vendor drop)
jtenniswood Aug 18, 2026
ee065e2
chore(studio): correct stray Proprietary license headers
jtenniswood Aug 18, 2026
fd980bf
chore(studio): rebrand and retool (npm, Node 22, daemon-only shims)
jtenniswood Aug 18, 2026
09a1cfc
feat(studio): graft the hardened server tier from feat/studio-module
jtenniswood Aug 18, 2026
1fc6aa2
feat(studio): merge the protocol seam (events, sessions, schedules)
jtenniswood Aug 18, 2026
bfdbf40
feat(studio): daemon-only hooks behind a shared runtime status
jtenniswood Aug 18, 2026
ffdc2c3
feat(studio): wire the five surfaces daemon-first
jtenniswood Aug 18, 2026
46bb75b
test(studio): browser e2e over a fixture daemon
jtenniswood Aug 18, 2026
646cd58
ci(studio): workflow, dependabot, and Taskfile integration
jtenniswood Aug 18, 2026
ffa2e36
docs(studio): ADRs 0228/0229, guides, tracker, llms
jtenniswood Aug 18, 2026
fc91e86
fix(studio): npm-10 lockfile and the audited Next bump
jtenniswood Aug 18, 2026
de1c999
docs: regenerate llms.txt after the readiness-tracker row
jtenniswood Aug 18, 2026
42e1264
feat(studio): settings subpages, identity preferences, empty-state po…
jtenniswood Aug 18, 2026
82c7f0f
fix(studio): re-sync the lockfile under npm 10 and repoint the settin…
jtenniswood Aug 18, 2026
6ab5678
feat(studio): Figma shell redesign — top nav, card surface, right ses…
jtenniswood Aug 18, 2026
b3bc4a3
feat(studio): left-align the conversation column, widen the session l…
jtenniswood Aug 18, 2026
b950173
fix(studio): a draft's first stream survives its own session mint
jtenniswood Aug 18, 2026
5a00650
feat(studio): title spinner while generating, one shared panel width
jtenniswood Aug 18, 2026
01a31c5
feat(studio): darker dark-mode shell gradient, header bar on drafts
jtenniswood Aug 18, 2026
a403521
fix(studio): pin the Taskfile's npm install to npm 10
jtenniswood Aug 18, 2026
9896a47
feat(studio): setting to dock the session list left or right
jtenniswood Aug 18, 2026
f234078
feat(studio): sidebar toggle docks on the header edge nearest the panel
jtenniswood Aug 18, 2026
e8e370c
fix(studio): appease biome's key and hook-dependency rules
jtenniswood Aug 18, 2026
3cb1224
fix(studio): mobile shell — 500px breakpoint everywhere, halved margi…
jtenniswood Aug 19, 2026
8d8d53d
feat(studio): PWA installability for Android and iOS
jtenniswood Aug 19, 2026
a4266eb
feat(studio): mobile interaction round — sheets, threads, swipe actio…
jtenniswood Aug 19, 2026
c7a565e
feat(studio): mobile bottom tab bar + native settings drill-down
jtenniswood Aug 19, 2026
05239b1
feat(studio): chat-style settings subpage header, avatar downscale, l…
jtenniswood Aug 19, 2026
17141cc
feat(studio): native-style settings list, Memory moves into Settings
jtenniswood Aug 19, 2026
bd1da2b
fix(studio): nav pill gap, mobile-only trims
jtenniswood Aug 19, 2026
b20bca9
fix(studio): allow dev-server assets for LAN origins
jtenniswood Aug 19, 2026
6852152
fix(studio): iOS standalone safe areas
jtenniswood Aug 19, 2026
2bb8bbb
style(studio): neutral settings icon squares
jtenniswood Aug 19, 2026
ece69b5
feat(studio): mobile composer — one-line layout, picker bottom sheets
jtenniswood Aug 19, 2026
e77bff2
feat(studio): tab bar yields to the keyboard
jtenniswood Aug 19, 2026
13722f3
fix(studio): kill the iOS launch gap for real, disable pinch-zoom
jtenniswood Aug 19, 2026
2944758
style(studio): full-bleed content card on mobile
jtenniswood Aug 19, 2026
ebe65b0
feat(studio): docked mobile composer — one bar, options in a sheet
jtenniswood Aug 19, 2026
3cfff5d
revert(studio): mobile navigates from the top bar again
jtenniswood Aug 19, 2026
433e521
feat(studio): UI text-size setting
jtenniswood Aug 19, 2026
bf95b60
fix(studio): keyboard resizes the layout viewport on Android
jtenniswood Aug 19, 2026
546e2a2
style(studio): mobile type/icon bump, slimmer bars, options glyph
jtenniswood Aug 19, 2026
37b8732
feat(studio): settings UX round — scale slider, select fields, mobile…
jtenniswood Aug 19, 2026
8d751d2
feat(studio): agent identity page — picture and name, split from Profile
jtenniswood Aug 19, 2026
106c8ef
feat(studio): scroll-to-bottom control in chat
jtenniswood Aug 19, 2026
10979d7
style(studio): slimmer desktop gradient border
jtenniswood Aug 19, 2026
57c9492
style(studio): mobile base font-size up to 18px
jtenniswood Aug 19, 2026
6fa28f8
style(studio): trim the transcript's bottom reserve on mobile
jtenniswood Aug 19, 2026
8bc2c41
feat(studio): pinned-follow auto-scroll in chat
jtenniswood Aug 19, 2026
640782e
feat(studio): chat polish — usage in the menu, activity line, roomier…
jtenniswood Aug 19, 2026
4cd0ea0
style(studio): page titles down to text-3xl on desktop too
jtenniswood Aug 19, 2026
bd159af
fix(studio): interface-scale slider no longer jitters mid-drag
jtenniswood Aug 19, 2026
6e92284
feat(studio): long-press a chat row for its actions on touch
jtenniswood Aug 19, 2026
6265530
feat(studio): draft chat uses the standard composer position
jtenniswood Aug 19, 2026
9a0b8c7
feat(studio): interface scale becomes a − / + stepper
jtenniswood Aug 19, 2026
6be2315
feat(studio): image attachments reach the model; usage is a chat total
jtenniswood Aug 19, 2026
9c95e86
style(studio): biome reflow of the shortened title class strings
jtenniswood Aug 19, 2026
da50dd5
fix(studio): chat row "…" menu shows on hover at every desktop width
jtenniswood Aug 19, 2026
b0f1f84
fix(studio): big and HEIC images re-encode before sending
jtenniswood Aug 19, 2026
9f9cf22
fix(studio): whole-package lint pass
jtenniswood Aug 19, 2026
cb65c25
fix(studio): satisfy knip's dead-code gate
jtenniswood Aug 19, 2026
f6052d4
feat(studio): message queue with steer, edit, and delete
jtenniswood Aug 19, 2026
eb205b6
Merge remote-tracking branch 'origin/main' into feat/studio-mobile
jtenniswood Aug 20, 2026
e532776
feat(server): unary HTTP steer endpoints (steer / steer-cancel)
jtenniswood Aug 20, 2026
a03cf05
feat(studio): steering, threads, mock tour, schedules/skills/settings…
jtenniswood Aug 20, 2026
8dd94b0
chore: ignore Studio-managed local state; regenerate llms.txt
jtenniswood Aug 20, 2026
6a9d4d3
fix(studio): skill dialogs and Manage row polish
jtenniswood Aug 20, 2026
843b102
fix(studio): tighter page gutters; serif greeting on the empty chat
jtenniswood Aug 20, 2026
89745ed
fix(studio): mode menu language + explainers; canvas PDF crash
jtenniswood Aug 20, 2026
2749962
fix(studio): avatar removal is a hover × on the picture
jtenniswood Aug 20, 2026
11430cb
refactor(studio): memory list as a table; detail as a dedicated page
jtenniswood Aug 20, 2026
1271342
fix(studio): appearance stepper width; agent name above picture
jtenniswood Aug 20, 2026
a4cde73
feat(studio): "You" settings section with display name; detail-page p…
jtenniswood Aug 20, 2026
becd408
fix(studio): Messages settings row matches Appearance; concise subtitle
jtenniswood Aug 20, 2026
4f9b2d0
feat(studio): provider management — key health, test, remove, guided add
jtenniswood Aug 20, 2026
181a247
feat(studio): client half of the runtime active-provider switch
jtenniswood Aug 20, 2026
d9eee78
fix(studio): identity cards align; add-provider dialog reads as 3 steps
jtenniswood Aug 20, 2026
fba775b
fix(studio): opaque composer banners; search input clears its close b…
jtenniswood Aug 20, 2026
6c30188
refactor(studio): every settings page speaks the Appearance grammar
jtenniswood Aug 20, 2026
e7a59de
feat(studio): controller route for the live provider switch
jtenniswood Aug 20, 2026
fcb79de
fix(studio): thinking dots actually bounce
jtenniswood Aug 20, 2026
11a3244
fix(studio): quoted user messages render as quotes; mobile thread scr…
jtenniswood Aug 20, 2026
17d3e9a
fix(studio): queued messages are one opaque group with a kebab per row
jtenniswood Aug 20, 2026
4f2f607
feat(studio): real model picker; dialog & gateway polish; quote/threa…
jtenniswood Aug 20, 2026
8cfcf44
fix(studio): steer replies render in order; one clean provider list
jtenniswood Aug 20, 2026
0b6af4b
fix(studio): steer text lands straight in the chat; approval panel sa…
jtenniswood Aug 20, 2026
edf5345
feat(studio): files a chat writes render as openable attachments
jtenniswood Aug 20, 2026
fbcd886
fix(studio): produced-file chips read the daemon's real Write arg key
jtenniswood Aug 20, 2026
37e9230
fix(studio): router model pickers offer the daemon's whole inventory
jtenniswood Aug 20, 2026
b9d8b72
refactor(studio): Appearance becomes Personalize and absorbs Messages
jtenniswood Aug 20, 2026
2343ea5
refactor(studio): Personalize absorbs notifications with a bell test
jtenniswood Aug 20, 2026
63f6a23
feat(studio): progressive model router; uniform Personalize controls
jtenniswood Aug 20, 2026
e22386d
fix(studio): the Enter-behavior row is labeled "Message queuing"
jtenniswood Aug 20, 2026
f9d59ec
fix(studio): "Your name" subtitle asks what the agent should call you
jtenniswood Aug 20, 2026
4e39bba
feat(studio): attachment previews everywhere, consistent chips
jtenniswood Aug 20, 2026
74ecaa2
fix(studio): thinking indicator aligns with the message grid
jtenniswood Aug 20, 2026
32065cc
feat(studio): attachments survive refreshes; compaction reads as a di…
jtenniswood Aug 20, 2026
7f1b0c2
fix(studio): thread replies drop the redundant root quote
jtenniswood Aug 20, 2026
9692b56
feat(studio): thread panel menu (tools toggle, open as full chat); sk…
jtenniswood Aug 20, 2026
23a0cab
fix(studio): mock tour drops its canned thread — threads are real now
jtenniswood Aug 20, 2026
ca0ec3e
fix(studio): attachment chips share one fixed height
jtenniswood Aug 20, 2026
942f7c9
refactor(studio): lean schedule form; markdown lists match body rhythm
jtenniswood Aug 20, 2026
987f87b
feat(studio): two-step skill creation; quieter router and provider cards
jtenniswood Aug 20, 2026
734a587
feat(studio): skill detail browses folder skills; tighter page bottoms
jtenniswood Aug 20, 2026
a0ad73f
Merge origin/main into feat/studio-atrium
jtenniswood Aug 20, 2026
09f507d
feat(studio): tool-activity failures, drill-down panel, durable toggl…
jtenniswood Aug 20, 2026
bb698d6
feat(studio): skill uploads take zips and folders, create immediately
jtenniswood Aug 20, 2026
0bfe3c8
polish(studio): tighter page gutters, roomier form labels, inline SKI…
jtenniswood Aug 20, 2026
6acc3ea
fix(studio): regenerate package-lock with npm 10 for CI
jtenniswood Aug 20, 2026
475d67f
fix(studio): e2e asserts on the visible instance of dual-rendered rows
jtenniswood Aug 20, 2026
d0349ee
feat(studio): Labs mock Projects section in the chat sidebar
jtenniswood Aug 20, 2026
55bdd46
feat(studio): mock projects lead the sidebar; green marks the selection
jtenniswood Aug 20, 2026
7efe1ee
fix(studio): one green row in mock projects; rows match chat heights
jtenniswood Aug 20, 2026
724c5da
fix(studio): mock project chats never claim selection; standard row menu
jtenniswood Aug 20, 2026
7eb0790
fix(studio): sidebar toggle closes an open canvas in the right slot
jtenniswood Aug 20, 2026
2105130
fix(studio): one Show-more expander that opens everything
jtenniswood Aug 20, 2026
eaaf28a
polish(studio): the sidebar expander reads plain Show more
jtenniswood Aug 20, 2026
2fef33f
fix(studio): PDF previews render; model picks work and switch mid-chat
jtenniswood Aug 20, 2026
5554003
fix(studio): the composer never steals focus on mobile
jtenniswood Aug 21, 2026
d24e5ab
Merge origin/main into feat/studio-mobile (daemon catch-up step 0)
jtenniswood Sep 1, 2026
2f90327
polish(studio): sidebar reads Chat History; Labs drops its subtitle
jtenniswood Sep 1, 2026
fc24495
feat(studio): typed daemon errors and compatibility feature detection
jtenniswood Sep 1, 2026
e2dea5d
feat(server,studio): HTTP steer aligned to ADR 0252; authority-aware …
jtenniswood Sep 1, 2026
8c140d1
feat(studio): custom gateway providers; controller rides the ready file
jtenniswood Sep 1, 2026
e8d3d28
feat(studio): live re-attach via the durable session watch; run identity
jtenniswood Sep 1, 2026
dda5d54
feat(studio): learning review, learned skills, dream review, storage …
jtenniswood Sep 1, 2026
29540fe
feat(studio): About-this-daemon card off the safe identity probe
jtenniswood Sep 1, 2026
8adb1af
feat(studio): base-URL overrides for built-in providers in the add flow
jtenniswood Sep 1, 2026
6294ae5
feat(studio): server-tier OIDC login for external-mode daemons
jtenniswood Sep 1, 2026
3f5419c
feat(studio): context meter + compact, true retry, strict multimodal
jtenniswood Sep 1, 2026
c31098a
docs(studio): rule 2 covers server-assigned workspaces; ready-file go…
jtenniswood Sep 1, 2026
b4407f3
feat(studio): Debug with AI, title provenance, enriched agent roster
jtenniswood Sep 1, 2026
b33b3ff
fix(ci): knip dead code, tidy go.mod, clean-tree llms.txt regen
jtenniswood Sep 1, 2026
e4fbe3a
chore(studio): ignore the controller's .scratch runtime state
jtenniswood Sep 2, 2026
7818623
Merge remote-tracking branch 'origin/main' into feat/studio-mobile
jtenniswood Sep 2, 2026
4cf84d8
Merge origin/main into feat/studio-mobile
jtenniswood Sep 15, 2026
4d40bcf
feat(studio,sdk): route every Studio daemon capability through the Ty…
jtenniswood Sep 15, 2026
be52399
Merge origin/main into feat/webui
jtenniswood Sep 15, 2026
aa5407a
test(studio): make the e2e fixture serve every route its capabilities…
jtenniswood Sep 15, 2026
b95f44c
fix(studio): resync the lockfile with SDK 0.2.0 and clear the audit gate
jtenniswood Sep 15, 2026
a627a57
feat(sdk): type the remaining daemon routes — MCP authorization, conn…
jtenniswood Sep 16, 2026
ba87b54
feat(studio): parity wave 0 — posture, queue, fleet, stats, help
jtenniswood Sep 16, 2026
35d1230
feat(studio): parity wave 1 — approvals, retry, delegation, defaults,…
jtenniswood Sep 16, 2026
6f321dc
feat(studio): parity wave 2 — agents panel, built-ins, storage mainte…
jtenniswood Sep 16, 2026
acce14b
feat(studio): parity wave 3 — approvals, effort, cancel-child, daemon…
jtenniswood Sep 16, 2026
b83dc16
Merge origin/main into feat/webui
jtenniswood Sep 16, 2026
a24cc8c
docs: renumber the Studio ADRs to 0347/0348
jtenniswood Sep 16, 2026
193a921
feat(studio): parity wave 4 — plan review, attachments, keymap, picker
jtenniswood Sep 16, 2026
81059d8
feat(studio): parity wave 5 — debug MCP, paste, worktrees, perf, enro…
jtenniswood Sep 16, 2026
317af47
feat(studio): parity wave 6 — trust prompt, auth recovery, palettes, …
jtenniswood Sep 17, 2026
29877b3
feat(studio): parity wave 7 — mode cycle, tool tiers, sessions, help
jtenniswood Sep 17, 2026
87043ac
feat(studio): parity wave 8 — approvals, status line, MCP panel
jtenniswood Sep 17, 2026
8a8cf51
feat(studio): parity wave 9 — hooks, deep links, row actions, MCP pic…
jtenniswood Sep 17, 2026
b093b71
feat(studio): parity wave 10 — welcome, soul, workspace, preferences
jtenniswood Sep 17, 2026
11dd7ab
feat(studio): parity wave 11 — composer rail, tool profile, review po…
jtenniswood Sep 17, 2026
bd5bea2
feat(studio): parity wave 12 — memory indicator, MCP tool titles, per…
jtenniswood Sep 17, 2026
ad8461f
feat(studio): parity wave 13 — daemon options, skill change notices
jtenniswood Sep 17, 2026
0412c16
fix(studio): parity program final verification fixes
jtenniswood Sep 17, 2026
5c71173
feat(sdk,studio): close parity program follow-ups
jtenniswood Sep 17, 2026
55bfc5f
feat(studio): simplify the UI for non-technical users
jtenniswood Sep 17, 2026
0cfabdd
feat(studio): folders for chats in the sidebar
jtenniswood Sep 17, 2026
f267d2d
feat(studio): file a chat into a folder from the touch sheet
jtenniswood Sep 17, 2026
9e19522
feat(studio): plain-language settings for non-technical users
jtenniswood Sep 17, 2026
25d2c1a
feat(studio): shorter Agent behaviour copy
jtenniswood Sep 17, 2026
1dc11e0
feat(studio): every button is pill-shaped
jtenniswood Sep 17, 2026
9ccb929
feat(studio): primary buttons use the brand green
jtenniswood Sep 17, 2026
0ad948f
feat(studio): instant-apply switches, own pills for Tools and Safety,…
jtenniswood Sep 17, 2026
05a8242
feat(studio): drop the sidebar storage link, the effort note and the …
jtenniswood Sep 17, 2026
8010126
feat(studio): context pill in the composer bar; Yolo warning under Sa…
jtenniswood Sep 17, 2026
e2bbb62
feat(studio): drop the Project trust row; "Mode" label on the mode pill
jtenniswood Sep 17, 2026
dd480aa
feat(studio): drop the composer's context pill and the Skills empty-s…
jtenniswood Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,19 @@ updates:
update-types:
- minor
- patch

# Studio (the Node web client) — npm.
- package-ecosystem: npm
directory: "/studio"
schedule:
interval: weekly
open-pull-requests-limit: 5
commit-message:
prefix: "chore(deps)"
labels:
- dependencies
groups:
npm-minor-patch:
update-types:
- minor
- patch
122 changes: 122 additions & 0 deletions .github/workflows/studio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Studio

on:
pull_request:
paths:
- "studio/**"
- "sdk/typescript/**"
- ".github/workflows/studio.yml"
push:
branches: [main]
paths:
- "studio/**"
- "sdk/typescript/**"
- ".github/workflows/studio.yml"

permissions:
contents: read

jobs:
checks:
name: Build, test, lint, typecheck, audit
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Studio depends on the TypeScript SDK as `file:../sdk/typescript`; npm
# links the checkout without building it, so the SDK is built first with
# its own toolchain (pnpm, pinned exactly as ci.yml's SDK job pins it).
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
run_install: false

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: studio/.nvmrc
cache: npm
cache-dependency-path: studio/package-lock.json

- uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0

- name: Build the TypeScript SDK
run: |
task sdk:install
task sdk:build

# No package in the tree needs install scripts (Next/sharp ship prebuilt
# binaries), so scripts stay off — supply-chain surface CI never runs.
- name: Install
working-directory: studio
run: npm ci --ignore-scripts

- name: Lint, typecheck, dead-code
working-directory: studio
run: |
npm run lint
npm run typecheck
npm run knip

- name: Unit tests
working-directory: studio
run: npx vitest run

- name: Build + hermetic server-tier suite
working-directory: studio
run: npm run test:server

- name: Audit
working-directory: studio
run: npm audit --audit-level=high

- name: License headers
run: |
if git grep -l "SPDX-License-Identifier: Proprietary" -- studio/; then
echo "Proprietary SPDX headers are not allowed in studio/" >&2
exit 1
fi

# Browser smoke over the real proxy tier against the fixture daemon.
# Separate job so a browser-infra flake never masks the checks above.
e2e:
name: Playwright (fixture daemon)
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Studio depends on the TypeScript SDK as `file:../sdk/typescript`; npm
# links the checkout without building it, so the SDK is built first with
# its own toolchain (pnpm, pinned exactly as ci.yml's SDK job pins it).
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
run_install: false

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: studio/.nvmrc
cache: npm
cache-dependency-path: studio/package-lock.json

- uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0

- name: Build the TypeScript SDK
run: |
task sdk:install
task sdk:build

- name: Install
working-directory: studio
run: |
npm ci --ignore-scripts
npx playwright install --with-deps chromium

- name: Build and test
working-directory: studio
run: npm run test:e2e
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ coverage.*
# Personal, local-only Claude Code instructions and running-state notes
/CLAUDE.local.md
/HANDOFF.md

# Studio managed-mode local state (controller-pinned skills/memory dirs).
/.mecatl/

# Ad-hoc local attachment drops.
/attachments/
6 changes: 6 additions & 0 deletions .matlatlignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ user-docs/
website/AGENTS.md
website/CLAUDE.md

# Studio's managed-mode working state (the controller pins the project skills
# and memory dirs here) and ad-hoc local attachment drops — machine-local
# state, not documentation. CI checkouts never contain them; ignoring them
# keeps local `check`/`index` runs byte-identical to CI's.
/.mecatl/
/attachments/
# API Extractor reports are review artifacts, not navigational documentation.
# Exclude both the committed reports and their ignored comparison copies.
sdk/typescript/etc/*.api.md
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ the opt-in `provider/*` submodules (ADR 0093), and the root module all move in l
- `contracts/proto/mecatl/v1/` — gRPC contract (source of truth); `contracts/proto/mecatl/driver/v1/` — the driver protocol (SessionStoreService/MemoryStoreService stores; SkillSourceService/SoulSourceService/AgentSourceService/CommandSourceService content sources) a remote driver process implements; `contracts/gen/` is generated, **never hand-edit**.
- `cmd/mecated/` — standalone server (composition root): flags, TLS/auth/rate-limit, HTTP + metrics listeners. `cmd/mecademo/` — the offline demo. `cmd/mecatequi/` — single-shot HEADLESS composition root (peer of mecademo over `app.Build`): one prompt → a git-diff patch + a JSON Summary + an optional JSONL log + an exit code. It is **FORGE-AGNOSTIC** — knows nothing about GitHub; the glue that turns an issue into a PR lives ONLY in `.github/` + shell, NEVER the binary or `engine/`, and keeps a **split-privilege token boundary** (the agent job holds NO GitHub write token; the publish job runs NO agent code, applies the patch as DATA). See `docs/adr/0028-mecatequi.md`. `cmd/mecak8s/` — storage-free k8s-native agent (ADR 0048), a thin peer of mecated that composes `app.Build` with k8s-native defaults (Redis store + k8s lease + drain gate); no PVC, no local state — state is a managed service (Redis + k8s API server). The four real-provider mains share credential/base-URL wiring via `internal/cliconfig`.
- `cmd/mecatui/` — optional gRPC **client** TUI; by default hosts a `mecated` in-process over a UNIX socket. `ui`/`theme`/`client` import no `engine/...` or `internal/...` and no proto directly — they render from relayed proto `Event`s. See `docs/tui.md`.
- `studio/` — the web client: a Next.js **Node module**, never a Go module (not in `go.work`, the layering DAG, depguard, or api-compat). A CLIENT like mecatui, consuming the daemon EXCLUSIVELY through the TypeScript SDK (`@stacklok-oss/mecatl-sdk`, `sdk/typescript`, a `file:` dependency built before Studio installs) pointed at Studio's own same-origin `/api/mecatl` proxy, which holds the credential and injects auth ONLY (placement is server-owned, ADR 0291 — no workspace injection); controller calls (`/api/mecatl-control`) stay Studio-owned; daemon-only (an unreachable daemon renders offline, never demo data). Commands run via `task studio:*` (npm underneath). **A breaking HTTP/SSE wire change owes a Studio update in the same PR.** See ADR 0347/0348 + `studio/CLAUDE.md`.
- `perf/` — the OFFLINE scenario perf harness (perf-tracking Phase 2, `task perf:scenarios`, NOT part of `task test`): `perf/kpi` (stdlib-ONLY KPI capture — `ScenarioResult`/`Capture`/`/proc` RSS sampler; never imports `engine/...` or `internal/...`) + `perf/scenarios` (external-test `testing.B` whole-loop benchmarks over `engine/...` + `engine/adapter/*`, never `internal/...`). The TUI scrollback render bench lives in `cmd/mecatui/ui/scrollback_bench_test.go` (perf/kpi imported in the `_test` file only). `perf/cmd/perfconvert` (Phase 3; stdlib + `perf/kpi` only) reshapes the scenario JSON into the two github-action-benchmark suites the CI gate consumes; `perf/cmd/benchtrend` (stdlib only, tested, FAIL-CLOSED) median-aggregates Go benchmark samples and compacts the commit-keyed dashboard history; and `perf/cmd/allocsgate` (stdlib only, tested, FAIL-CLOSED) is the deterministic allocs/op gate over `task bench` — the gate DECISION (benchstat is the local human A/B tool only, never the CI gate); the gate is `.github/workflows/perf.yml` (split: allocsgate over `task bench` + github-action-benchmark over the scenarios; PR fails-but-never-pushes, main pushes the `gh-pages` trend store). See `docs/adr/0019-perf-tracking.md`.

## The layering rule (the thing to get right)
Expand Down
3 changes: 3 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ includes:
site:
taskfile: website/Taskfile.yml
dir: website
studio:
taskfile: studio/Taskfile.yml
dir: studio
sdk:
taskfile: sdk/typescript/Taskfile.yml
dir: sdk/typescript
Expand Down
1 change: 1 addition & 0 deletions cmd/mecated/helpmeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ var flagMetaByFlag = map[string]flagMeta{

// ── Storage (both) ───────────────────────────────────────────────────
"store-dir": {group: groupStorage, common: true, acp: acpInclude},
"local-storage-management": {group: groupStorage, common: false, acp: acpExclude},
"memory-dir": {group: groupStorage, common: true, acp: acpInclude},
"memory-consolidate-interval": {group: groupStorage, common: false, acp: acpInclude},
"child-retention": {group: groupStorage, common: false, acp: acpInclude},
Expand Down
7 changes: 7 additions & 0 deletions cmd/mecated/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ type config struct {
// deployment where clients drive runs but never answer permission prompts — it
// is what makes --subagent-ask-reviewer actually engage.
headless bool
// localStorageManagement grants the private single-user storage
// management surface (health / clean-up) to unauthenticated-principal
// callers — the embedded-server grant, for a loopback daemon a trusted
// supervisor (Studio's controller) spawns. Refused with OIDC ownership.
localStorageManagement bool

// Skills self-improvement loop (opt-in): when skillsDraftDir is non-empty the
// writable SkillDraft tool is registered, writing model-authored candidate
Expand Down Expand Up @@ -1322,6 +1327,7 @@ func appConfig(cfg config, sink port.EventSink, recorder port.ToolCallRecorder,
// Headless is explicit deployment identity. The posture ladder raises
// workspace trust only when this is false.
Headless: cfg.headless,
LocalStorageManagement: cfg.localStorageManagement,
Sink: sink,
ToolCallRecorder: recorder,
MetricsRoleScoper: roleScoper,
Expand Down Expand Up @@ -1793,6 +1799,7 @@ func parseFlagsModeOut(mode commandMode, argv []string, out io.Writer) (*flag.Fl
fs.IntVar(&cfg.subagentAskReviewerMaxDenies, "subagent-ask-reviewer-max-denies", agent.DefaultAskReviewMaxDenies, "circuit breaker for --subagent-ask-reviewer: after this many CONSECUTIVE non-allow reviewer outcomes (denies/errors/timeouts) in one run, further asks skip the reviewer and fall through to the plain auto-deny; an allow resets the count. <=0 uses the default (3)")
fs.StringVar(&cfg.subagentAskReviewerPolicyFile, "subagent-ask-reviewer-policy", "", "path to a TRUSTED policy rubric file for --subagent-ask-reviewer; its CONTENT replaces the built-in read-only/verification rubric the reviewer applies. Empty keeps the built-in rubric. Read once at startup; an unreadable file FAILS STARTUP")
fs.BoolVar(&cfg.subagentModelRouter, "subagent-model-router", false, "Semantic model router KILL-SWITCH (ADR 0042, superseding 0031's enable model): the router is ENABLED by configuring a `models.router:` category taxonomy in the OPERATOR-TIER user-global settings.yaml (the guardrails-parity enable model — configure = enable), NOT by this flag. Pass --subagent-model-router=false to force the router OFF despite a taxonomy (the kill-switch; also expressible as models.router.disabled: true in YAML). When ENABLED, a tiny one-turn classifier (on the `router` model slot) reads each plain Subagent delegation's task prompt + the operator taxonomy and picks the child's model BEFORE the child is minted (decide-once, same-provider; only for a plain delegation — no per-call model/agent, no fork/resume). FAIL-SOFT: any classifier failure, unknown category, or the per-run breaker (3 consecutive misses) inherits the default model")
fs.BoolVar(&cfg.localStorageManagement, "local-storage-management", false, "grant the storage management surface (GET /v1/storage/health, the clean-up plan/apply routes; advertised as capabilities.storage_health / storage_cleanup) to callers with no OIDC principal — the private single-user grant the embedded mecatui server has, for a LOOPBACK daemon a trusted supervisor spawns (Studio's controller passes it). Refused at startup together with --auth-oidc ownership enforcement; storage_management.principals in settings.yaml is the multi-tenant alternative. DEFAULT off")
fs.BoolVar(&cfg.headless, "headless", false, "run NON-interactive: declare that clients drive sessions but never answer permission prompts (autonomous / CI deployments). A child subagent/member/branch permission ask is then NOT surfaced to the client (nobody would answer it — it would park until run-end) but resolved by the auto-deny path / the opt-in --subagent-ask-reviewer. DEFAULT off: a normal mecated serving an interactive client (mecatui, an IDE) surfaces asks for a human. Setting --subagent-ask-reviewer WITHOUT --headless has no effect (asks surface to the client instead) — a startup WARNING says so")
fs.BoolVar(&cfg.planModeAutoApprove, "plan-mode-auto-approve", false, "OPT-IN autonomous plan approval (issue #206 Wave 6a): when a plan-mode run ends HEADLESS (no human to review), auto-approve the plan via ApprovePlan(ModeDefault) instead of leaving it parked. This is a deliberate autonomous-approval capability — an operator deployment decision, NEVER load-bearing for safety. It does NOT fire when interactive (a human can approve), NOT in non-plan modes, NOT for non-plan asks. DEFAULT off: a headless plan ask is auto-denied. Requires --headless to engage (an interactive deployment surfaces the plan to the human). A LOUD diagnostic (plan_mode_auto_approve: ON (NO HUMAN REVIEW)) is emitted at startup")
fs.StringVar(&cfg.guardrailsModel, "guardrails-model", "", "GUARDRAILS (issue #27): model id or --model-alias of a tool-less checker that inspects OUTBOUND tool-call args (PreToolUse, data exfil) and INBOUND tool results (PostToolUse, prompt injection) and enforces a verdict per the operator-tier `guardrails:` rule list. Configuring a model here OR via a bound `guardrail` model slot (--model-slot guardrail=… / models.slots.guardrail) ENABLES guardrails (configure = enable, the router-parity model of ADR 0042; see ADR 0046) — empty + no slot disables them. A value that does not resolve to a usable model id FAILS STARTUP. A bound `guardrail` slot SUPERSEDES this flag's model when both are set (this flag then supplies only the enable gate). The RULE LIST + cost knobs live in the user-global settings.yaml `guardrails:` subtree (operator-tier ONLY — a project repo cannot configure or weaken a checker); --guardrails-model overrides the YAML model")
Expand Down
Loading