@imdeadpool/guardex 7.0.34 → 7.0.36

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
@@ -9,6 +9,8 @@
9
9
  and human teammates working the same codebase at the same time.
10
10
  </p>
11
11
 
12
+ Guardian T-Rex for your multi-agent repo. Isolated worktrees, file locks, and PR-only merges stop parallel Codex & Claude agents from overwriting each other's work. Auto-wires Oh My Codex, Oh My Claude, OpenSpec, and Caveman. See [about_description.txt](./about_description.txt).
13
+
12
14
  <p align="center">
13
15
  <a href="https://www.npmjs.com/package/@imdeadpool/guardex"><img alt="npm version" src="https://img.shields.io/npm/v/%40imdeadpool%2Fguardex?label=npm&style=flat-square&color=cb3837&logo=npm&logoColor=white"></a>
14
16
  <a href="https://www.npmjs.com/package/@imdeadpool/guardex"><img alt="npm downloads per month" src="https://img.shields.io/npm/dm/%40imdeadpool%2Fguardex?label=downloads%2Fmonth&style=flat-square&color=0b76c5"></a>
@@ -57,7 +59,7 @@ gx setup # hooks, state, OMX / OpenSpec / caveman wiring — one shot
57
59
 
58
60
  ---
59
61
 
60
- ## `02` &nbsp;The problem
62
+ ## The problem
61
63
 
62
64
  ![Parallel agents colliding in the same files](https://raw.githubusercontent.com/recodeee/gitguardex/main/docs/images/problem-agent-collision.svg)
63
65
 
@@ -74,6 +76,10 @@ started overwriting or deleting each other's changes. More agents meant
74
76
  | `claude-a` → `test/auth.spec.ts` · ⚠ clash | `claude-a` → `agent/claude/token-rotation` · ● owned |
75
77
  | `codex-04` → `src/auth/session.ts` · ◌ stalled | `human` → `main` (protected) · ● clean |
76
78
 
79
+ ### Solution
80
+
81
+ ![Agent branch/worktree start protocol](https://raw.githubusercontent.com/recodeee/gitguardex/main/docs/images/workflow-branch-start.svg)
82
+
77
83
  ---
78
84
 
79
85
  ## `03` &nbsp;What it does
@@ -204,6 +210,12 @@ the compact layout everywhere.
204
210
  | `gx sync` | Sync current agent branch against base. |
205
211
  | `gx release` | Update the GitHub release from README notes. |
206
212
 
213
+ ```bash
214
+ gx release # create/update the current GitHub release from README notes
215
+ ```
216
+
217
+ `gx release` is the maintainer path for package releases. It reads `README.md`, finds the last published GitHub release, and writes one grouped GitHub release body.
218
+
207
219
  ### Protected branches
208
220
 
209
221
  ```bash
@@ -249,12 +261,35 @@ Being honest about where this still has issues:
249
261
 
250
262
  ---
251
263
 
264
+ ## Release notes
265
+
266
+ <details open>
267
+ <summary><strong>v7.x</strong></summary>
268
+
269
+ ### v7.0.36
270
+ - Bumped `@imdeadpool/guardex` from `7.0.35` to `7.0.36` so the latest
271
+ branch-finish cwd-prune fix can ship under a fresh npm version after PR #424.
272
+ - No new CLI command surface is introduced in this release lane.
273
+
274
+ ### v7.0.35
275
+ - Bumped `@imdeadpool/guardex` from `7.0.34` to `7.0.35` so the current
276
+ merged `main` payload can publish on a fresh npm version after PR #420.
277
+ - Refreshed README release/skills metadata and shipped Active Agents template
278
+ parity so the current `main` payload passes release verification.
279
+ - No new CLI command behavior is introduced in this release lane.
280
+
281
+ </details>
282
+
283
+ ---
284
+
252
285
  ## `10` &nbsp;Companion tools
253
286
 
254
287
  All optional — but if you're running many agents, you probably want them.
255
288
  `gx status` auto-detects each one and reports it in the `Global services`
256
289
  block.
257
290
 
291
+ Install repo skills with `npx skills add recodee/gitguardex`; `npx skills add recodee/` opens the recodee namespace. `gx setup` does not auto-run `npx skills add ...`. If the picker does not show a separate `guardex` skill, that is expected.
292
+
258
293
  | Tool | What it does | Stars |
259
294
  | --- | --- | --- |
260
295
  | [**oh-my-codex**](https://github.com/Yeachan-Heo/oh-my-codex) — `npm i -g oh-my-codex` | Codex config + skills framework. Merged into every agent worktree so each spawned Codex starts with the same tuned config. | [![stars](https://img.shields.io/github/stars/Yeachan-Heo/oh-my-codex?style=social)](https://github.com/Yeachan-Heo/oh-my-codex) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imdeadpool/guardex",
3
- "version": "7.0.34",
3
+ "version": "7.0.36",
4
4
  "description": "Guardian T-Rex for your multi-agent repo. Isolated worktrees, file locks, and PR-only merges stop parallel Codex & Claude agents from overwriting each other's work. Auto-wires Oh My Codex, Oh My Claude, OpenSpec, and Caveman.",
5
5
  "license": "MIT",
6
6
  "preferGlobal": true,
@@ -787,6 +787,15 @@ if [[ -n "$base_worktree" ]] && is_clean_worktree "$base_worktree" && [[ "$PUSH_
787
787
  fi
788
788
  maybe_auto_commit_parent_gitlink "$base_worktree"
789
789
 
790
+ # Pivot out of the agent worktree before prune calls that may remove it.
791
+ # Without this, subprocess spawns can fail with ENOENT uv_cwd after cwd
792
+ # disappears even when the merge succeeded.
793
+ pivot_to_repo_root_before_prune() {
794
+ if [[ "$current_worktree" == "$source_worktree" && "$source_worktree" == "${agent_worktree_root}"/* ]]; then
795
+ cd "$repo_root" 2>/dev/null || true
796
+ fi
797
+ }
798
+
790
799
  if [[ "$CLEANUP_AFTER_MERGE" -eq 1 ]]; then
791
800
  if [[ "$source_worktree" == "$repo_root" ]]; then
792
801
  if is_clean_worktree "$source_worktree"; then
@@ -830,17 +839,20 @@ if [[ "$CLEANUP_AFTER_MERGE" -eq 1 ]]; then
830
839
  if [[ "$DELETE_REMOTE_BRANCH" -eq 1 ]]; then
831
840
  prune_args+=(--delete-remote-branches)
832
841
  fi
842
+
843
+ pivot_to_repo_root_before_prune
833
844
  if ! run_guardex_cli worktree prune "${prune_args[@]}"; then
834
845
  echo "[agent-branch-finish] Warning: automatic worktree prune failed." >&2
835
846
  echo "[agent-branch-finish] You can run manual cleanup: gx cleanup --base ${BASE_BRANCH}" >&2
836
847
  fi
837
848
 
838
849
  echo "[agent-branch-finish] Merged '${SOURCE_BRANCH}' into '${BASE_BRANCH}' via ${merge_status} flow and cleaned source branch/worktree."
839
- if [[ "$source_worktree" == "$current_worktree" && "$source_worktree" == "${agent_worktree_root}"/* ]]; then
850
+ if [[ "$source_worktree" == "$current_worktree" && "$source_worktree" == "${agent_worktree_root}"/* && -d "$source_worktree" ]]; then
840
851
  echo "[agent-branch-finish] Current worktree '${source_worktree}' still exists because it is the active shell cwd." >&2
841
852
  echo "[agent-branch-finish] Leave this directory, then run: gx cleanup --base ${BASE_BRANCH}" >&2
842
853
  fi
843
854
  else
855
+ pivot_to_repo_root_before_prune
844
856
  if ! run_guardex_cli worktree prune --base "$BASE_BRANCH"; then
845
857
  echo "[agent-branch-finish] Warning: temporary worktree prune failed." >&2
846
858
  fi
@@ -5,6 +5,9 @@ const os = require('node:os');
5
5
  const path = require('node:path');
6
6
 
7
7
  const PATCH_COMPATIBILITY_WINDOW = 20;
8
+ const RETIRED_EXTENSION_IDS = [
9
+ 'recodeee.gitguardex-active-agents',
10
+ ];
8
11
 
9
12
  function parseOptions(argv) {
10
13
  const options = {};
@@ -65,6 +68,12 @@ function buildInstallTargets(extensionId, version, extensionsDir) {
65
68
  return targets;
66
69
  }
67
70
 
71
+ function isRetiredExtensionInstall(entryName, currentExtensionId) {
72
+ return RETIRED_EXTENSION_IDS
73
+ .filter((extensionId) => extensionId !== currentExtensionId)
74
+ .some((extensionId) => entryName === extensionId || entryName.startsWith(`${extensionId}-`));
75
+ }
76
+
68
77
  function main() {
69
78
  const repoRoot = path.resolve(__dirname, '..');
70
79
  const options = parseOptions(process.argv.slice(2));
@@ -82,11 +91,17 @@ function main() {
82
91
  const targetDirs = buildInstallTargets(extensionId, manifest.version, extensionsDir);
83
92
  const canonicalTargetDir = targetDirs[0];
84
93
  const keepDirNames = new Set(targetDirs.map((targetDir) => path.basename(targetDir)));
94
+ let retiredInstallCount = 0;
85
95
 
86
96
  for (const entry of fs.readdirSync(extensionsDir, { withFileTypes: true })) {
87
97
  if (!entry.isDirectory()) {
88
98
  continue;
89
99
  }
100
+ if (isRetiredExtensionInstall(entry.name, extensionId)) {
101
+ removeIfExists(path.join(extensionsDir, entry.name));
102
+ retiredInstallCount += 1;
103
+ continue;
104
+ }
90
105
  if (keepDirNames.has(entry.name)) {
91
106
  continue;
92
107
  }
@@ -107,6 +122,7 @@ function main() {
107
122
  process.stdout.write(
108
123
  `[guardex-active-agents] Installed ${extensionId}@${manifest.version} to ${canonicalTargetDir}\n` +
109
124
  `[guardex-active-agents] Refreshed ${targetDirs.length - 1} recent patch compatibility path(s) for already-open windows.\n` +
125
+ `[guardex-active-agents] Removed ${retiredInstallCount} retired extension install path(s).\n` +
110
126
  '[guardex-active-agents] Reload each already-open VS Code window to activate the newest Source Control companion.\n',
111
127
  );
112
128
  }
@@ -13,7 +13,7 @@ node scripts/install-vscode-active-agents-extension.js
13
13
  ```
14
14
 
15
15
  2. Reload the VS Code window.
16
- 3. In the Activity Bar, open the `Active Agents` hive icon under Source Control. Use `Start agent` to enter a task + agent name and launch the repo Guardex agent runner. The companion prefers `bash scripts/codex-agent.sh` when present, falls back to `npm run agent:codex --`, and only uses `gx branch start` as a last resort.
16
+ 3. In the Activity Bar, open the dedicated `Active Agents` hive icon. Use `Start agent` to enter a task + agent name and launch the repo Guardex agent runner. The companion prefers `bash scripts/codex-agent.sh` when present, falls back to `npm run agent:codex --`, and only uses `gx branch start` as a last resort.
17
17
 
18
18
  What it does:
19
19
 
@@ -23,6 +23,7 @@ What it does:
23
23
  - Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
24
24
  - Splits live sessions inside `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `THINKING`, `STALLED`, and `DEAD` groups so stuck, active, and inactive lanes stand out immediately.
25
25
  - Mirrors the same live state in the VS Code status bar so the selected session or active-agent count stays visible outside the tree.
26
+ - Keeps the built-in Source Control view focused on real Git repositories; the Active Agents commit command prompts for a message from its own toolbar action.
26
27
  - Shows one row per live Guardex sandbox session inside those activity groups, with changed-file rows nested under sessions that are touching files.
27
28
  - Labels session rows with provider identity and snapshot context; snapshot-backed rows use a one-letter snapshot badge such as `N` for `nagyviktor@edixa.com`.
28
29
  - Shows raw agent branch groups with the `git-branch` icon instead of the generic folder icon.
@@ -99,17 +99,29 @@ function iconColorId(iconId) {
99
99
  case 'folder':
100
100
  case 'graph':
101
101
  case 'history':
102
+ case 'dashboard':
103
+ case 'inbox':
104
+ case 'file-directory':
105
+ case 'settings-gear':
106
+ case 'folder-library':
102
107
  return 'textLink.foreground';
103
108
  case 'git-branch':
104
109
  return 'gitDecoration.modifiedResourceForeground';
105
110
  case 'account':
106
111
  return 'terminal.ansiYellow';
112
+ case 'debug-pause':
113
+ return 'terminal.ansiYellow';
107
114
  case 'sparkle':
115
+ case 'rocket':
108
116
  return 'terminal.ansiMagenta';
109
117
  case 'list-flat':
118
+ case 'device-camera':
110
119
  return 'terminal.ansiCyan';
111
120
  case 'list-tree':
121
+ case 'telescope':
112
122
  return 'terminal.ansiBlue';
123
+ case 'organization':
124
+ return 'terminal.ansiGreen';
113
125
  case 'pass-filled':
114
126
  case 'pass':
115
127
  case 'check':
@@ -453,7 +465,7 @@ function sessionCommitPlaceholder(session) {
453
465
  return 'Pick an Active Agents session to commit its worktree.';
454
466
  }
455
467
 
456
- return `Commit ${sessionIdentityLabel(session)} on ${session.branch} · ${formatCountLabel(session.lockCount || 0, 'lock')} (Ctrl+Enter)`;
468
+ return `Commit ${sessionIdentityLabel(session)} on ${session.branch} · ${formatCountLabel(session.lockCount || 0, 'lock')}`;
457
469
  }
458
470
 
459
471
  function agentNameFromBranch(branch) {
@@ -2777,12 +2789,12 @@ function buildSessionDetailItems(session) {
2777
2789
  }
2778
2790
  if (provider?.label) {
2779
2791
  items.push(new DetailItem('Provider', provider.label, {
2780
- iconId: 'sparkle',
2792
+ iconId: 'rocket',
2781
2793
  }));
2782
2794
  }
2783
2795
  if (snapshot) {
2784
2796
  items.push(new DetailItem('Snapshot', snapshot, {
2785
- iconId: 'account',
2797
+ iconId: 'device-camera',
2786
2798
  }));
2787
2799
  }
2788
2800
  if (projectRelativePath) {
@@ -2795,7 +2807,7 @@ function buildSessionDetailItems(session) {
2795
2807
  iconId: 'git-branch',
2796
2808
  }));
2797
2809
  items.push(new DetailItem('Worktree', session.worktreePath, {
2798
- iconId: 'folder',
2810
+ iconId: 'folder-library',
2799
2811
  tooltip: session.worktreePath,
2800
2812
  }));
2801
2813
  return items;
@@ -3077,12 +3089,12 @@ class ActiveAgentsProvider {
3077
3089
  const sectionItems = [
3078
3090
  new SectionItem('Overview', [
3079
3091
  new DetailItem('Summary', buildOverviewDescription(element.overview), {
3080
- iconId: 'graph',
3092
+ iconId: 'dashboard',
3081
3093
  tooltip: buildRepoTooltip(element.repoRoot, element.overview),
3082
3094
  }),
3083
3095
  ], {
3084
3096
  description: '1',
3085
- collapsedState: vscode.TreeItemCollapsibleState.Collapsed,
3097
+ iconId: 'telescope',
3086
3098
  }),
3087
3099
  ];
3088
3100
 
@@ -3100,14 +3112,14 @@ class ActiveAgentsProvider {
3100
3112
  sectionItems.push(new SectionItem('Idle / thinking', idleThinkingItems, {
3101
3113
  description: String(idleThinkingItems.length),
3102
3114
  collapsedState: vscode.TreeItemCollapsibleState.Collapsed,
3103
- iconId: 'comment-discussion',
3115
+ iconId: 'debug-pause',
3104
3116
  }));
3105
3117
  }
3106
3118
 
3107
3119
  if (element.unassignedChanges.length > 0) {
3108
3120
  sectionItems.push(new SectionItem('Unassigned changes', buildUnassignedChangeNodes(element.unassignedChanges), {
3109
3121
  description: String(element.unassignedChanges.length),
3110
- iconId: 'warning',
3122
+ iconId: 'inbox',
3111
3123
  }));
3112
3124
  }
3113
3125
 
@@ -3117,7 +3129,7 @@ class ActiveAgentsProvider {
3117
3129
  advancedItems.push(new SectionItem('Active agent tree', rawActiveAgents, {
3118
3130
  description: String(element.sessions.length),
3119
3131
  collapsedState: vscode.TreeItemCollapsibleState.Collapsed,
3120
- iconId: 'git-branch',
3132
+ iconId: 'organization',
3121
3133
  }));
3122
3134
  }
3123
3135
  const rawChangeTree = buildGroupedChangeTreeNodes(element.sessions, element.changes);
@@ -3125,14 +3137,14 @@ class ActiveAgentsProvider {
3125
3137
  advancedItems.push(new SectionItem('Raw path tree', rawChangeTree, {
3126
3138
  description: String(element.changes.length),
3127
3139
  collapsedState: vscode.TreeItemCollapsibleState.Collapsed,
3128
- iconId: 'list-tree',
3140
+ iconId: 'file-directory',
3129
3141
  }));
3130
3142
  }
3131
3143
  if (advancedItems.length > 0) {
3132
3144
  sectionItems.push(new SectionItem('Advanced details', advancedItems, {
3133
3145
  description: String(advancedItems.length),
3134
- collapsedState: vscode.TreeItemCollapsibleState.Expanded,
3135
- iconId: 'list-tree',
3146
+ collapsedState: vscode.TreeItemCollapsibleState.Collapsed,
3147
+ iconId: 'settings-gear',
3136
3148
  }));
3137
3149
  }
3138
3150
  return sectionItems;
@@ -3338,10 +3350,6 @@ function activate(context) {
3338
3350
  treeDataProvider: provider,
3339
3351
  showCollapseAll: true,
3340
3352
  });
3341
- const sourceControl = vscode.scm.createSourceControl(
3342
- 'gitguardex.activeAgents.commitInput',
3343
- 'Active Agents Commit',
3344
- );
3345
3353
  const activeAgentsStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10);
3346
3354
  activeAgentsStatusItem.name = 'GitGuardex Active Agents';
3347
3355
  activeAgentsStatusItem.command = 'gitguardex.activeAgents.focus';
@@ -3357,11 +3365,6 @@ function activate(context) {
3357
3365
  const worktreeLockWatcher = vscode.workspace.createFileSystemWatcher(WORKTREE_AGENT_LOCKS_GLOB);
3358
3366
  const managedWorktreeGitWatcher = vscode.workspace.createFileSystemWatcher(MANAGED_WORKTREE_GIT_FILES_GLOB);
3359
3367
  const logWatcher = vscode.workspace.createFileSystemWatcher(AGENT_LOG_FILES_GLOB);
3360
- const updateCommitInput = (session) => {
3361
- sourceControl.inputBox.enabled = true;
3362
- sourceControl.inputBox.visible = true;
3363
- sourceControl.inputBox.placeholder = sessionCommitPlaceholder(session);
3364
- };
3365
3368
  const updateStatusBar = () => {
3366
3369
  const selectedSession = provider.getSelectedSession();
3367
3370
  const summary = provider.getViewSummary();
@@ -3376,8 +3379,18 @@ function activate(context) {
3376
3379
  activeAgentsStatusItem.tooltip = buildActiveAgentsStatusTooltip(selectedSession, summary);
3377
3380
  activeAgentsStatusItem.show();
3378
3381
  };
3379
- updateCommitInput(null);
3380
3382
  updateStatusBar();
3383
+ const readCommitMessageForSession = async (session) => {
3384
+ const rawMessage = await vscode.window.showInputBox?.({
3385
+ prompt: `Commit ${sessionIdentityLabel(session)} worktree`,
3386
+ placeHolder: sessionCommitPlaceholder(session),
3387
+ ignoreFocusOut: true,
3388
+ });
3389
+ if (rawMessage === undefined) {
3390
+ return undefined;
3391
+ }
3392
+ return String(rawMessage).trim();
3393
+ };
3381
3394
  const commitSelectedSession = async () => {
3382
3395
  const selectedSession = provider.getSelectedSession();
3383
3396
  if (!selectedSession?.worktreePath) {
@@ -3385,12 +3398,6 @@ function activate(context) {
3385
3398
  return;
3386
3399
  }
3387
3400
 
3388
- const message = String(sourceControl.inputBox.value || '').trim();
3389
- if (!message) {
3390
- vscode.window.showInformationMessage?.('Enter a commit message first.');
3391
- return;
3392
- }
3393
-
3394
3401
  if (!fs.existsSync(selectedSession.worktreePath)) {
3395
3402
  vscode.window.showInformationMessage?.(
3396
3403
  `Selected session worktree is no longer on disk: ${selectedSession.worktreePath}`,
@@ -3398,10 +3405,18 @@ function activate(context) {
3398
3405
  return;
3399
3406
  }
3400
3407
 
3408
+ const message = await readCommitMessageForSession(selectedSession);
3409
+ if (message === undefined) {
3410
+ return;
3411
+ }
3412
+ if (!message) {
3413
+ vscode.window.showInformationMessage?.('Enter a commit message first.');
3414
+ return;
3415
+ }
3416
+
3401
3417
  try {
3402
3418
  stageWorktreeForCommit(selectedSession.worktreePath);
3403
3419
  commitWorktree(selectedSession.worktreePath, message);
3404
- sourceControl.inputBox.value = '';
3405
3420
  refresh();
3406
3421
  } catch (error) {
3407
3422
  const failure = formatGitCommandFailure(error);
@@ -3412,10 +3427,6 @@ function activate(context) {
3412
3427
  vscode.window.showErrorMessage?.(`Active Agents commit failed: ${failure}`);
3413
3428
  }
3414
3429
  };
3415
- sourceControl.acceptInputCommand = {
3416
- command: 'gitguardex.activeAgents.commitSelectedSession',
3417
- title: 'Commit Selected Session',
3418
- };
3419
3430
  const interval = setInterval(refresh, REFRESH_POLL_INTERVAL_MS);
3420
3431
  const refreshLockRegistry = (uri) => {
3421
3432
  if (uri?.fsPath) {
@@ -3425,18 +3436,15 @@ function activate(context) {
3425
3436
  };
3426
3437
 
3427
3438
  provider.onDidChangeSelectedSession((session) => {
3428
- updateCommitInput(session);
3429
3439
  updateStatusBar();
3430
3440
  decorationProvider.refresh();
3431
3441
  });
3432
3442
  provider.onDidChangeTreeData(() => {
3433
- updateCommitInput(provider.getSelectedSession());
3434
3443
  updateStatusBar();
3435
3444
  });
3436
3445
 
3437
3446
  context.subscriptions.push(
3438
3447
  treeView,
3439
- sourceControl,
3440
3448
  activeAgentsStatusItem,
3441
3449
  inspectPanelManager,
3442
3450
  refreshController,
@@ -1,4 +1,5 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#75beff" d="M8 1.5a3 3 0 0 1 3 3v1a3 3 0 1 1-6 0v-1a3 3 0 0 1 3-3Z"/>
3
- <path fill="#3794ff" d="M2.5 14c.5-2.8 2.6-4.5 5.5-4.5s5 1.7 5.5 4.5H2.5Z"/>
2
+ <circle cx="8" cy="5" r="2.5" fill="#75beff"/>
3
+ <path fill="#3794ff" d="M2.75 13.5c.5-2.4 2.6-3.9 5.25-3.9s4.75 1.5 5.25 3.9H2.75Z"/>
4
+ <circle cx="8" cy="5.1" r="1" fill="#1e1e1e" opacity=".35"/>
4
5
  </svg>
@@ -1,4 +1,7 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#89d185" d="M4 3.5a2 2 0 1 1 2.5 1.94v3.12A4 4 0 0 0 10 4.6V3h1.5v1.6a5.5 5.5 0 0 1-5 5.47v.49A2 2 0 1 1 4 12.5a2 2 0 0 1 1-1.73V5.23a2 2 0 0 1-1-1.73Zm2-.5a.5.5 0 1 0 0 1 .5.5 0 0 0 0-1Zm0 9a.5.5 0 1 0 0 1 .5.5 0 0 0 0-1Z"/>
3
- <path fill="#4ec9b0" d="M10.5 1.5H14V5h-3.5V1.5Z"/>
2
+ <circle cx="4" cy="3.5" r="1.75" fill="#89d185"/>
3
+ <circle cx="4" cy="12.5" r="1.75" fill="#89d185"/>
4
+ <circle cx="12" cy="3.5" r="1.75" fill="#4ec9b0"/>
5
+ <path fill="#89d185" d="M3.35 5h1.3v6h-1.3z"/>
6
+ <path fill="#4ec9b0" d="M12 5.25v1.5a3.5 3.5 0 0 1-3.5 3.5H5.8v-1.3H8.5A2.2 2.2 0 0 0 10.7 6.75v-1.5z"/>
4
7
  </svg>
@@ -1,4 +1,4 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#c586c0" d="M7.2 1h1.6l.4 1.7a5.4 5.4 0 0 1 1.2.5l1.5-.9 1.1 1.1-.9 1.5c.2.4.4.8.5 1.2l1.7.4v1.6l-1.7.4c-.1.4-.3.8-.5 1.2l.9 1.5-1.1 1.1-1.5-.9c-.4.2-.8.4-1.2.5L8.8 15H7.2l-.4-1.7a5.4 5.4 0 0 1-1.2-.5l-1.5.9L3 12.6l.9-1.5a5.4 5.4 0 0 1-.5-1.2l-1.7-.4V7.9l1.7-.4c.1-.4.3-.8.5-1.2L3 4.8l1.1-1.1 1.5.9c.4-.2.8-.4 1.2-.5L7.2 1Z"/>
3
- <circle cx="8" cy="8" r="2.2" fill="#1e1e1e"/>
2
+ <path fill="#c586c0" d="M7.2 1h1.6l.35 1.55c.44.12.86.29 1.24.51l1.38-.84 1.13 1.13-.84 1.38c.22.38.39.8.51 1.24l1.55.35v1.6l-1.55.35c-.12.44-.29.86-.51 1.24l.84 1.38-1.13 1.13-1.38-.84c-.38.22-.8.39-1.24.51L8.8 15h-1.6l-.35-1.55c-.44-.12-.86-.29-1.24-.51l-1.38.84-1.13-1.13.84-1.38c-.22-.38-.39-.8-.51-1.24L1.87 9.8V8.2l1.55-.35c.12-.44.29-.86.51-1.24l-.84-1.38 1.13-1.13 1.38.84c.38-.22.8-.39 1.24-.51L7.2 1Z"/>
3
+ <circle cx="8" cy="8" r="2.1" fill="#1e1e1e"/>
4
4
  </svg>
@@ -1,3 +1,4 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#ffcc66" d="M8.6 1.5 3.5 8.6h3.2L5.7 14.5l6.8-8.2H9.1l1.4-4.8H8.6Z"/>
2
+ <path fill="#ffcc66" d="M9.1 1.5 3.5 8.7h3.4l-1 5.8 7-8.4H9.3l1.35-4.6H9.1Z"/>
3
+ <path fill="#ce9178" opacity=".35" d="M9.1 1.5 3.5 8.7h3.4l.55-2.45L9.1 1.5Z"/>
3
4
  </svg>
@@ -1,5 +1,5 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#4ec9b0" d="M3 1.5h7l3 3V14.5H3V1.5Z"/>
3
- <path fill="#3794ff" d="M9.5 2.2v3h3L9.5 2.2Z"/>
4
- <path fill="#ffcc66" d="m6.9 10.6-2-2 1-1 1 1 3.2-3.2 1 1-4.2 4.2Z"/>
2
+ <path fill="#4ec9b0" d="M3.25 1.5h6.25l3.25 3.25V14.5H3.25V1.5Z"/>
3
+ <path fill="#3794ff" d="M9.5 1.75v3h3L9.5 1.75Z"/>
4
+ <path fill="#ffcc66" d="M6.9 11.1 4.7 8.9l1-1 1.2 1.2 3.3-3.3 1 1L6.9 11.1Z"/>
5
5
  </svg>
@@ -1,4 +1,4 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#dcdcaa" d="M2 2h12v12H2V2Zm2 2v8h2.5V4H4Zm4 0v8h4V4H8Z"/>
3
- <path fill="#ce9178" d="M8 6h4v1.5H8V6Zm0 3h4v1.5H8V9Z"/>
2
+ <rect x="2.25" y="2.25" width="11.5" height="11.5" rx="1.25" fill="#dcdcaa"/>
3
+ <path fill="#1e1e1e" d="m5.6 7.6-1.4-1.4.85-.85.55.55 1.55-1.55.85.85zM8.5 5.7h3.6v1.2H8.5zM5.6 11.8l-1.4-1.4.85-.85.55.55 1.55-1.55.85.85zM8.5 10h3.6v1.2H8.5z"/>
4
4
  </svg>
@@ -1,4 +1,5 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
2
- <path fill="#b5cea8" d="M3 1.5h10v13H3v-13Z"/>
3
- <path fill="#1e1e1e" d="M5 4h6v1.2H5V4Zm0 2.8h6V8H5V6.8Zm0 2.8h4.5v1.2H5V9.6Z"/>
2
+ <path fill="#b5cea8" d="M3.25 1.5h6.25l3.25 3.25V14.5H3.25V1.5Z"/>
3
+ <path fill="#4ec9b0" d="M9.5 1.75v3h3L9.5 1.75Z"/>
4
+ <path fill="#1e1e1e" d="M5 7.4h6v1.1H5zm0 2.3h6v1.1H5zm0 2.3h4v1.1H5z"/>
4
5
  </svg>