@1agh/maude 0.35.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/studio/canvas-shell.tsx +73 -2
- package/apps/studio/client/app.jsx +225 -11
- package/apps/studio/client/panels/GitPanel.jsx +6 -0
- package/apps/studio/client/panels/RepoBranchSwitcher.jsx +199 -68
- package/apps/studio/client/styles/3-shell-maude.css +22 -0
- package/apps/studio/commands/edit-source-command.ts +118 -0
- package/apps/studio/dist/client.bundle.js +21 -53108
- package/apps/studio/dist/comment-mount.js +1 -2048
- package/apps/studio/dist/styles.css +1 -12220
- package/apps/studio/git/endpoints.ts +17 -0
- package/apps/studio/git/service.ts +483 -40
- package/apps/studio/github/endpoints.ts +28 -4
- package/apps/studio/github/identity-cache.ts +138 -0
- package/apps/studio/github/service.ts +40 -23
- package/apps/studio/http.ts +12 -0
- package/apps/studio/test/canvas-origin-gate.test.ts +2 -0
- package/apps/studio/test/edit-source-command.test.ts +119 -0
- package/apps/studio/test/git-branches.test.ts +141 -3
- package/apps/studio/test/github-api.test.ts +58 -1
- package/apps/studio/test/identity-cache.test.ts +83 -0
- package/apps/studio/test/remote-ahead-behind-cache.test.ts +89 -0
- package/apps/studio/test/use-undo-stack.test.tsx +30 -0
- package/apps/studio/undo-stack.ts +10 -0
- package/apps/studio/use-undo-stack.tsx +21 -1
- package/apps/studio/whats-new.json +18 -0
- package/package.json +15 -10
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// DDR-132 — per-user GitHub identity SWR disk cache.
|
|
2
|
+
//
|
|
3
|
+
// Round-trips the cache against a temp XDG_CACHE_HOME, proves a different
|
|
4
|
+
// token-hash is a clean miss, and asserts the raw token NEVER appears in the
|
|
5
|
+
// on-disk file (only its sha256 prefix). Pure module — no network.
|
|
6
|
+
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
8
|
+
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import {
|
|
12
|
+
__testing,
|
|
13
|
+
cacheDir,
|
|
14
|
+
clearCached,
|
|
15
|
+
readCached,
|
|
16
|
+
tokenHash,
|
|
17
|
+
writeCached,
|
|
18
|
+
} from '../github/identity-cache.ts';
|
|
19
|
+
|
|
20
|
+
const realXdg = process.env.XDG_CACHE_HOME;
|
|
21
|
+
let tmp: string;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
tmp = mkdtempSync(join(tmpdir(), 'maude-idcache-'));
|
|
25
|
+
process.env.XDG_CACHE_HOME = tmp;
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
if (realXdg === undefined) delete process.env.XDG_CACHE_HOME;
|
|
29
|
+
else process.env.XDG_CACHE_HOME = realXdg;
|
|
30
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const IDENTITY = { login: 'octocat', name: 'Octo Cat', avatar_url: 'https://x/y.png' };
|
|
34
|
+
|
|
35
|
+
describe('identity-cache', () => {
|
|
36
|
+
test('cacheDir lands under $XDG_CACHE_HOME/maude', () => {
|
|
37
|
+
expect(cacheDir()).toBe(join(tmp, 'maude'));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('round-trips a written identity for the matching key', () => {
|
|
41
|
+
const key = tokenHash('tok_secret_abc');
|
|
42
|
+
expect(readCached(key)).toBeNull(); // first run: clean miss
|
|
43
|
+
writeCached(key, IDENTITY);
|
|
44
|
+
expect(readCached(key)).toEqual(IDENTITY);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('a different token-hash is a clean miss (account/token swap)', () => {
|
|
48
|
+
writeCached(tokenHash('tok_account_A'), IDENTITY);
|
|
49
|
+
expect(readCached(tokenHash('tok_account_B'))).toBeNull();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('the raw token never appears in the on-disk file', () => {
|
|
53
|
+
const token = 'ghp_SUPERSECRETtokenVALUE1234567890';
|
|
54
|
+
writeCached(tokenHash(token), IDENTITY);
|
|
55
|
+
const raw = readFileSync(__testing.cacheFile(), 'utf8');
|
|
56
|
+
expect(raw).not.toContain(token);
|
|
57
|
+
// the stored key IS present and is the hash prefix, not the token
|
|
58
|
+
expect(raw).toContain(tokenHash(token));
|
|
59
|
+
expect(tokenHash(token).length).toBe(16);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('tolerates a null name', () => {
|
|
63
|
+
const key = tokenHash('t');
|
|
64
|
+
writeCached(key, { login: 'ghost', name: null, avatar_url: 'a' });
|
|
65
|
+
expect(readCached(key)?.name).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('corrupt JSON is a clean miss, not a throw', () => {
|
|
69
|
+
writeCached(tokenHash('t'), IDENTITY);
|
|
70
|
+
// clobber the file with garbage
|
|
71
|
+
const fs = require('node:fs');
|
|
72
|
+
fs.writeFileSync(__testing.cacheFile(), '{ not json');
|
|
73
|
+
expect(readCached(tokenHash('t'))).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('clearCached forces a subsequent miss', () => {
|
|
77
|
+
const key = tokenHash('t');
|
|
78
|
+
writeCached(key, IDENTITY);
|
|
79
|
+
expect(readCached(key)).toEqual(IDENTITY);
|
|
80
|
+
clearCached();
|
|
81
|
+
expect(readCached(key)).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// DDR-132 — remote ahead/behind probe: in-memory TTL cache + in-flight dedupe.
|
|
2
|
+
//
|
|
3
|
+
// Verifies the cache WRAPPER (TTL-serve / invalidate / in-flight coalesce) fully
|
|
4
|
+
// offline, with no network and no git spawn. Trick: the probe's DDR-131 transport
|
|
5
|
+
// gate classifies a bare local-path remote as `unsafe`, so `remoteAheadBehind`
|
|
6
|
+
// returns a FRESH `{ahead:0,behind:0}` object on every *uncached* evaluation
|
|
7
|
+
// without touching the network. Object IDENTITY (`Object.is`) therefore tells a
|
|
8
|
+
// cache-serve (same reference) apart from a re-run (new reference) — a stronger
|
|
9
|
+
// signal than value equality, and one the security hardening can't invalidate.
|
|
10
|
+
//
|
|
11
|
+
// (The real fetch/count path needs a reachable github.com remote and is covered
|
|
12
|
+
// by the manual native dogfood — same offline ceiling DDR-131 records for
|
|
13
|
+
// `gitFetchRemote`. This file owns the wrapper semantics only.)
|
|
14
|
+
//
|
|
15
|
+
// This file deliberately does NOT set MAUDE_USE_SYSTEM_GIT (it would leak into the
|
|
16
|
+
// shared bun-test process and flip other files' iso-engine expectations).
|
|
17
|
+
|
|
18
|
+
import { afterEach, beforeEach, expect, test } from 'bun:test';
|
|
19
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { tmpdir } from 'node:os';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { invalidateRemoteProbe, remoteAheadBehind } from '../git/service.ts';
|
|
23
|
+
|
|
24
|
+
function git(cwd: string, args: string[]): void {
|
|
25
|
+
const p = Bun.spawnSync(['git', ...args], {
|
|
26
|
+
cwd,
|
|
27
|
+
env: { ...process.env, GIT_CONFIG_GLOBAL: '/dev/null', GIT_CONFIG_SYSTEM: '/dev/null' },
|
|
28
|
+
});
|
|
29
|
+
if (p.exitCode !== 0) throw new Error(`git ${args.join(' ')}: ${p.stderr.toString()}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let work: string;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
work = mkdtempSync(join(tmpdir(), 'maude-ab-work-'));
|
|
36
|
+
git(work, ['init', '-q', '-b', 'main']);
|
|
37
|
+
git(work, ['config', 'user.email', 't@t.dev']);
|
|
38
|
+
git(work, ['config', 'user.name', 'Tester']);
|
|
39
|
+
writeFileSync(join(work, 'a.txt'), 'hello\n');
|
|
40
|
+
git(work, ['add', '.']);
|
|
41
|
+
git(work, ['commit', '-q', '-m', 'init']);
|
|
42
|
+
// A bare local path → DDR-131 transport gate classifies it `unsafe` → the probe
|
|
43
|
+
// returns {0,0} with no spawn. (Any value is fine; we assert on identity.)
|
|
44
|
+
git(work, ['remote', 'add', 'origin', '/var/empty/maude-test-remote']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
invalidateRemoteProbe(work);
|
|
49
|
+
rmSync(work, { recursive: true, force: true });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('a second call within the TTL serves the cached object (no re-run)', async () => {
|
|
53
|
+
const a = await remoteAheadBehind(work, undefined);
|
|
54
|
+
expect(a).toEqual({ ahead: 0, behind: 0 });
|
|
55
|
+
const b = await remoteAheadBehind(work, undefined);
|
|
56
|
+
expect(Object.is(a, b)).toBe(true); // same reference ⇒ served from cache
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('invalidateRemoteProbe forces a fresh evaluation (new object)', async () => {
|
|
60
|
+
const a = await remoteAheadBehind(work, undefined);
|
|
61
|
+
invalidateRemoteProbe(work);
|
|
62
|
+
const c = await remoteAheadBehind(work, undefined);
|
|
63
|
+
expect(c).toEqual({ ahead: 0, behind: 0 });
|
|
64
|
+
expect(Object.is(a, c)).toBe(false); // new reference ⇒ re-ran after invalidation
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('SECURITY (DDR-133 F1): the unattended probe never fetches a non-github HTTP remote', async () => {
|
|
68
|
+
// Repoint origin to a non-github HTTPS host (a poisoned `.git/config` riding a clone).
|
|
69
|
+
// With system git auto-preferred (DDR-133), the host-allowlist must gate this probe
|
|
70
|
+
// BEFORE the engine branch — otherwise an http transport reached `git fetch` against
|
|
71
|
+
// ANY host on the unattended 45s poll (SSRF / presence beacon). The guard returns
|
|
72
|
+
// {0,0} with NO spawn; a regression would attempt the fetch and reject/hang here.
|
|
73
|
+
git(work, ['remote', 'set-url', 'origin', 'https://evil.example.invalid/repo.git']);
|
|
74
|
+
invalidateRemoteProbe(work);
|
|
75
|
+
const r = await remoteAheadBehind(work, 'tok_must_never_be_sent');
|
|
76
|
+
expect(r).toEqual({ ahead: 0, behind: 0 });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('concurrent callers coalesce onto one shared in-flight result', async () => {
|
|
80
|
+
const [a, b, c] = await Promise.all([
|
|
81
|
+
remoteAheadBehind(work, undefined),
|
|
82
|
+
remoteAheadBehind(work, undefined),
|
|
83
|
+
remoteAheadBehind(work, undefined),
|
|
84
|
+
]);
|
|
85
|
+
// One shared in-flight promise (or the just-written cache) ⇒ identical reference,
|
|
86
|
+
// never three independent evaluations.
|
|
87
|
+
expect(Object.is(a, b)).toBe(true);
|
|
88
|
+
expect(Object.is(b, c)).toBe(true);
|
|
89
|
+
});
|
|
@@ -155,6 +155,36 @@ describe('use-undo-stack / runner side-effects', () => {
|
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
+
describe('use-undo-stack / record (already-applied edits)', () => {
|
|
159
|
+
test('record() appends WITHOUT running do()', async () => {
|
|
160
|
+
const v = captureProvider(undefined, { layoutPatchFn: () => {} });
|
|
161
|
+
v.record(rec('inline-edit', 'X'));
|
|
162
|
+
// undo() is enqueued after record(), so awaiting it flushes record first.
|
|
163
|
+
await v.undo();
|
|
164
|
+
expect(doSpy).toHaveBeenCalledTimes(0); // record never runs do()
|
|
165
|
+
expect(undoSpy).toHaveBeenCalledTimes(1);
|
|
166
|
+
expect(undoSpy.mock.calls[0]?.[0]).toBe('X');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('record() then redo() (after undo) re-runs do()', async () => {
|
|
170
|
+
const v = captureProvider(undefined, { layoutPatchFn: () => {} });
|
|
171
|
+
v.record(rec('e', 'Y'));
|
|
172
|
+
await v.undo();
|
|
173
|
+
await v.redo();
|
|
174
|
+
expect(doSpy).toHaveBeenCalledTimes(1); // only redo's do(), not the record
|
|
175
|
+
expect(doSpy.mock.calls[0]?.[0]).toBe('Y');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('record() clears the redo future', async () => {
|
|
179
|
+
const v = captureProvider(undefined, { layoutPatchFn: () => {} });
|
|
180
|
+
await v.push(rec('a', 'A')); // doSpy: 1
|
|
181
|
+
await v.undo(); // future = [a]
|
|
182
|
+
v.record(rec('b', 'B')); // clears future
|
|
183
|
+
await v.redo(); // future empty → no-op, no extra do()
|
|
184
|
+
expect(doSpy).toHaveBeenCalledTimes(1);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
158
188
|
describe('use-undo-stack / cross-canvas persistence', () => {
|
|
159
189
|
test('history under a canvasFile survives a fresh provider mount with the same canvasFile', async () => {
|
|
160
190
|
// First mount: push 2 records.
|
|
@@ -71,6 +71,16 @@ export interface CommandSinks {
|
|
|
71
71
|
layoutPatchFn?: unknown;
|
|
72
72
|
/** Wired by `AnnotationsLayer`. */
|
|
73
73
|
strokesPutFn?: unknown;
|
|
74
|
+
/**
|
|
75
|
+
* Wired by `CanvasShell` (canvas-shell.tsx). Applies a single inline source
|
|
76
|
+
* edit (CSS / text / attr) by posting `dgn:'apply-edit'` to the parent shell,
|
|
77
|
+
* which owns the main-origin-only `/_api/edit-*` write (DDR-054 — the canvas
|
|
78
|
+
* iframe can't call those routes directly). Drives undo/redo of inspector
|
|
79
|
+
* CSS edits, inline text rewrites, and custom-attribute edits, which write
|
|
80
|
+
* the canvas `.tsx` source and were previously unrecoverable (no command, no
|
|
81
|
+
* snapshot). See `commands/edit-source-command.ts`.
|
|
82
|
+
*/
|
|
83
|
+
editSourceApplyFn?: unknown;
|
|
74
84
|
}
|
|
75
85
|
|
|
76
86
|
export type CommandBuilder<P = unknown> = (
|
|
@@ -51,6 +51,14 @@ export interface UndoStackValue {
|
|
|
51
51
|
* Awaiting the returned promise is optional.
|
|
52
52
|
*/
|
|
53
53
|
push: (record: CommandRecord) => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Record an ALREADY-APPLIED command — appends to `past` + clears `future`
|
|
56
|
+
* WITHOUT running `do()`. Use when the side-effect happened outside the
|
|
57
|
+
* stack (e.g. an inspector CSS commit / inline text edit that already POSTed
|
|
58
|
+
* `/_api/edit-*`), so re-running `do()` would double-apply. `undo()` / `redo()`
|
|
59
|
+
* still drive the command's `undo()` / `do()` normally afterwards.
|
|
60
|
+
*/
|
|
61
|
+
record: (record: CommandRecord) => void;
|
|
54
62
|
/** Undo the top of `past`. No-op when empty. */
|
|
55
63
|
undo: () => Promise<void>;
|
|
56
64
|
/** Redo the top of `future`. No-op when empty. */
|
|
@@ -69,6 +77,7 @@ const UndoStackContext = createContext<UndoStackValue | null>(null);
|
|
|
69
77
|
|
|
70
78
|
const NOOP_VALUE: UndoStackValue = {
|
|
71
79
|
push: () => Promise.resolve(),
|
|
80
|
+
record: () => {},
|
|
72
81
|
undo: () => Promise.resolve(),
|
|
73
82
|
redo: () => Promise.resolve(),
|
|
74
83
|
clear: () => {},
|
|
@@ -213,6 +222,16 @@ export function UndoStackProvider({
|
|
|
213
222
|
[enqueue, build, reportError, bumpLabel, writeState]
|
|
214
223
|
);
|
|
215
224
|
|
|
225
|
+
const record = useCallback(
|
|
226
|
+
(rec: CommandRecord): void => {
|
|
227
|
+
void enqueue(async () => {
|
|
228
|
+
writeState(undoReducer(stateRef.current, { type: 'push', record: rec }));
|
|
229
|
+
bumpLabel(rec.label);
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
[enqueue, writeState, bumpLabel]
|
|
233
|
+
);
|
|
234
|
+
|
|
216
235
|
const undo = useCallback(
|
|
217
236
|
(): Promise<void> =>
|
|
218
237
|
enqueue(async () => {
|
|
@@ -306,6 +325,7 @@ export function UndoStackProvider({
|
|
|
306
325
|
const value = useMemo<UndoStackValue>(
|
|
307
326
|
() => ({
|
|
308
327
|
push,
|
|
328
|
+
record,
|
|
309
329
|
undo,
|
|
310
330
|
redo,
|
|
311
331
|
clear,
|
|
@@ -318,7 +338,7 @@ export function UndoStackProvider({
|
|
|
318
338
|
// `lastTick` (bumped by every push/undo/redo/clear) as the proxy so the
|
|
319
339
|
// memoized canUndo/canRedo readouts re-evaluate on each transition.
|
|
320
340
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
321
|
-
[push, undo, redo, clear, lastLabel, lastTick]
|
|
341
|
+
[push, record, undo, redo, clear, lastLabel, lastTick]
|
|
322
342
|
);
|
|
323
343
|
|
|
324
344
|
return (
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./whats-new.schema.json",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"id": "git-native-switcher",
|
|
6
|
+
"version": "0.36.0",
|
|
7
|
+
"date": "2026-06-30",
|
|
8
|
+
"kind": "feature",
|
|
9
|
+
"title": "The version switcher now speaks Git",
|
|
10
|
+
"summary": "The bottom-left switcher uses plain Git names now — your branches by name, main as the default branch everyone shares, and a one-click “Merge this branch → main.” It opens instantly even on repos with hundreds of branches (it uses your installed Git when you have it), and “Pull a local copy” lists every repo you can reach on GitHub — including ones shared through your team or organization.",
|
|
11
|
+
"surface": "design-ui"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "remote-drafts-in-switcher",
|
|
15
|
+
"version": "0.36.0",
|
|
16
|
+
"date": "2026-06-30",
|
|
17
|
+
"kind": "feature",
|
|
18
|
+
"title": "Open any draft, including your team's",
|
|
19
|
+
"summary": "The version switcher now shows drafts that live on your team's shared remote — not only the ones already on this computer. They're marked “from your team,” and picking one downloads it for you. Hit Refresh to pull in a draft someone just made, search to find one in a long list, and your most recently worked-on drafts sort to the top. Works whether your project connects over SSH or HTTPS.",
|
|
20
|
+
"surface": "design-ui"
|
|
21
|
+
},
|
|
4
22
|
{
|
|
5
23
|
"id": "desktop-ai-chat-fix",
|
|
6
24
|
"version": "0.32.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1agh/maude",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"description": "Marketplace of Claude Code plugins by Michal Dovrtěl: `design` (canvas-first design iteration) + `flow` (generic agentic workflow loop with .ai second brain). Ships the `maude` CLI (with `mdcc` legacy alias) to scaffold workspace, run the design dev server, and manage configs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
"dev:site": "pnpm --filter @maude/site dev --port 4398",
|
|
23
23
|
"dev:desktop": "PATH=\"$HOME/.cargo/bin:$PATH\" pnpm --filter @maude/desktop tauri dev",
|
|
24
24
|
"build:desktop": "PATH=\"$HOME/.cargo/bin:$PATH\" pnpm --filter @maude/desktop tauri build",
|
|
25
|
-
"build": "pnpm
|
|
25
|
+
"test:e2e:desktop:build": "PATH=\"$HOME/.cargo/bin:$PATH\" pnpm --filter @maude/desktop tauri build --debug --config src-tauri/tauri.e2e.conf.json",
|
|
26
|
+
"test:e2e:desktop": "pnpm --filter @maude/desktop-e2e e2e",
|
|
27
|
+
"test:e2e:desktop:git": "pnpm --filter @maude/desktop-e2e e2e:git",
|
|
28
|
+
"build": "pnpm -r --if-present --filter '!@maude/desktop' '!@maude/desktop-e2e' run build",
|
|
26
29
|
"build:binary": "bun run apps/studio/build.ts --release",
|
|
27
30
|
"test": "node --test --test-reporter=spec cli/**/*.test.mjs",
|
|
28
31
|
"test:dev-server": "cd apps/studio && bun test",
|
|
@@ -40,16 +43,18 @@
|
|
|
40
43
|
"video:render": "cd scripts/video/final && pnpm run render",
|
|
41
44
|
"video:studio": "cd scripts/video/final && pnpm run studio",
|
|
42
45
|
"postinstall": "node cli/install.cjs",
|
|
43
|
-
"prepublishOnly": "bash scripts/check-version-parity.sh && bash apps/studio/bin/check-runtime-bundles.sh"
|
|
46
|
+
"prepublishOnly": "bash scripts/check-version-parity.sh && bash apps/studio/bin/check-runtime-bundles.sh",
|
|
47
|
+
"test:e2e:desktop:lifecycle": "pnpm --filter @maude/desktop-e2e e2e:lifecycle",
|
|
48
|
+
"test:e2e:desktop:switchrepos": "pnpm --filter @maude/desktop-e2e e2e:switchrepos"
|
|
44
49
|
},
|
|
45
50
|
"optionalDependencies": {
|
|
46
|
-
"@1agh/maude-darwin-arm64": "0.
|
|
47
|
-
"@1agh/maude-darwin-x64": "0.
|
|
48
|
-
"@1agh/maude-linux-arm64": "0.
|
|
49
|
-
"@1agh/maude-linux-arm64-musl": "0.
|
|
50
|
-
"@1agh/maude-linux-x64": "0.
|
|
51
|
-
"@1agh/maude-linux-x64-musl": "0.
|
|
52
|
-
"@1agh/maude-win32-x64": "0.
|
|
51
|
+
"@1agh/maude-darwin-arm64": "0.36.1",
|
|
52
|
+
"@1agh/maude-darwin-x64": "0.36.1",
|
|
53
|
+
"@1agh/maude-linux-arm64": "0.36.1",
|
|
54
|
+
"@1agh/maude-linux-arm64-musl": "0.36.1",
|
|
55
|
+
"@1agh/maude-linux-x64": "0.36.1",
|
|
56
|
+
"@1agh/maude-linux-x64-musl": "0.36.1",
|
|
57
|
+
"@1agh/maude-win32-x64": "0.36.1"
|
|
53
58
|
},
|
|
54
59
|
"files": [
|
|
55
60
|
"cli",
|