pressship 0.1.15 → 0.2.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/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  <a href="https://www.npmjs.com/package/pressship"><img alt="npm" src="https://img.shields.io/npm/v/pressship?color=3858e9&logo=npm&logoColor=white&style=flat-square" /></a>
17
17
  <a href="https://wordpress.org/plugins/developers/"><img alt="WordPress.org" src="https://img.shields.io/badge/WordPress.org-plugin%20directory-21759b?logo=wordpress&logoColor=white&style=flat-square" /></a>
18
18
  <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-3858e9?style=flat-square" /></a>
19
- <a href="https://github.com/f/pressship"><img alt="GitHub stars" src="https://img.shields.io/github/stars/f/pressship?style=flat-square&logo=github&color=1e293b" /></a>
19
+ <a href="https://github.com/Automattic/pressship"><img alt="GitHub stars" src="https://img.shields.io/github/stars/Automattic/pressship?style=flat-square&logo=github&color=1e293b" /></a>
20
20
  </p>
21
21
 
22
22
  <p align="center">
@@ -70,6 +70,7 @@ That's it. Pressship handles browser-based login, packaging, readme validation,
70
70
  - **Submission state inspector** — reads the logged-in developer page to surface review status, slug, reupload availability, and Plugin Check links.
71
71
  - **SVN release workflow** — handles checkout, trunk sync, tag creation, and commit.
72
72
  - **WordPress Playground demos** — boot any local path or hosted slug in Playground using the plugin's own WP/PHP requirements.
73
+ - **Pressship Studio** — a local VS Code-style workspace with file tabs, Playground previews, AI assistance, release management, package-size checks, and CLI command hints in the terminal.
73
74
  - **`.pressshipignore` + glob ignores** — sensible defaults, easy per-command overrides.
74
75
  - **Agent skill included** — a Pressship publishing skill for coding agents (Codex, Claude Code, etc.).
75
76
  - **Beautiful terminal UX** — colored output, progress indicators, structured findings.
@@ -115,7 +116,7 @@ pressship <command> --help
115
116
  Pressship can also be installed as a WP-CLI package:
116
117
 
117
118
  ```bash
118
- wp package install f/pressship
119
+ wp package install Automattic/pressship
119
120
  ```
120
121
 
121
122
  That adds a `wp ship` command:
@@ -260,7 +261,9 @@ pressship studio --no-open
260
261
  pressship studio --port 9478
261
262
  ```
262
263
 
263
- `studio` starts a localhost-only Pressship Studio workspace. It lists plugins from the saved WordPress.org session, remembers local plugin paths, clones and updates WordPress.org SVN checkouts, shows plugin metadata and readmes, opens local plugins in a VS Code-style editor, streams Playground output into the Studio terminal, previews Playground in an iframe, checks version state, bumps patch/minor/major versions, and runs dry-run-first publish/release flows.
264
+ `studio` starts a localhost-only Pressship Studio workspace. It lists plugins from the saved WordPress.org session, remembers local plugin paths, clones and updates WordPress.org SVN checkouts, shows plugin metadata and readmes, opens local plugins in a VS Code-style editor, streams Playground output into the Studio terminal, previews Playground in an iframe, checks package size, manages `.pressshipignore`, checks version state, bumps patch/minor/major versions, and runs dry-run-first publish/release flows.
265
+
266
+ Studio also prints the equivalent `npx pressship ...` command in its terminal for CLI-backed actions such as Playground, Plugin Check, package size, version bumps, and publish dry runs.
264
267
 
265
268
  By default it binds to `127.0.0.1`, generates a per-run token for mutating API requests, and uses the same local Pressship config directory as the CLI.
266
269
 
@@ -406,13 +409,13 @@ pressship release ./my-plugin --no-install-svn
406
409
  Pressship ships with a publishing skill for coding agents (Codex, Claude Code, etc.). It teaches your agent to publish WordPress plugins cautiously — dry-run first, state-aware, with a final review step before any upload.
407
410
 
408
411
  ```bash
409
- npx skills add f/pressship --skill wordpress-plugin-publish -a codex
412
+ npx skills add Automattic/pressship --skill wordpress-plugin-publish -a codex
410
413
  ```
411
414
 
412
415
  Replace `codex` with another supported agent name, e.g. `claude-code`. List available skills first:
413
416
 
414
417
  ```bash
415
- npx skills add f/pressship --list
418
+ npx skills add Automattic/pressship --list
416
419
  ```
417
420
 
418
421
  ## Configuration
@@ -552,7 +555,7 @@ Pressship is built on the work of many people and projects:
552
555
 
553
556
  ## Disclaimer
554
557
 
555
- **Pressship is an independent, community project.** It is not affiliated with, endorsed by, or sponsored by WordPress, WordPress.org, the WordPress Foundation, or Automattic. The WordPress® trademark is the property of the WordPress Foundation.
558
+ **Pressship is an Automattic-maintained community project.** It is currently unofficial tooling for WordPress.org plugin publishing workflows, not an official WordPress.org service or a WordPress Foundation project. WordPress® is a trademark of the WordPress Foundation.
556
559
 
557
560
  ## License
558
561
 
package/assets/web/app.js CHANGED
@@ -76,14 +76,14 @@ const HARNESS_ICON = {
76
76
  const STUDIO_LAYOUT_STORAGE_KEY = "pressship.studio.layout.v1";
77
77
 
78
78
  const STUDIO_LAYOUT_DEFAULTS = {
79
- files: 260,
79
+ files: 220,
80
80
  ai: 330,
81
81
  terminal: 190,
82
82
  checkNotes: 152
83
83
  };
84
84
 
85
85
  const STUDIO_LAYOUT_LIMITS = {
86
- files: { min: 180, max: 560 },
86
+ files: { min: 160, max: 440 },
87
87
  ai: { min: 260, max: 720 },
88
88
  terminal: { min: 100, max: 600 },
89
89
  checkNotes: { min: 80, max: 520 }
@@ -1311,8 +1311,9 @@ function renderRemote() {
1311
1311
  }
1312
1312
 
1313
1313
  function remoteCard(plugin) {
1314
- const inLibrary = state.local.find((entry) => entry.slug === plugin.slug);
1315
- const primaryLabel = inLibrary ? "Open in Studio" : "Open in Library";
1314
+ const localState = remotePluginLocalState(plugin);
1315
+ const inLibrary = localState.entry;
1316
+ const primaryLabel = inLibrary ? "Open in Studio" : "Clone to Local";
1316
1317
  const primaryAction = inLibrary
1317
1318
  ? `data-action="studio" data-scope="local" data-id="${escapeAttr(inLibrary.id)}"`
1318
1319
  : `data-action="open-in-library" data-slug="${escapeAttr(plugin.slug)}"`;
@@ -1321,7 +1322,7 @@ function remoteCard(plugin) {
1321
1322
  const description = plugin.author ? `By ${plugin.author}` : "WordPress.org plugin";
1322
1323
 
1323
1324
  return `
1324
- <article class="ps-plugin-card${inLibrary ? " is-in-library" : ""}" data-slug="${escapeAttr(plugin.slug)}">
1325
+ <article class="ps-plugin-card${inLibrary ? " is-in-library" : " is-not-cloned"}" data-slug="${escapeAttr(plugin.slug)}">
1325
1326
  <header class="ps-plugin-card-header">
1326
1327
  <span class="ps-plugin-card-icon" aria-hidden="true">${escapeHtml(initials)}</span>
1327
1328
  <div class="ps-plugin-card-title">
@@ -1345,6 +1346,13 @@ function remoteCard(plugin) {
1345
1346
  <dd>${roleBadges}</dd>
1346
1347
  </div>
1347
1348
  </dl>
1349
+ <div class="ps-plugin-card-status ps-plugin-card-local-state" title="${escapeAttr(localState.title)}">
1350
+ <span class="badge badge-${escapeAttr(localState.tone)}">
1351
+ <span class="dashicons ${escapeAttr(localState.icon)}" aria-hidden="true"></span>
1352
+ ${escapeHtml(localState.label)}
1353
+ </span>
1354
+ <small>${escapeHtml(localState.note)}</small>
1355
+ </div>
1348
1356
  <footer class="ps-plugin-card-footer">
1349
1357
  <button type="button" class="button button-primary ps-plugin-card-primary" ${primaryAction}>
1350
1358
  <span class="dashicons ${inLibrary ? "dashicons-editor-code" : "dashicons-download"}" aria-hidden="true"></span>
@@ -1358,6 +1366,55 @@ function remoteCard(plugin) {
1358
1366
  `;
1359
1367
  }
1360
1368
 
1369
+ function remotePluginLocalState(plugin) {
1370
+ const matches = state.local.filter((entry) => entry.slug === plugin.slug);
1371
+ const cloned = matches.find((entry) => entry.source === "clone" && entry.exists !== false);
1372
+ const tracked = matches.find((entry) => entry.exists !== false);
1373
+ const missing = matches.find((entry) => entry.exists === false);
1374
+
1375
+ if (cloned) {
1376
+ return {
1377
+ entry: cloned,
1378
+ label: "Cloned locally",
1379
+ note: cloned.path || "SVN checkout is tracked in Studio.",
1380
+ title: cloned.path || "This WordPress.org plugin has a local SVN checkout.",
1381
+ tone: "soft-success",
1382
+ icon: "dashicons-yes-alt"
1383
+ };
1384
+ }
1385
+
1386
+ if (tracked) {
1387
+ return {
1388
+ entry: tracked,
1389
+ label: "Tracked locally",
1390
+ note: tracked.path || "Matching local folder is tracked in Studio.",
1391
+ title: tracked.path || "A matching local plugin folder is tracked in Studio.",
1392
+ tone: "soft-success",
1393
+ icon: "dashicons-admin-site-alt3"
1394
+ };
1395
+ }
1396
+
1397
+ if (missing) {
1398
+ return {
1399
+ entry: null,
1400
+ label: "Local path missing",
1401
+ note: "Clone to recreate the local checkout.",
1402
+ title: missing.path || "The previous local folder is no longer available.",
1403
+ tone: "soft-warning",
1404
+ icon: "dashicons-warning"
1405
+ };
1406
+ }
1407
+
1408
+ return {
1409
+ entry: null,
1410
+ label: "Not cloned",
1411
+ note: "Clone this WordPress.org plugin to work on it locally.",
1412
+ title: "This WordPress.org plugin is not cloned into the local library.",
1413
+ tone: "soft-warning",
1414
+ icon: "dashicons-download"
1415
+ };
1416
+ }
1417
+
1361
1418
  function remoteRoleChips(roles = []) {
1362
1419
  const safeRoles = Array.isArray(roles) ? roles : [];
1363
1420
  if (!safeRoles.length) {
@@ -1400,6 +1457,9 @@ async function loadLocal() {
1400
1457
  state.local.map((plugin, index) => [plugin.id, versionStates[index]])
1401
1458
  );
1402
1459
  renderLocal();
1460
+ if (!state.remoteLoading && state.remote.length) {
1461
+ renderRemote();
1462
+ }
1403
1463
  } catch (error) {
1404
1464
  state.localError = error.message;
1405
1465
  els.local.innerHTML = emptyState({
@@ -3461,15 +3521,19 @@ function renderStudioAiChangeCard(change) {
3461
3521
  <article class="studio-ai-change-card${selected ? " is-selected" : ""}">
3462
3522
  <button type="button" class="studio-ai-change" data-action="studio-ai-change" data-path="${escapeAttr(change.path)}">
3463
3523
  <span class="dashicons ${change.status === "deleted" ? "dashicons-trash" : studioFileIcon(change.path)}" aria-hidden="true"></span>
3464
- <span>${escapeHtml(change.path)}</span>
3465
- <small>${escapeHtml(studioAiPatchSummary(change))}</small>
3524
+ <span class="studio-ai-change-main">
3525
+ <span class="studio-ai-change-path">${escapeHtml(change.path)}</span>
3526
+ <small>${escapeHtml(studioAiPatchSummary(change))}</small>
3527
+ </span>
3466
3528
  </button>
3467
3529
  <div class="studio-ai-change-actions" aria-label="${escapeAttr(`Review ${change.path}`)}">
3468
3530
  <button type="button" class="studio-ai-change-action is-accept" data-action="studio-ai-accept" data-path="${escapeAttr(change.path)}" title="Accept patch" aria-label="${escapeAttr(`Accept patch for ${change.path}`)}">
3469
3531
  <span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>
3532
+ <span>Accept</span>
3470
3533
  </button>
3471
3534
  <button type="button" class="studio-ai-change-action is-reject" data-action="studio-ai-reject" data-path="${escapeAttr(change.path)}" title="Reject patch" aria-label="${escapeAttr(`Reject patch for ${change.path}`)}">
3472
3535
  <span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
3536
+ <span>Reject</span>
3473
3537
  </button>
3474
3538
  </div>
3475
3539
  </article>
@@ -4468,12 +4532,16 @@ function handleStudioJobEvent(id, payload) {
4468
4532
  }
4469
4533
  } else if (payload.type === "log") {
4470
4534
  if (isAiJob) {
4471
- appendStudioAiOutput(payload.data?.message ?? payload.data, "log");
4472
- if (payload.data?.data?.changedFiles) {
4535
+ const aiLogData = payload.data?.data;
4536
+ if (aiLogData?.changedFiles) {
4473
4537
  mergeStudioAiChangedFiles(payload.data.data.changedFiles);
4474
4538
  updateStudioAiSidebar();
4475
4539
  renderStudio();
4476
4540
  remountStudioEditorIfNeeded();
4541
+ } else if (aiLogData?.proposedChanges) {
4542
+ return;
4543
+ } else {
4544
+ appendStudioAiOutput(payload.data?.message ?? payload.data, "log");
4477
4545
  }
4478
4546
  } else {
4479
4547
  appendStudioTerminal(payload.data?.message ?? payload.data, "log");
@@ -4710,6 +4778,7 @@ async function mountStudioEditor(content) {
4710
4778
  modified: modifiedModel
4711
4779
  });
4712
4780
  state.studio.editorKind = "monaco-diff";
4781
+ revealStudioAiPatchChange(aiPatch);
4713
4782
  return;
4714
4783
  }
4715
4784
 
@@ -4861,6 +4930,69 @@ function applyStudioAiPatchMarkers() {
4861
4930
  );
4862
4931
  }
4863
4932
 
4933
+ function firstStudioAiPatchLocation(change) {
4934
+ const hunks = change?.hunks?.length
4935
+ ? change.hunks
4936
+ : change
4937
+ ? buildStudioAiPatchHunks(change.beforeContent ?? "", change.afterContent ?? "")
4938
+ : [];
4939
+
4940
+ for (const hunk of hunks) {
4941
+ let oldLine = Number(hunk.oldStart) || 1;
4942
+ let newLine = Number(hunk.newStart) || 1;
4943
+
4944
+ for (const line of hunk.lines ?? []) {
4945
+ if (line.type === "add" || line.type === "delete") {
4946
+ return {
4947
+ oldLine: Math.max(1, oldLine),
4948
+ newLine: Math.max(1, newLine)
4949
+ };
4950
+ }
4951
+ if (line.type === "context") {
4952
+ oldLine += 1;
4953
+ newLine += 1;
4954
+ } else if (line.type === "add") {
4955
+ newLine += 1;
4956
+ } else if (line.type === "delete") {
4957
+ oldLine += 1;
4958
+ }
4959
+ }
4960
+ }
4961
+
4962
+ return null;
4963
+ }
4964
+
4965
+ function revealStudioAiPatchChange(change) {
4966
+ const location = firstStudioAiPatchLocation(change);
4967
+ if (!location) {
4968
+ return;
4969
+ }
4970
+
4971
+ requestAnimationFrame(() => {
4972
+ if (state.studio.editorKind === "monaco-diff" && state.studio.editor) {
4973
+ const originalEditor = state.studio.editor.getOriginalEditor?.();
4974
+ const modifiedEditor = state.studio.editor.getModifiedEditor?.();
4975
+ const originalModel = originalEditor?.getModel?.();
4976
+ const modifiedModel = modifiedEditor?.getModel?.();
4977
+ const oldLine = originalModel ? clampEditorLine(originalModel, location.oldLine) : location.oldLine;
4978
+ const newLine = modifiedModel ? clampEditorLine(modifiedModel, location.newLine) : location.newLine;
4979
+
4980
+ originalEditor?.revealLineInCenter?.(oldLine);
4981
+ modifiedEditor?.revealLineInCenter?.(newLine);
4982
+ originalEditor?.setPosition?.({ lineNumber: oldLine, column: 1 });
4983
+ modifiedEditor?.setPosition?.({ lineNumber: newLine, column: 1 });
4984
+ modifiedEditor?.focus?.();
4985
+ return;
4986
+ }
4987
+
4988
+ if (state.studio.editorKind === "textarea-diff" && state.studio.editor) {
4989
+ const offset = offsetForLineColumn(state.studio.editor.value, location.oldLine, 1);
4990
+ state.studio.editor.focus();
4991
+ state.studio.editor.setSelectionRange(offset, offset);
4992
+ }
4993
+ });
4994
+ }
4995
+
4864
4996
  function revealStudioCheckNote(line, column = 1) {
4865
4997
  if (!line) {
4866
4998
  return;
@@ -7259,14 +7391,14 @@ function escapeAttr(value) {
7259
7391
  }
7260
7392
 
7261
7393
  /* ===================================================================
7262
- * Open in Library — clones from WordPress.org SVN or jumps to existing
7394
+ * Clone to Local — clones from WordPress.org SVN or jumps to existing
7263
7395
  * =================================================================== */
7264
7396
 
7265
7397
  async function openInLibrary(slug) {
7266
7398
  if (!slug) {
7267
7399
  return;
7268
7400
  }
7269
- const existing = state.local.find((entry) => entry.slug === slug);
7401
+ const existing = remotePluginLocalState({ slug }).entry;
7270
7402
  if (existing) {
7271
7403
  await openStudio("local", existing.id);
7272
7404
  return;
@@ -3203,7 +3203,7 @@ body[data-active-view="studio"] #notice-stack {
3203
3203
  .studio-main {
3204
3204
  display: grid;
3205
3205
  grid-template-columns:
3206
- var(--studio-files-width, 260px)
3206
+ var(--studio-files-width, 220px)
3207
3207
  6px
3208
3208
  minmax(0, 1fr)
3209
3209
  6px
@@ -5210,18 +5210,18 @@ body.is-studio-resizing-v iframe {
5210
5210
 
5211
5211
  .studio-ai-changes {
5212
5212
  grid-row: 3;
5213
- max-height: 120px;
5213
+ max-height: 176px;
5214
5214
  min-height: 0;
5215
5215
  overflow: auto;
5216
5216
  border-bottom: 1px solid var(--wp-border);
5217
- background: var(--wp-info-bg);
5217
+ background: var(--wp-surface-alt);
5218
5218
  }
5219
5219
 
5220
5220
  .studio-ai-changes header {
5221
5221
  align-items: center;
5222
- display: inline-flex;
5222
+ display: flex;
5223
5223
  gap: 6px;
5224
- padding: 8px 10px 5px;
5224
+ padding: 8px 10px 6px;
5225
5225
  color: var(--wp-text);
5226
5226
  font-size: 11px;
5227
5227
  }
@@ -5234,38 +5234,39 @@ body.is-studio-resizing-v iframe {
5234
5234
  }
5235
5235
 
5236
5236
  .studio-ai-change-list {
5237
- display: flex;
5238
- gap: 6px;
5239
- overflow-x: auto;
5237
+ display: grid;
5238
+ gap: 8px;
5240
5239
  padding: 0 10px 10px;
5241
5240
  }
5242
5241
 
5243
5242
  .studio-ai-change-card {
5244
5243
  display: grid;
5245
- flex: 0 0 min(220px, 82%);
5246
- grid-template-columns: minmax(0, 1fr) auto;
5247
- align-items: stretch;
5248
- border: 1px solid #b7d9ee;
5244
+ gap: 8px;
5245
+ border: 1px solid var(--wp-border);
5249
5246
  border-radius: var(--wp-radius-s);
5250
5247
  background: var(--wp-surface);
5251
5248
  box-shadow: var(--wp-shadow-sm);
5249
+ padding: 8px;
5252
5250
  }
5253
5251
 
5254
5252
  .studio-ai-change-card.is-selected {
5255
5253
  border-color: var(--wp-admin-theme-color);
5254
+ box-shadow: 0 0 0 1px var(--wp-admin-theme-color);
5256
5255
  }
5257
5256
 
5258
5257
  .studio-ai-change {
5259
- align-items: center;
5260
- display: inline-flex;
5261
- gap: 5px;
5258
+ align-items: start;
5259
+ display: grid;
5260
+ grid-template-columns: auto minmax(0, 1fr);
5261
+ gap: 8px;
5262
5262
  min-width: 0;
5263
5263
  border: 0;
5264
+ border-radius: calc(var(--wp-radius-s) - 2px);
5264
5265
  background: transparent;
5265
5266
  color: var(--wp-text);
5266
5267
  cursor: pointer;
5267
- font-size: 11px;
5268
- padding: 5px 8px;
5268
+ font-size: 12px;
5269
+ padding: 2px;
5269
5270
  text-align: left;
5270
5271
  }
5271
5272
 
@@ -5276,7 +5277,24 @@ body.is-studio-resizing-v iframe {
5276
5277
  outline: none;
5277
5278
  }
5278
5279
 
5279
- .studio-ai-change span:nth-child(2) {
5280
+ .studio-ai-change > .dashicons {
5281
+ margin-top: 1px;
5282
+ color: var(--wp-admin-theme-color);
5283
+ font-size: 16px;
5284
+ height: 16px;
5285
+ width: 16px;
5286
+ }
5287
+
5288
+ .studio-ai-change-main {
5289
+ display: grid;
5290
+ gap: 3px;
5291
+ min-width: 0;
5292
+ }
5293
+
5294
+ .studio-ai-change-path {
5295
+ color: var(--wp-heading);
5296
+ font-weight: 600;
5297
+ line-height: 1.25;
5280
5298
  overflow: hidden;
5281
5299
  text-overflow: ellipsis;
5282
5300
  white-space: nowrap;
@@ -5284,29 +5302,40 @@ body.is-studio-resizing-v iframe {
5284
5302
 
5285
5303
  .studio-ai-change small {
5286
5304
  color: var(--wp-text-muted);
5287
- font-size: 9px;
5305
+ font-size: 10px;
5306
+ letter-spacing: 0.04em;
5288
5307
  text-transform: uppercase;
5289
5308
  }
5290
5309
 
5291
5310
  .studio-ai-change-actions {
5292
5311
  display: grid;
5293
- grid-template-columns: 26px 26px;
5294
- border-left: 1px solid var(--wp-border);
5312
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5313
+ gap: 6px;
5295
5314
  }
5296
5315
 
5297
5316
  .studio-ai-change-action {
5298
- display: grid;
5299
- place-items: center;
5300
- width: 26px;
5301
- border: 0;
5302
- border-left: 1px solid var(--wp-border-soft);
5317
+ align-items: center;
5318
+ justify-content: center;
5319
+ display: inline-flex;
5320
+ gap: 5px;
5321
+ min-height: 28px;
5322
+ border: 1px solid var(--wp-border);
5323
+ border-radius: calc(var(--wp-radius-s) - 2px);
5303
5324
  background: transparent;
5304
5325
  color: var(--wp-text-muted);
5305
5326
  cursor: pointer;
5327
+ font-size: 11px;
5328
+ font-weight: 600;
5306
5329
  }
5307
5330
 
5308
- .studio-ai-change-action:first-child {
5309
- border-left: 0;
5331
+ .studio-ai-change-action.is-accept {
5332
+ border-color: rgba(0, 128, 0, 0.32);
5333
+ color: var(--wp-success);
5334
+ }
5335
+
5336
+ .studio-ai-change-action.is-reject {
5337
+ border-color: rgba(220, 38, 38, 0.32);
5338
+ color: var(--wp-error);
5310
5339
  }
5311
5340
 
5312
5341
  .studio-ai-change-action:hover,
@@ -5318,11 +5347,13 @@ body.is-studio-resizing-v iframe {
5318
5347
  .studio-ai-change-action.is-accept:hover,
5319
5348
  .studio-ai-change-action.is-accept:focus-visible {
5320
5349
  color: var(--wp-success);
5350
+ border-color: var(--wp-success);
5321
5351
  }
5322
5352
 
5323
5353
  .studio-ai-change-action.is-reject:hover,
5324
5354
  .studio-ai-change-action.is-reject:focus-visible {
5325
5355
  color: var(--wp-error);
5356
+ border-color: var(--wp-error);
5326
5357
  }
5327
5358
 
5328
5359
  .studio-ai-composer {
@@ -5561,7 +5592,7 @@ body.is-studio-resizing-v iframe {
5561
5592
  .studio-main {
5562
5593
  grid-template-columns:
5563
5594
  48px
5564
- var(--studio-files-width, 260px)
5595
+ var(--studio-files-width, 220px)
5565
5596
  6px
5566
5597
  minmax(0, 1fr)
5567
5598
  6px
@@ -5574,7 +5605,7 @@ body.is-studio-resizing-v iframe {
5574
5605
  }
5575
5606
 
5576
5607
  .studio-root.has-files.is-secondary-sidebar-collapsed .studio-main {
5577
- grid-template-columns: 48px var(--studio-files-width, 260px) 6px minmax(0, 1fr);
5608
+ grid-template-columns: 48px var(--studio-files-width, 220px) 6px minmax(0, 1fr);
5578
5609
  }
5579
5610
 
5580
5611
  .studio-root.is-files-collapsed.is-secondary-sidebar-collapsed .studio-main {
@@ -6052,7 +6083,15 @@ body.is-studio-resizing-v iframe {
6052
6083
 
6053
6084
  .studio-ai-changes {
6054
6085
  border-bottom-color: var(--studio-vscode-border);
6055
- background: #1f2937;
6086
+ background: #202020;
6087
+ }
6088
+
6089
+ .studio-ai-change-path {
6090
+ color: var(--studio-vscode-text);
6091
+ }
6092
+
6093
+ .studio-ai-change-action {
6094
+ border-color: var(--studio-vscode-border-strong);
6056
6095
  }
6057
6096
 
6058
6097
  .studio-ai-composer textarea {
@@ -6204,7 +6243,7 @@ body.is-studio-resizing-v iframe {
6204
6243
  .studio-main {
6205
6244
  grid-template-columns:
6206
6245
  48px
6207
- var(--studio-files-width, 260px)
6246
+ var(--studio-files-width, 220px)
6208
6247
  6px
6209
6248
  minmax(0, 1fr)
6210
6249
  6px
@@ -6216,7 +6255,7 @@ body.is-studio-resizing-v iframe {
6216
6255
  }
6217
6256
 
6218
6257
  .studio-root.has-files.is-secondary-sidebar-collapsed .studio-main {
6219
- grid-template-columns: 48px var(--studio-files-width, 260px) 6px minmax(0, 1fr);
6258
+ grid-template-columns: 48px var(--studio-files-width, 220px) 6px minmax(0, 1fr);
6220
6259
  }
6221
6260
 
6222
6261
  .studio-root.is-files-collapsed.is-secondary-sidebar-collapsed .studio-main {
@@ -6673,6 +6712,27 @@ td code {
6673
6712
  gap: 5px;
6674
6713
  }
6675
6714
 
6715
+ .ps-plugin-card-local-state {
6716
+ align-items: center;
6717
+ gap: 8px;
6718
+ min-height: 24px;
6719
+ }
6720
+
6721
+ .ps-plugin-card-local-state .badge {
6722
+ flex: 0 0 auto;
6723
+ }
6724
+
6725
+ .ps-plugin-card-local-state small {
6726
+ color: var(--wp-text-muted);
6727
+ display: block;
6728
+ flex: 1 1 auto;
6729
+ font-size: 12px;
6730
+ min-width: 0;
6731
+ overflow: hidden;
6732
+ text-overflow: ellipsis;
6733
+ white-space: nowrap;
6734
+ }
6735
+
6676
6736
  .ps-plugin-card-meta {
6677
6737
  display: grid;
6678
6738
  gap: 8px 16px;
@@ -7411,9 +7471,10 @@ td code {
7411
7471
  }
7412
7472
 
7413
7473
  .ps-release-tag-row {
7414
- display: flex;
7474
+ display: grid;
7475
+ grid-template-columns: minmax(0, 1fr) auto;
7415
7476
  align-items: center;
7416
- gap: 6px;
7477
+ gap: 5px 6px;
7417
7478
  padding: 5px 8px;
7418
7479
  border-bottom: 1px solid var(--wp-border-soft);
7419
7480
  min-height: 30px;
@@ -7434,12 +7495,13 @@ td code {
7434
7495
  .ps-release-tag-name {
7435
7496
  display: inline-flex;
7436
7497
  align-items: center;
7498
+ flex-wrap: wrap;
7437
7499
  gap: 5px;
7438
7500
  font-weight: 500;
7439
7501
  color: var(--wp-heading);
7440
- flex: 1 1 auto;
7441
7502
  min-width: 0;
7442
7503
  font-size: 12px;
7504
+ line-height: 1.25;
7443
7505
  }
7444
7506
 
7445
7507
  .ps-release-tag-name .dashicons {
@@ -7486,9 +7548,33 @@ td code {
7486
7548
 
7487
7549
  .ps-release-tag-actions {
7488
7550
  display: inline-flex;
7551
+ align-items: center;
7552
+ justify-content: flex-end;
7553
+ min-width: 0;
7489
7554
  gap: 4px;
7490
7555
  }
7491
7556
 
7557
+ .ps-release-tag-row.is-uncommitted {
7558
+ align-items: start;
7559
+ }
7560
+
7561
+ .ps-release-tag-row.is-uncommitted .ps-release-tag-name,
7562
+ .ps-release-tag-row.is-uncommitted .ps-release-tag-actions {
7563
+ grid-column: 1 / -1;
7564
+ }
7565
+
7566
+ .ps-release-tag-row.is-uncommitted .ps-release-tag-actions {
7567
+ display: grid;
7568
+ grid-template-columns: minmax(0, 1fr) auto;
7569
+ padding-left: 20px;
7570
+ }
7571
+
7572
+ .ps-release-tag-row.is-uncommitted .ps-release-tag-local-note {
7573
+ min-width: 0;
7574
+ white-space: normal;
7575
+ line-height: 1.15;
7576
+ }
7577
+
7492
7578
  .ps-release-tag-actions .button.is-confirming,
7493
7579
  .ps-release-confirm-button.is-confirming {
7494
7580
  background: var(--wp-warning);
@@ -8379,6 +8465,14 @@ td code {
8379
8465
  color: var(--studio-vscode-text);
8380
8466
  }
8381
8467
 
8468
+ .studio-root[data-theme="light"] .studio-ai-change-path {
8469
+ color: var(--studio-vscode-text);
8470
+ }
8471
+
8472
+ .studio-root[data-theme="light"] .studio-ai-change-action {
8473
+ border-color: var(--studio-vscode-border);
8474
+ }
8475
+
8382
8476
  .studio-root[data-theme="light"] .studio-terminal-output {
8383
8477
  background: #ffffff;
8384
8478
  }
package/composer.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "f/pressship",
2
+ "name": "automattic/pressship",
3
3
  "type": "wp-cli-package",
4
4
  "description": "Run Pressship from WP-CLI by forwarding to the Node.js Pressship package.",
5
5
  "homepage": "https://pressship.org",
@@ -22,7 +22,7 @@
22
22
  ]
23
23
  },
24
24
  "support": {
25
- "issues": "https://github.com/f/pressship/issues",
26
- "source": "https://github.com/f/pressship"
25
+ "issues": "https://github.com/Automattic/pressship/issues",
26
+ "source": "https://github.com/Automattic/pressship"
27
27
  }
28
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pressship",
3
- "version": "0.1.15",
3
+ "version": "0.2.1",
4
4
  "description": "Submit and release WordPress.org plugins from the command line.",
5
5
  "homepage": "https://pressship.org",
6
6
  "bin": {