mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-29 18:11:40 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2a20a725d | ||
|
|
cac7ff1f3e |
No files matched your search
@@ -0,0 +1,98 @@
|
||||
# Batch 1 aggregate failure comparison
|
||||
|
||||
Frozen base: `e5bd294cddbf58dfe04c646b6291933d980498fd`. Current:
|
||||
`9af123e5d7bdb15771d69fb427faacf32c46dfb3`. Same Node 24.19.0 executable,
|
||||
same installed dependency tree, same sandbox and environment. Tests use existing
|
||||
synthetic fixtures. No home/cache permission or native-build bypass was added.
|
||||
|
||||
The 39 entries below were observed before stopping the local full suite.
|
||||
Later runner failures caused by that explicit termination are excluded. This
|
||||
is not a successful aggregate run and is not proof that every full-suite test
|
||||
was executed. The full suite was stopped after existing/environmental failures
|
||||
to avoid presenting an incomplete run as green.
|
||||
|
||||
## Bounded comparison result
|
||||
|
||||
Targeted test-name patterns selected the original 39 failures across 15 files.
|
||||
Thirty-eight fail on both frozen base and current with matching failure titles
|
||||
and key error signatures. The persistence-volume assertion passes on both.
|
||||
Three additional paired repetitions of that assertion also pass on both: four
|
||||
passing runs per side including the initial comparison. Its code is unchanged;
|
||||
the aggregate-only result remains a timing-sensitive limitation, not an
|
||||
established current-only regression.
|
||||
|
||||
The first baseline rerun reproduced 11 entries: rows 1-2 and 4-12. It did not
|
||||
reproduce row 3. No new source change fixes unrelated baseline failures.
|
||||
|
||||
| Rows | Signature and classification |
|
||||
| --- | --- |
|
||||
| 1-2, 14-16, 27-33, 35-39 | Host temp-dir creation fails outside writable roots (`ENOENT` from `tempDirBridge`). Both revisions fail. Environment constraint |
|
||||
| 4-9 | Markdown comparison falls back to source; expected rich-preview elements are absent. Both revisions fail. Existing baseline/dependency behavior; no source repair in this scope |
|
||||
| 10-12 | Native `pty.node` missing from normal build/prebuild lookup. Both revisions fail. Dependency/native setup constraint |
|
||||
| 13 | UI algorithm list includes `ssh-ed25519-cert-v01@openssh.com` but installed ssh2 rejects it. Both revisions fail. Existing baseline/dependency behavior |
|
||||
| 17-26 | Cursor discovery/SDK expectations differ (`false` vs `true`, then expected installation/auth DTO). Both revisions fail with matching assertion signatures. Existing environment/dependency behavior; no real account accessed |
|
||||
| 34 | Electron bootstrap fetch fails and the binary is not installed. Both revisions fail. Dependency/network setup constraint |
|
||||
| 3 | Persistence writes exceed aggregate threshold; isolated baseline/current and three repetitions each pass. Aggregate-only timing-sensitive assertion; no current-only failure reproduced |
|
||||
|
||||
## Original titles and first error
|
||||
|
||||
| # | Test file | Original title | First key error | Paired result |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | `application/state/sftp/dedicatedTransferResume.test.ts` | large-history replace recovery retransfers retained completed children into its empty stage: late=false | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 2 | `application/state/sftp/dedicatedTransferResume.test.ts` | large-history replace recovery retransfers retained completed children into its empty stage: late=true | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 3 | `application/state/sftpTransferCenterStore.test.ts` | large directory progress coalesces synchronous persistence work | AssertionError [ERR_ASSERTION]: expected bounded persistence volume, wrote 2638624 characters for a 588644-character snapshot | base/current pass; aggregate-only |
|
||||
| 4 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | literal Markdown comparisons render without changing the note source | AssertionError [ERR_ASSERTION]: a comparison must render as ordinary text | base/current same failure |
|
||||
| 5 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | comparison variants render in paragraphs, tables and alongside HTML | assert.ok(!querySourceFallback(rootNode)) is false | base/current same failure |
|
||||
| 6 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | issue 3205 author note survives source, preview and edit without rewriting | AssertionError [ERR_ASSERTION]: preview must render the author's note | base/current same failure |
|
||||
| 7 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | editing a comparison emits Markdown that can be reopened | assert.ok(editable): actual null | base/current same failure |
|
||||
| 8 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | preview task checkboxes still save explicit changes without rewriting comparisons | assert.ok(task): actual null | base/current same failure |
|
||||
| 9 | `components/notes/InlineMarkdownEditor.unrenderableMarkdown.test.tsx` | switching between a comparison note and an unsupported note keeps the fallback scoped | assert.ok(!querySourceFallback(rootNode)) is false | base/current same failure |
|
||||
| 10 | `components/terminal/runtime/serialInputSequences.test.ts` | components/terminal/runtime/serialInputSequences.test.ts | Failed to load native module: pty.node | base/current same failure |
|
||||
| 11 | `components/terminal/runtime/terminalLinePaste.test.ts` | components/terminal/runtime/terminalLinePaste.test.ts | Failed to load native module: pty.node | base/current same failure |
|
||||
| 12 | `components/terminal/runtime/terminalPasteCancellation.test.ts` | components/terminal/runtime/terminalPasteCancellation.test.ts | Failed to load native module: pty.node | base/current same failure |
|
||||
| 13 | `domain/sshAlgorithmList.test.ts` | SUPPORTED_ALGORITHMS_BY_CATEGORY only lists algorithms ssh2 will actually accept | AssertionError [ERR_ASSERTION]: ssh-ed25519-cert-v01@openssh.com (serverHostKey) is in the UI list but ssh2 would reject it | base/current same failure |
|
||||
| 14 | `electron/bridges/ai/liveShellProbe.test.cjs` | Bash invoked as sh cleans probe history | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 15 | `electron/bridges/ai/liveShellProbe.test.cjs` | Bash invoked as renamed-bash cleans probe history | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 16 | `electron/bridges/aiBridge.externalContext.test.cjs` | electron/bridges/aiBridge.externalContext.test.cjs | ENOENT creating host temp directory from sshBridge import | base/current same failure |
|
||||
| 17 | `electron/bridges/aiBridge.test.cjs` | resolve-cli reports Cursor Agent CLI on PATH as installed without CLI login | AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | base/current same failure |
|
||||
| 18 | `electron/bridges/aiBridge.test.cjs` | resolve-cli reports Cursor SDK installed but unavailable without an API key | AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | base/current same failure |
|
||||
| 19 | `electron/bridges/aiBridge.test.cjs` | resolve-cli separates Cursor SDK installation from API key availability | AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | base/current same failure |
|
||||
| 20 | `electron/bridges/aiBridge.test.cjs` | resolve-cli ignores custom Cursor paths and stores the SDK sentinel path | AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | base/current same failure |
|
||||
| 21 | `electron/bridges/aiBridge.test.cjs` | resolve-cli exposes Cursor SDK support when installed and authenticated | AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | base/current same failure |
|
||||
| 22 | `electron/bridges/aiBridge.test.cjs` | resolve-cli exposes Cursor SDK support when API key is saved in settings | AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | base/current same failure |
|
||||
| 23 | `electron/bridges/aiBridge.test.cjs` | resolve-cli reports settings as Cursor auth source when settings and env keys both exist | AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | base/current same failure |
|
||||
| 24 | `electron/bridges/aiBridge.test.cjs` | resolve-cli can refresh shell env before resolving Cursor | AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | base/current same failure |
|
||||
| 25 | `electron/bridges/aiBridge.test.cjs` | discover exposes Cursor SDK support when API key is saved in settings | AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | base/current same failure |
|
||||
| 26 | `electron/bridges/aiBridge.test.cjs` | discover can refresh shell env before scanning Cursor | AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | base/current same failure |
|
||||
| 27 | `electron/bridges/aiBridge/sdk/copilotDriver.test.cjs` | listCopilotModels resolves a Windows .cmd shim to the copilot JS entry before the SDK sees it | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 28 | `electron/bridges/aiBridge/sdk/copilotDriver.test.cjs` | listCopilotModels retains the official loader when its platform runtime is unavailable | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 29 | `electron/bridges/aiBridge/sdk/copilotDriver.test.cjs` | resolveCopilotPlatformExecutable resolves the platform package exe from the loader root | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 30 | `electron/bridges/aiBridge/sdk/copilotDriver.test.cjs` | resolveCopilotExecutableForSdk resolves npm's copilot.ps1 wrapper to the JS entry on Windows | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 31 | `electron/bridges/aiBridge/sdk/copilotDriver.test.cjs` | connectCopilotStdioPath directly selects the official loader's native runtime | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 32 | `electron/bridges/aiBridge/sdk/opencodeDriver.startup.test.cjs` | OpenCode releases the process-env gate after spawning separate catalog profiles | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 33 | `electron/bridges/aiBridge/sdk/opencodeDriver.test.cjs` | createOpenCodeProcessEnv prefers an existing opencode binary | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 34 | `electron/bridges/aiEchoSuppressionOrdering.test.cjs` | electron/bridges/aiEchoSuppressionOrdering.test.cjs | fetch failed; Electron failed to install correctly | base/current same failure |
|
||||
| 35 | `electron/bridges/autoUpdateBridge.test.cjs` | recognizes packaged Linux FPM formats as auto-update capable | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 36 | `electron/bridges/autoUpdateBridge.test.cjs` | allows the update check to reach electron-updater for a packaged Linux deb | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 37 | `electron/bridges/autoUpdateBridge.test.cjs` | keeps the manual-update fallback for an unmarked Linux package | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 38 | `electron/bridges/autoUpdateBridge.test.cjs` | keeps AppImage auto-update support on Linux | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
| 39 | `electron/bridges/autoUpdateBridge.test.cjs` | install handler reports package-manager failures and restores the app state | ENOENT creating host temp directory from tempDirBridge | base/current same failure |
|
||||
|
||||
## Reproduction method
|
||||
|
||||
For each file above, run the existing test with the same title pattern in each
|
||||
checkout. Pass the title pattern as an argument, without interpolating it as
|
||||
shell code. Native/import failures occur before the title filter can execute.
|
||||
|
||||
```sh
|
||||
node --test --import tsx --test-reporter=tap --test-name-pattern "<escaped original title>" <test file>
|
||||
```
|
||||
|
||||
The comparison used bounded 90-second subprocess deadlines. None reached that
|
||||
deadline. The persistence repeat used the same existing test and a 60-second
|
||||
deadline. It added no load generator or attack payload.
|
||||
|
||||
All 15 test files and the business modules responsible for these signatures
|
||||
are unchanged by batch 1. This classification does not resolve the two
|
||||
independently reported grant-management review findings; those receive
|
||||
separate source fixes and tests.
|
||||
@@ -27,7 +27,7 @@ mean complete. Existing APIs remain available.
|
||||
| Vault and keychain | Credential references and import preview/commit | Metadata/write enums do not grant a generic Vault SDK | Only user-selected whitelist DTOs and drafts | Notes, environmentVariables, startupCommand, keys and credentials | Selected object plus field/direction | Explicit preview, identity checks, redacted audit | Full Vault export and secret reads deferred indefinitely. No agent field-exclusion DTO reuse |
|
||||
| System manager and Docker | No plugin system API | Agent/MCP adapters are separate authority | Typed read-only summaries excluding args/env/inspect | Process command lines and Docker inspect can expose secrets | Selected live session and summary kind | Bounded result, endpoint identity, cancellation | Planned evaluation. Arbitrary process/inspect forwarding deferred |
|
||||
| Port forwarding | No generic plugin API | Existing agent start is write-sensitive | Selected rule status and open host form | Rule endpoints and local exposure | Selected rule plus host action | Bounded DTO, session close and revoke | Planned evaluation. Direct start deferred until binding/listener approval design |
|
||||
| Themes, settings, appearance, i18n | Contributions, scoped setting API, environment updates | No arbitrary application settings write | Existing namespaced contributions. Candidate: declarative global ThemePack using the 19 semantic tokens in `uiThemes.ts`, with preview/apply/reset and uninstall fallback | Settings can contain sensitive plugin values. A theme must preserve contrast and security UI | Plugin namespace, declared scope | Existing persistence and lifecycle, explicit sync flag | Existing tests. ThemePack design pending parent review of allowed tokens, accessibility and fallback. No arbitrary host DOM/CSS, remote CSS/fonts or security UI hiding. Arbitrary host settings mutation deferred |
|
||||
| Themes, settings, appearance, i18n | Terminal theme/background Providers, isolated view CSS, scoped settings and environment updates | No host global theme contribution. Personal customCSS is not plugin authority | Accepted ThemePack stage: static palette registry, source-labelled selector, window-local preview, revision-safe apply/cancel/reset, static terminal linkage | Unreadable colors and misleading security UI. Nineteen UiThemeTokens fields are not independent: primary/accent/ring and foregrounds derive from the effective accent | User explicitly selects a theme. Separate static contribution enablement from code permissions; no generic appearance.write or runtime activation | Immutable version/hash, bounded JSON, preview owner/token/revision, disable/update/uninstall fallback, no implicit sync, fixed host security appearance | [ThemePack design](./theme-packs-design.md) accepted for implementation after current A work; unfinished until contract, security boundary, lifecycle, contrast, samples and native gates pass. No arbitrary DOM/CSS, remote assets, free layout or security UI customization |
|
||||
| Transfer center | Host transfer queue exists, no plugin entry | No ownership-bound task API | Observe and cancel only plugin-created tasks | Paths and host endpoints reveal user data. Cancel may leave partial files | Own transfer handle plus source/destination authority | Shared backpressure, cancel/close cleanup, honest partial status | Planned with batch 2. Do not broadcast or cancel other tasks |
|
||||
| AI, MCP, automation | Host agent catalog and harness exist separately | No generic plugin AI or tool forwarding | Selection-to-proposal workflow through the same controlled primitives | Content disclosure, account authority and model cost | Explicit content sharing plus service origin/budget | No inherited history, tools, account, or hidden cron | Controlled workflow planned. Generic host AI and visible schedules deferred to distinct product decision |
|
||||
| Known hosts, app lock and global security | Host security management UI | No plugin management API | Future allowlisted security-page navigation | Host-key trust, unlock, keys and security policy affect all sessions | Host navigation action only | No mutation or sensitive DTO | Security policy mutation, private-key reads, auto-trust and unlocking deferred indefinitely |
|
||||
@@ -41,7 +41,8 @@ mean complete. Existing APIs remain available.
|
||||
2. Batch 1b: host action context, native interactions, selected context and terminal
|
||||
sharing/drafts. A plugin-supplied gesture is never authority.
|
||||
3. Batch 2: SFTP selected-file handles and explicit transfer destinations.
|
||||
4. Reassess editor, Notes, snippets, menus, system summaries, and port forwarding
|
||||
4. Deliver the separately reviewed [declarative ThemePack stage](./theme-packs-design.md), including protected security surfaces, contrast gates, revision-safe preview/apply/reset, and safe fallback.
|
||||
5. Reassess editor, Notes, snippets, menus, system summaries, and port forwarding
|
||||
using the tested host-action and resource primitives.
|
||||
|
||||
Stop only when every row is implemented and tested, reasonably deferred with a
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
# Declarative theme packs
|
||||
|
||||
Status: proposed implementation plan. No theme contribution or theme permission
|
||||
is implemented by this document. The baseline is Draft #3951 at
|
||||
`e5bd294cddbf58dfe04c646b6291933d980498fd`; batch 1 grants and network contracts
|
||||
are reviewed separately in Draft #3955.
|
||||
|
||||
## Scope and existing behavior
|
||||
|
||||
A theme pack supplies validated color data. Users preview, apply, cancel, or
|
||||
reset it through the host Appearance UI. Selecting a theme never starts a
|
||||
plugin runtime or approves its function permissions. This extends whole-app
|
||||
appearance alongside existing `terminal.theme` and `terminal.background`
|
||||
Providers and isolated view styles.
|
||||
|
||||
Personal `customCSS` is a user-owned advanced setting, not a third-party plugin
|
||||
surface. This plan introduces no stylesheet, selector, DOM, font URL, image URL,
|
||||
script, layout, notification, or background permission.
|
||||
|
||||
`UiThemeTokens` has 19 fields. They are not independent controls:
|
||||
`buildAppThemeCssVars()` assigns one effective accent to primary, accent, and
|
||||
ring and computes both accent foregrounds. The initial theme contract preserves
|
||||
this relationship. It must not accept independent primary, primaryForeground,
|
||||
accentForeground, or ring overrides and then silently discard them.
|
||||
|
||||
## Contract and package admission
|
||||
|
||||
The proposed feature is `appearance.theme-packs`. Its schema definitions,
|
||||
generated SDK exports, runtime/package compatibility, and documentation move
|
||||
together. Plan an internal schema/API revision with legacy negotiation retained;
|
||||
do not change the current batch 1 API just to publish this proposal. Old hosts
|
||||
reject a pack that requires the unknown feature before registration.
|
||||
|
||||
A proposed `contributes.themes` entry contains:
|
||||
|
||||
| Field | Meaning and validation |
|
||||
| --- | --- |
|
||||
| `id` | Contribution ID under the owning plugin namespace |
|
||||
| `label` | Existing bounded localized-text contract |
|
||||
| `variant` | `light`, `dark`, `hc-light`, or `hc-dark` |
|
||||
| `path` | Canonical package-relative JSON path inside the immutable installed version |
|
||||
|
||||
A theme JSON document contains a schema revision, a variant-matching built-in
|
||||
base ID, bounded color overrides, and an optional static terminal palette.
|
||||
It contains no cross-plugin includes, arbitrary file references, inheritance
|
||||
chains, or remote resources. Resolve the validated base and overrides into one
|
||||
immutable complete palette before registration. Never retain partially valid
|
||||
entries from a failed theme document.
|
||||
|
||||
The initial allowed UI overrides are `background`, `foreground`, `card`,
|
||||
`cardForeground`, `popover`, `popoverForeground`, `secondary`,
|
||||
`secondaryForeground`, `muted`, `mutedForeground`, `accent`, `destructive`,
|
||||
`destructiveForeground`, `border`, and `input`. Accept only opaque `#RRGGBB`
|
||||
colors. The host converts them to its internal HSL representation. Reject
|
||||
unknown keys, alpha, CSS expressions, `url()`, `var()`, `@import`, non-finite
|
||||
values, and custom properties. Do not pass author strings to CSS parsing.
|
||||
|
||||
The optional terminal palette uses the existing `TerminalThemeColorName`
|
||||
allowlist. It merges with a host default and is validated independently.
|
||||
Static terminal colors require neither a session snapshot nor a Provider call.
|
||||
|
||||
Initial bounds for implementation and tests are 32 themes per package,
|
||||
64 KiB per JSON file, 2 MiB total theme JSON, depth 8, and one active preview per
|
||||
window. These are proposed defaults, not existing limits. The schema and host
|
||||
must share the final constants. No font, image, or video assets enter v1.
|
||||
|
||||
### Static admission must remain distinct from code activation
|
||||
|
||||
The present manifest requires `main` and browser-only policy expects a browser
|
||||
entrypoint. Removing either check without a separate package variant is unsafe.
|
||||
|
||||
For the first usable slice, a sample can retain a no-op browser entrypoint.
|
||||
Static theme registration must not invoke it. Theme enablement has a separate
|
||||
host-owned state from function/code enablement. Installing a pack keeps both
|
||||
off until a user opts into the corresponding contribution. Enabling its themes
|
||||
never sets the code-enabled flag, grants permissions, or runs activation events.
|
||||
Disabling the package disables its theme contributions as well as its code.
|
||||
|
||||
A later exclusive data-only manifest variant can remove the no-op entrypoint.
|
||||
It must reject `main`, activation events, permissions, companions, providers,
|
||||
commands, and every non-theme contribution. Update canonical validation,
|
||||
semantic admission, package inspection, catalog policy, manager behavior, and
|
||||
compatibility tests together. The public catalog must explicitly recognize
|
||||
this inert variant while retaining browser-only admission for executable packs.
|
||||
A theme-only exception must not admit Node or an executable mixed package.
|
||||
|
||||
## Host registry and persistence
|
||||
|
||||
A host registry reads only installed, immutable package versions through the
|
||||
existing package-store path boundary. Verify real paths, file kinds, byte caps,
|
||||
and package ownership. Preserve the validated source version and content hash.
|
||||
No plugin RPC can register, apply, or replace global palette data.
|
||||
|
||||
A committed selection references plugin ID, theme ID, variant, package version,
|
||||
and validated theme hash. Store per-variant selections and a monotonic commit
|
||||
revision through the settings/persistence layer. Do not persist plugin CSS or
|
||||
turn this into implicit KV/cloud synchronization. Preserve legacy built-in theme
|
||||
IDs and existing user settings when no plugin theme is selected.
|
||||
|
||||
Theme availability records and applied preferences are user state, separate
|
||||
from runtime KV and function permissions. Define retained missing-selection
|
||||
metadata and uninstall behavior explicitly. Missing code or theme files must
|
||||
not trigger downloads, runtime activation, or new grants.
|
||||
|
||||
## Preview, apply, cancel, and reset
|
||||
|
||||
A single appearance resolver feeds existing chrome/terminal effects. Do not add
|
||||
a second root effect that races `useAppThemeStyle`, `useThemeRuntime`, or active
|
||||
terminal chrome selection.
|
||||
|
||||
| Host action | Required behavior |
|
||||
| --- | --- |
|
||||
| Preview | Create a host-owned token bound to window, preview owner, selected immutable theme, and current committed revision. Render locally without storage writes, sync events, runtime activation, or other-window changes |
|
||||
| Apply | Verify owner, token, version/hash, availability, and expected commit revision. Commit the selected theme and explicitly chosen terminal linkage as one settings action. A stale preview produces a conflict, not an overwrite |
|
||||
| Cancel or close | Clear only the matching local preview token. Render the latest committed state. Never restore a captured old settings snapshot over a newer commit |
|
||||
| Reset | Clear the selected variant's plugin reference using the same revision check and apply the host default. Preserve font, accent, per-host terminal, and accessibility preferences |
|
||||
| Another window applies | Advance the shared commit revision. End the old preview or mark it stale; later cancel cannot alter the new selection |
|
||||
| Disable/uninstall/update | Invalidate matching previews and registry entries. Immediately resolve affected selections to a safe built-in variant, retain a bounded missing-reference notice, and never silently adopt unreviewed replacement bytes |
|
||||
| Application exit or window destruction | Release local preview ownership. Only committed preferences survive startup |
|
||||
|
||||
The preview UI always identifies plugin source/version and has host-controlled
|
||||
Apply, Cancel, and Restore default controls. Those controls live inside the
|
||||
security appearance boundary. Theme data cannot control their labels, order,
|
||||
visibility, click behavior, or layout.
|
||||
|
||||
Applying a theme changes only the selected palette and explicit terminal linkage.
|
||||
It does not overwrite user font family/size, accent override, host terminal
|
||||
override, reduced-motion choice, or OS accessibility preferences.
|
||||
|
||||
## Appearance precedence and terminal behavior
|
||||
|
||||
Resolve appearance in this order:
|
||||
|
||||
1. Host security surfaces and OS accessibility requirements.
|
||||
2. Explicit user font, size, accent, and per-host/per-terminal overrides.
|
||||
3. The selected and validated theme pack.
|
||||
4. Built-in defaults.
|
||||
|
||||
Define one effective accent using the current host rule. Reject impossible
|
||||
contrast combinations, including a user accent override against the effective
|
||||
surface, or show an explicit host correction before apply. Do not report an
|
||||
ignored author field as a successful override.
|
||||
|
||||
Follow App may use the pack's static terminal palette. Manual terminal choices
|
||||
and per-host overrides retain precedence. Reuse the existing active-chrome
|
||||
selection rather than resetting app appearance on tab changes. Test Vault,
|
||||
SFTP, terminal, editor, Notes, logs, split panes, and detached windows.
|
||||
|
||||
High-contrast flags in plugin environments are not proof that the host already
|
||||
has complete high-contrast themes. Missing HC variants require a host-owned HC
|
||||
fallback. Do not downgrade a forced-colors/high-contrast preference to an
|
||||
ordinary light/dark theme. Respect reduced motion and font scaling.
|
||||
|
||||
## Security appearance and contrast gates
|
||||
|
||||
Native Electron permission dialogs already sit outside renderer CSS. React
|
||||
security surfaces need a new explicit boundary before a theme pack ships.
|
||||
Cover AppLock, host-key trust, credential selection, grant/revoke management,
|
||||
dangerous confirmations, and theme preview/apply controls. Use host-controlled
|
||||
colors, font, icons, and layout there. Package colors never style those surfaces.
|
||||
The existing code has no verified shared boundary covering all of them.
|
||||
|
||||
Color validation checks complete resolved/composited pairs, not only body text:
|
||||
foreground/background, card text/card, popover text/popover, secondary/muted
|
||||
text, accent/button text, destructive/button text, focus rings, borders, inputs,
|
||||
and selected/disabled states. Ordinary text needs 4.5:1, large text 3:1, and
|
||||
required non-text indicators 3:1 against adjacent surfaces. Reject a failing
|
||||
palette with a named pair and ratio, or show an explicit host correction.
|
||||
Tests must prove the effective UI, not only a helper's arithmetic.
|
||||
|
||||
These gates follow [WCAG text contrast](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)
|
||||
and [non-text contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html).
|
||||
Theme screenshot review supplements contract, lifecycle, and accessibility
|
||||
checks. It does not establish safe ownership, persistence, or revocation.
|
||||
|
||||
## Delivery stages and acceptance
|
||||
|
||||
Current batch A grants and SDK consistency reaches review/CI first. Complete
|
||||
the controlled native interaction/context work as planned; theme work remains
|
||||
a separate small stage from marketplace card/layout changes.
|
||||
|
||||
| Stage | Implementation and evidence |
|
||||
| --- | --- |
|
||||
| Contract and pure validation | Canonical schema/generated SDK, feature/revision negotiation, strict color parser, derived-accent semantics, static terminal palette, bounds, named contrast diagnostics, old manifest compatibility |
|
||||
| Registry and security boundary | Immutable package ownership, static registration without runtime, independent theme/code enablement, fixed security appearance, same-variant/HC fallback, unavailable/tampered version behavior |
|
||||
| Product workflow | Appearance grouping/source, local preview ownership, revision-safe apply/cancel/reset, safe defaults, system theme changes, terminal linkage and overrides, persistence and window synchronization |
|
||||
| Samples and final acceptance | Light/dark no-op-browser sample, normal settings import without advanced mode, no runtime/grants on theme apply, later data-only admission only if fully validated, exact-SHA tests/build/package/CI, Codex review/fix/review, parent-owned native recording |
|
||||
|
||||
Boundary tests include unknown fields/feature, invalid or excessive JSON,
|
||||
unsupported variant/base, non-package and changed paths, unreadable colors,
|
||||
preview cancellation and window close, two-window apply/cancel ordering,
|
||||
update/disable/uninstall/failure fallback, startup restoration, host and accent
|
||||
overrides, forced colors, reduced motion, Chinese fonts/fallback, and every
|
||||
protected security surface. A pending gate keeps the theme row unfinished.
|
||||
|
||||
Later controlled candidates are known-font recommendations, radius/density
|
||||
presets after component support exists, declarative file/folder icons, and
|
||||
package-local static backgrounds on fixed surfaces with contrast limits. They
|
||||
need separate contracts and acceptance. Global CSS, free layout, remote fonts,
|
||||
HTML/video backgrounds, and security-UI customization remain excluded.
|
||||
|
||||
## Baseline source references
|
||||
|
||||
- `infrastructure/config/uiThemes.ts`: token fields and built-in registry.
|
||||
- `application/state/settingsStateDefaults.ts`: accent derivation and built-in ID checks.
|
||||
- `application/state/appearanceSync.ts`, `appearanceChromeStore.ts`, and
|
||||
`useSettingsState.ts`: persistence and cross-window behavior.
|
||||
- `application/app/useAppThemeStyle.ts`, `activeChromeTheme.ts`,
|
||||
`application/state/useThemeRuntime.ts`, and `domain/terminalAppearance.ts`:
|
||||
effective UI and terminal precedence.
|
||||
- `packages/plugin-sdk/src/index.ts`: existing terminal theme/background types.
|
||||
- `electron/plugins/pluginProtocol.cjs`: isolated view CSS/font/network CSP.
|
||||
- `lib/customCss.ts`: personal user CSS, excluded from plugin authority.
|
||||
- `domain/pluginRuntimePolicy.cjs` and the canonical manifest schema: executable admission.
|
||||
- `electron/plugins/nativePermissionDecision.cjs`: native permission prompts.
|
||||
Reference in new issue
Block a user