938 Commits
Author SHA1 Message Date
Juan DenisandClaude Opus 5 7d477889e1 fix(walkthroughs): give the blue tone its own colour
`is-blue` resolved to var(--cyan), making it pixel-identical to `is-cyan`
while Walkthrough Studio offers both in its tone dropdown. The theme defines
no --blue token, so point it at --accent, the one remaining distinct hue
among the tones on offer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Opus 5 c181e72793 fix(walkthrough-studio): select the appended step from one snapshot
addStep() appended through a functional setDraft but then selected with
setStepIndex(draft.steps.length), reading the closed-over render snapshot.
The two can disagree under fast interaction, selecting the wrong step or an
index past the end of the list.

Build the list and derive the index from the same snapshot so they cannot
drift apart. Applied to the builtin-extensions source and the bundled copy
together; sync-builtin-frontends --check keeps them identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Opus 5 4beb439fa3 fix(walkthroughs): only the current step may complete on a signal
The signal handler searched the whole step list for a matching signal and
completed whichever step it found. These signals are ordinary product events
-- running a monitor check, creating a service -- so a later step's signal
fires readily while an earlier step is still current, marking it done out of
order and skipping every step in between.

Scope the match to currentStep, which is what the route effect directly above
already does. Normalization flattens an explicit `completion` block onto the
step (normalized.signal), so this covers both spellings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Fable 5 ef2175d533 feat(i18n): translate walkthrough + studio backlog into all 16 locales
Migrates existing translations onto the consolidated common.* keys and
fills the ~399-key backlog (walkthrough guides, Walkthrough Studio, and
older gaps) in ar, bn, de, es, fr, id, it, ko, pl, pt, ru, th, tr, vi,
zh-Hans, zh-Hant. check-i18n: 6420 keys, 16 locales, no orphans or
placeholder drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 23:52:55 -04:00
Juan DenisandClaude Fable 5 d3f6f29ed6 refactor(i18n): consolidate duplicate strings into common.* keys
Duplicate page-scoped keys (Title, Duration, Publish, Live preview,
Move up/down) and Walkthrough Studio strings now reuse common.labels/
common.actions instead of re-declaring identical English text.
en.json regenerated: 6430 -> 6420 keys.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 23:52:49 -04:00
Juan Denis 3a34358ae1 feat: add Walkthrough Studio builtin extension
Visual authoring tool for walkthroughs: create and reorder steps, pick
highlighted UI targets, choose completion modes (route, signal, manual,
check), validate against the shared schema, preview in a live dock,
publish to the server library, and import/export JSON or copy an
extension contribution block. The Studio dogfoods the new system by
declaring its own getting-started walkthrough in its manifest.
2026-08-31 23:14:50 -04:00
Juan Denis 3708227d0e feat(frontend): dynamic walkthrough registry and SDK support
WalkthroughContext now merges built-in walkthroughs with extension
contributions and server-persisted custom guides through a shared
registry, so enabling or disabling an extension adds or removes its
guides at runtime. Adds the walkthrough contribution type to the plugin
SDK (with TypeScript types and vendor shim), Studio API methods, and
i18n strings.
2026-08-31 23:14:41 -04:00
Juan Denis b44f2439f9 feat: add optional walkthrough guides 2026-08-31 22:36:14 -04:00
Juan DenisandClaude Fable 5 27e6c0ba9a fix(i18n): prune the recycle-bin header keys the refactor orphaned
5bfb0f67 dropped the tab-local header but did not regenerate en.json,
so the lint gate failed on catalog drift. Regenerate en.json and delete
the three now-unused recycleBinTab keys from every locale bundle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 20:55:35 -04:00
Juan DenisandClaude Fable 5 5bfb0f6747 refactor(recycle-bin): drop the page-local header
The tab-local title, retention blurb and standalone Refresh button
duplicated chrome the grid already provides (Refresh data lives in the
grid tools menu; per-row 'purges in Xd' carries the retention signal).
The page now leads with the view picker and table like other grids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 19:35:53 -04:00
Juan DenisandClaude Fable 5 fc89a979ef i18n: translate panel self-update strings in all 15 remaining locales
The self-update feature commit added the 10 new app.aboutTab keys to en
and es only; every other locale fell back to English in an otherwise
fully translated About tab. Add ar, bn, de, fr, id, it, ko, pl, pt, ru,
th, tr, vi, zh-Hans and zh-Hant, matching each file's existing register
(Sie/vous/formal).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 08:17:47 -04:00
Juan DenisandClaude Fable 5 160bf6dab7 feat(panel): one-click self-update from the About tab
The About tab could only detect a new release and link to it; applying the
update meant SSH and scripts/update.sh. Wire that script to the UI:

- panel_update_service launches update.sh via systemd-run in its own
  transient unit — a plain subprocess child would be killed when the
  updater restarts the panel's own systemd unit. Status is stateless
  (transient-unit state + the updater's own update-*.log) so it survives
  the mid-update backend restart.
- Capability gates keep the button honest: root systemd installs only.
  Docker installs get the docker compose pull instructions; dev servers
  and hosts without systemd-run get a reason instead of a button.
- GET/POST /api/v1/system/update (admin_required, confirm-gated,
  audited). API surface doc regenerated.
- About tab gains Update Now with inline confirm, live log tail while
  the update runs, a restarting phase that tolerates the panel being
  briefly unreachable, and success/rollback/timeout outcomes. New
  aboutTab locale keys in en + es.

The heavy lifting (blue/green switch, migrations, health check,
automatic rollback) stays in update.sh, which is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 08:09:52 -04:00
Juan DenisandClaude Opus 5 b764418b09 fix(status): re-sync the pre-bundled frontend manifest
30b780f4 corrected the serverkit-status description in two of its three
copies. The extension's manifest also exists at
frontend/src/plugins/serverkit-status/plugin.json, which is generated from
the builtin-extensions/ source by scripts/sync-builtin-frontends.mjs --
so Extensions CI went red on the builtin-frontend drift check, and
bump-version failed downstream of it rather than on its own.

Regenerated with the sync script rather than hand-edited; the diff is the
one description line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 00:44:04 -04:00
Juan DenisandClaude Opus 5 12c863b230 fix(templates): repo deploys send the build inputs the template declares
The deploy drawer posted only url/branch/app_type/build_method/port, so a
repo template's `build_command`, `start_command` and `dockerfile_path`
were decorative — declared in the YAML, read by nobody. The endpoint has
always accepted custom_build_cmd / custom_start_cmd / dockerfile_path;
only the caller was dropping them.

The visible cost was nixpacks builds: with no start command it falls back
to `npm start`, so any repo whose package.json has no `start` script
produced an image that built fine and could not boot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:47:14 -04:00
Juan Denis 37cf8b6e84 Merge plan 52 cutover: the published extensions leave the tree
localkit, email, cloudflare-ops and git are now published, signed and in
the registry index, so the panel no longer needs in-tree copies of them.
This removes ~29k lines that existed in two places at once and flips the
bundled registry so they install from the catalog like any other
extension.

Unblocked by the operator publishing all nine repos (2026-08-30); the two
registry-mirror tests that plan 83 expected to stay red now pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

# Conflicts:
#	builtin-extensions/serverkit-cloudflare-ops/frontend/components/StoragePanel.jsx
#	frontend/src/plugins/serverkit-cloudflare-ops/components/StoragePanel.jsx
2026-08-30 22:13:01 -04:00
Juan DenisandClaude Fable 5 cea1770562 fix(review): posture installs survive unchecked overlaps; translatable storage empty-states
PR #121 review follow-ups. The setup summary de-duplicated the install
queue with recommendations winning, so a security-posture extension
that also appeared as an unchecked recommendation was silently dropped
— the posture half now wins regardless of checkbox state. The
Cloudflare storage panel templated English around a translated title
(`No ${title.toLowerCase()} yet.`); each section now passes a fully
translated emptyHint instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 20:25:17 -04:00
Juan Denis d764f50809 Merge branch 'dev' into feature/plan52-cutover
# Conflicts:
#	backend/app/data/registry_index.json
#	frontend/src/plugins/serverkit-git/plugin.json
2026-08-30 16:24:27 -04:00
Juan DenisandClaude Fable 5 91d464f871 chore: re-sync the pre-bundled serverkit-git plugin.json
The plan 52 Phase 6 git split updated the source manifest under
builtin-extensions/ (shell permission, entry_point, url_prefix,
min_panel_version) without running sync-builtin-frontends.mjs, so the
Extensions CI drift check went red on the next PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 14:00:50 -04:00
Juan DenisandClaude Fable 5 d3e3564c7d fix(templates): surface validate-install errors in the deploy drawer
The API client throws on any non-2xx, so a 400 from validate-install
never reached the `!validation.valid` branch — and the catch only read
`err.data.error` (singular), while this endpoint returns an `errors`
array. The operator saw "Request failed (400)" instead of the actual
reason (e.g. the app name being reserved by the Recycle Bin).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 03:20:27 -04:00
Juan DenisandClaude Fable 5 02967b0547 cutover(git): serverkit-git leaves the tree (plan 52 Phase 6)
builtin-extensions/serverkit-git + the tracked frontend live copy removed;
the bundled registry entry flips to bundled:false at v1.1.0 (the version
that carries the Gitea backend) with the local zip's sha256; the gated
auto-install (_gitea_was_used) moves to REGISTRY_GATED_SLUGS, leaving
GATED_BUILTIN_SLUGS empty with the machinery intact.

i18n: en.json regenerated (the app.git/app.email/app.cloudflare* namespaces
ride with their extensions, which carry en+es bundles; other languages are
recoverable from git history), all locales pruned, intl-door ratchet
tightens 123 -> 115.

Expected red on this branch: the two registry-mirror tests, until the four
repos are published + signed + re-vendored (see docs/plans/83).

OPERATOR: publish jhd3197/serverkit-git, sign, sync-registry-index.sh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 14:53:27 -04:00
Juan DenisandClaude Fable 5 665d6775e4 cutover(cloudflare-ops): the last in-place flagship leaves the tree (plan 52 Phase 2)
builtin-extensions/serverkit-cloudflare-ops + the tracked frontend live
copy removed; FLAGSHIP_SLUGS is now empty (machinery kept);
plugins-manifest.json empties; the bundled registry entry flips to
bundled:false with the local zip's sha256. cloudflare_ops_bridge resolves
the copy-installed package FIRST so a registry install works without the
builtin registration path.

Tests: new conftest.mount_sibling_extension mirrors a real install from
the sibling checkout (the _wp_support.ensure_plugin analogue) and a
cf_extension fixture forces a private app; the zone-settings and round2
suites mount it autouse (74/74 green), the extraction suite pins the
lean-panel shape, and the flagship-era onboarding tests prove the
machinery with a fabricated member instead.

OPERATOR: publish jhd3197/serverkit-cloudflare-ops, sign,
sync-registry-index.sh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 14:51:17 -04:00
Juan DenisandClaude Fable 5 43fec8030c cutover(email): serverkit-email leaves the tree (plan 52 Phase 2, D8)
builtin-extensions/serverkit-email + both tracked live copies removed; the
bundled registry entry flips to bundled:false with the local zip's sha256;
the gated auto-install (_email_was_configured) moves from
GATED_BUILTIN_SLUGS to REGISTRY_GATED_SLUGS so mail users still get it back
once the entry is published.

Panel-core tests re-home onto the sibling checkout via the new
conftest.sibling_extension_dir helper (skip cleanly when absent): the
extraction suite installs from the serverkit-email repo, the dovecot-probe
suite loads its module from there. All 39 affected tests green with the
sibling present.

OPERATOR: publish jhd3197/serverkit-email, sign, sync-registry-index.sh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 14:45:22 -04:00
Juan DenisandClaude Fable 5 2e0330d84d refactor(git): relocate the Git page into the serverkit-git extension (plan 52 Phase 6, frontend half)
Same relocation pattern as email/cloudflare-ops: pages/Git.jsx (1920 lines),
its SCSS partial (with the %sk-state placeholder inlined - @extend cannot
cross compile units) and a new Gitea-only API client move into
builtin-extensions/serverkit-git/frontend/. The page's two halves now show
their seam: Gitea self-host calls go through the extension's own client;
webhook + deployment calls stay on the core api object (they ARE the deploy
pipeline and exist on every panel).

Core files.js sheds the Gitea-half methods but keeps the three fail-soft
getGitea* aliases the app-creation repo pickers probe (they 404 and degrade
to 'not installed' when the extension is absent). serverkit-sdk adds the
ds/status helpers (statusKind & co). pages/ ratchets tighten: raw api calls
431->405, toast extractions 264->218.

Frontend build green, lint fully green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 14:04:30 -04:00
Juan DenisandClaude Fable 5 9f92850cbd feat(security)!: extract the install-gated security suite to extensions (plan 47 Ph3b-5 / plan 55 Ph3)
The 1791-line security omnibus splits along tool lines and the install-gated
surfaces leave core for five standalone extensions - serverkit-clamav
(ClamAV+YARA scanning, quarantine, scan jobs), serverkit-fail2ban
(management UI; probes stay core on Fail2banJailService), serverkit-lynis,
serverkit-auto-updates, and serverkit-image-scan (headless CVE/SBOM
scanning; models stay core per the plan 52 D1 data seam). Each mounts its
routes back at the same /api/v1/security prefix when installed, so route
shapes never change; absent extensions mean plain 404s, no dead UI.

Core keeps the zero-host-package baseline: status/config, legacy integrity,
suspicious activity/events, SSH keys, IP lists, the audit (fail2ban check
now probes via the jail service; updates check was already self-contained),
scoped FIM, and the scan/alert logs + notification helpers extensions write
through. Job handlers for security.malware_scan/lynis_scan/image_scan now
come exclusively from the extensions' manifest jobs key.

Security page becomes core-tabs-only; extension tabs contribute into the
security tab group (3a groupId). Overview posture drops the hardcoded
ClamAV rows and offers the Marketplace when no security extension is
installed. Upgrade parity: run_registry_auto_install() installs each
extension from the registry once, gated on the host tool actually being
present, fail-soft until the registry entry is published.

Wizard round 2 (Ph5): a security-posture chooser (minimal/recommended/
hardened) on the Summary step, catalog-resolved so unpublished slugs never
render dead installs; persisted as onboarding_security_posture.

Moved test suites re-home to the extension repos; panel keeps
test_security_suite_extraction.py (18 proving tests: absent-shape 404s,
lean summary, jail-service probes, migration gates, posture wiring).
docs/API_SURFACE.md regenerated (34 operations moved out).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 13:53:04 -04:00
Juan DenisandClaude Fable 5 3057d56977 refactor(cloudflare-ops): relocate the zone-ops frontend into the extension (plan 52 Phase 2 prep)
Same WP-Phase-4 pattern as the email relocation: the CloudflareZoneSettings
page, the WAF/Workers/Tunnels/Storage panels, the /cloudflare API client and
the SCSS partial move into builtin-extensions/serverkit-cloudflare-ops/
frontend/; the extension index.jsx imports locally and side-effect-imports
the SCSS. Core drops the cloudflareMethods spread from the api object and
the main.scss partial - DNS records and the Cloudflare connection stay core.

serverkit-sdk (still the unreleased 1.4.0 bump) adds Tabs kit, PageLoader
and copyToClipboard; vendor shim regenerated. The pages/ raw-api ratchet
tightens 460 -> 431 (the two relocated pages left pages/).

Frontend build green, lint fully green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 13:23:44 -04:00
Juan DenisandClaude Fable 5 f6d9dea954 refactor(email): relocate the Email page into the serverkit-email extension (plan 52 Phase 2 prep)
WP-Phase-4 pattern, in-tree Tier C: pages/Email.jsx, its SCSS partial and a
new self-contained /email API client move into
builtin-extensions/serverkit-email/frontend/; the extension index.jsx now
imports locally (no more core re-export shim) and side-effect-imports the
SCSS so it compiles through the extension's module graph. main.scss drops
the _email partial.

Core keeps only the email-adjacent surfaces core Settings renders: the
DNS-provider methods (core dns_providers blueprint) and the relay tile
methods. serverkit-sdk grows the generic list-page chrome the relocation
needed (DataTableFooter/ListToolbar/SearchField/SortChipBar, ds/grid saved-
view chrome, PageLayout, useTableSort, useColumnVisibility) - SDK 1.4.0,
backend mirror bumped in lock-step; vendor shim regenerated.

Frontend build green, lint 0 errors, i18n check no orphans.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 13:19:21 -04:00
Juan DenisandClaude Fable 5 2c7f13051f fix(scale): normalize backend nulls before they reach the policy form
The backend stores an unset service_name as null; spreading the API
response over the defaults pushed that null into a controlled <Input>,
flipping it uncontrolled. normalizeScalePolicy now coerces strings and
integer fields back to form-safe values. (Copilot review on #120)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 04:06:07 -04:00
Juan Denis 9a09a392cf test: add all-25 distro compatibility discovery 2026-08-28 23:01:48 -04:00
Juan DenisandClaude Fable 5 fb8d6bfbf8 fix(templates): the deploy drawer's domain promise now sticks
The drawer showed '<name>.<base> — Published automatically once the deploy
finishes' whenever a managed base domain existed, but publishing was gated
on a per-template auto_domain flag the operator can't see. For most of the
catalog the install landed on host:port instead — a link a default firewall
doesn't even expose — and the domain had to be redone by hand in the
service's Domain settings.

The promise on screen is now the contract: when the drawer displays a
domain it sends auto_domain: true, which rides the install plan to the
finalizer and overrides the template's silence (the forced flag also feeds
the SERVICE_FQDN magic context, so tokens and the published host agree).
Absent flag = the template YAML still decides, as before.

The drawer also stops promising what can't be delivered: the domain field
only renders for compose templates targeting the local server — the panel's
nginx can't proxy a remote container, and the repo pipeline has no
auto-publish step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 21:59:26 -04:00
Juan DenisandClaude Fable 5 3cb57ec77f fix(ui): lift modal stack above the shell statusbar
The VS Code-style bottom statusbar (z 1130) was added above the old modal
stack (40/50/60), so any full-height drawer or dialog reaching the bottom
edge had its footer buttons painted over — e.g. Deploy/Cancel in the
template deploy drawer. Modals own the screen: raise backdrop/modal/tooltip
to 1140/1150/1160, keeping their internal order and leaving toasts and the
app loader on top.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 21:50:12 -04:00
Juan Denis bb675f0d9a feat(apps): policy-driven replica scaling for local Compose apps
Add ContainerScaleService policies (min/max replicas, CPU thresholds,
cooldown) persisted via migration 093, with manual scale, single
evaluation, and an admin sweep endpoint. Container Ops panel exposes
policy editing; the configured minimum acts as a floor on the next
evaluation. Frontend node:test suites pin policy normalization and the
API contract.
2026-08-27 22:35:43 -04:00
Juan DenisandClaude Fable 5 6dfbc0df38 test(contract): pin frontend API paths to real backend routes
Nothing verified that the ~1200 URL literals in
frontend/src/services/api/*.js resolve to rules in the backend url map,
so a backend route rename surfaced as a dead button found by a user.
New test statically extracts every this.request() literal (mirror of
test_socket_contract.py's cross-language pattern) and asserts each
matches an /api/v1 rule from the session app's route_rules; paths under
a builtin extension's plugin.json url_prefix are excused only while
that manifest still declares the prefix, and a second test keeps the
allowlist from rotting.

First run caught 78 unresolved paths. Extension-owned families
(email/ftp/cloud/status/tunnels) were excused; the rest were dead
frontend code calling routes that no longer exist, removed here:
- 11 workflow wrappers in apps.js (the workflow engine left the
  backend in v1.7.33; zero callers remained)
- notification catalog/org-defaults wrappers (routes never existed;
  zero callers)
- 6 WordPress standalone lifecycle wrappers (no routes, no callers;
  the live status probe stays, allowlisted as extension-provided)

Frontend suite still green after the deletions (141/141, lint clean).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 04:33:57 -04:00
Juan DenisandClaude Fable 5 6f51b3b3c0 fix(i18n): drop orphaned noChange/envVar locale keys
ConfigDiffModal renamed noChange to noChangeValue and DeploymentTimeline
renamed envVar to envVarCount, but the old keys were left behind in the
16 translated locales, failing the i18n lint orphan check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 02:44:09 -04:00
Juan Denis 69182c3d95 feat(restore-points): add server restore points UI 2026-08-23 23:40:22 -04:00
Juan Denis 7cb04576bc fix(styles): remove duplicate disk reclaim owner 2026-08-22 15:00:53 -04:00
Juan Denis 1e4922746c fix(operations): normalize recipe handoff descriptors 2026-08-22 15:00:46 -04:00
Juan DenisandClaude Fable 5 2a5d18867f refactor(walkthroughs): the shell dock says Walkthroughs, not Recipes
Reserve the word Recipes for installers. The status-bar segment, dock
tab, hub aria-label and command-palette category now read Walkthroughs
(new app.walkthroughs.title/all keys; stale es allRecipes dropped).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:21:04 -04:00
Juan DenisandClaude Fable 5 93c8abbbbe feat(recipes): serverkit-recipes registry catalog with one-call installs
The curated serverkit-recipes index is consumed like the themes registry
(cached remote index, bundled fallback, SERVERKIT_RECIPES_REGISTRY_URL
override). GET /recipes/registry[/<slug>] browses it; POST /recipes/runs
now accepts a registry_slug plus server_id — targeting a server finds or
creates the per-workspace Recipes project — and validated non-secret
params that pre-supply handoff inputs so only true secrets pause the run.

Frontend: Recipes catalog page (cards, category chips, install drawer
with running-server picker, preflight table, up-front inputs and an
asked-during-the-run secrets preview) under new Services and Marketplace
tabs; runs land in the deployment console.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:20:55 -04:00
Juan DenisandClaude Fable 5 d867b92c98 chore(i18n): sync locales for the shell console round
en.json regenerated from inline defaults (new statusbar/console/palette/
recipes strings; Prompture and old walkthrough-hub strings gone). es picks
up translations for all 26 new keys; every locale drops the now-orphaned
keys so the parity gate stays green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:38 -04:00
Juan DenisandClaude Fable 5 adf6b48bff style(buttons): prototype accent treatment for the primary button
Gradient fill (accent-bright to accent), accent glow, inner top highlight,
and a hover that lifts the gradient toward white — all from theme tokens so
runtime skins keep recoloring it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:27 -04:00
Juan DenisandClaude Fable 5 8b7cecb62e feat(palette): create tile grid + recipes; the sidebar + opens the palette
The palette's empty state now leads with a Create tile grid (shared list in
data/createItems.js) plus a '+ n more' shelf that folds in the less-common
targets and any extension-contributed 'New ...' commands, then a Recipes
group (picking one starts it and opens the recipes console). Create and
recipe entries also score into regular search results.

The sidebar '+' stops carrying its own little dropdown and opens this
palette instead — one door for every new-thing flow, like the prototype.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:24 -04:00
Juan DenisandClaude Fable 5 3f3ff156f1 feat(ai): dock the assistant into the shell console; drop Prompture branding
The right-side chat drawer now carries the shared console tab strip, so the
assistant reads as the right-docked tab of the same console the bottom
panels belong to (its close moved into the strip). The 'powered by
Prompture' lines are gone from the header and empty state — the empty state
now tells the user what to ask instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:15 -04:00
Juan DenisandClaude Fable 5 6a8e80d7f1 feat(shell): one tabbed console + styled scope menus (port prototype chrome)
The bottom-edge surfaces (Operations, Alerts, Recipes, Assistant) now share
one console: every panel carries the same four-tab strip (ShellDockTabs) and
a ShellDockContext keeps exactly one open, so switching surfaces is a tab
click instead of hunting separate popovers. Recipes is rebuilt into the
prototype's split layout — step rail left, one step's story right, with a
deep-link action button, 'Done - next step', and Back.

The workspace/server switchers get real themed menus (dot - name - meta -
check) replacing the native <select> popup that ignored the theme, and the
sidebar keeps its full height again: it was shortened by the statusbar
height even though the bar only spans the content column, leaving a dead
30px hole under the user card.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:06 -04:00
Juan Denis c0de9fbcac refactor(i18n): consolidate duplicate locale strings into common.* namespace
en.json drops from 8107 to 6624 keys: repeated UI copy (Cancel x95,
Status x67, Refresh x54, ...) now lives under common.actions /
common.labels / common.loading, and extractor-era suffix duplicates
(refresh2, status3) within a component collapse onto one key.
Trailing ... defaults are normalized to the ellipsis character.

Translations are preserved: all 16 locales were re-keyed, carrying
existing per-component translations onto their new common.* keys
(majority vote where sources disagreed), and stale keys were pruned.

Verified: npm run lint (0 errors), node --test (140 pass), vite build.

edit
2026-08-22 01:32:52 -04:00
Juan Denis 6eb7e5433d feat: redesign app shell and file manager 2026-08-22 00:41:06 -04:00
Juan Denis 7b7779a6b2 fix(monitoring): restore missing disk-reclaim stylesheet (unbreaks build) 2026-08-21 23:59:46 -04:00
Juan Denis a16561a0fb refactor(ds): fold Drawer/PageTopbar/AppMap static styles into SCSS 2026-08-21 23:54:26 -04:00
Juan Denis 5a297adf97 refactor(ui): move widget/skeleton static inline styles into SCSS 2026-08-21 23:50:42 -04:00
Juan Denis 6ddeb0dad4 refactor(setup): replace wizard inline styles with modifier classes 2026-08-21 23:45:03 -04:00
Juan Denis 9f1aed7943 refactor(settings): replace static inline styles with SCSS classes 2026-08-21 23:43:02 -04:00