liteagents 2.11.1 → 2.12.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/CHANGELOG.md CHANGED
@@ -17,6 +17,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
17
 
18
18
  ---
19
19
 
20
+ ## [2.12.1] - 2026-07-07
21
+
22
+ ### Fixed
23
+ - **Non-Claude helper dir renamed `friction/` → `remember/`** (opencode, ampcode, droid). These tools expect a command's bundled directory to share the owning command's name; `friction.js` is run by `/remember`, so it now lives in `remember/friction.js` instead of the mismatched `friction/`. `remember.md`'s bundle-path reference updated to match. Claude keeps `friction/` — its command loader has no such naming constraint. `opencode.jsonc` needed no change (its only `friction` mention is a description string, not a path).
24
+
25
+ ---
26
+
27
+ ## [2.12.0] - 2026-07-07
28
+
29
+ ### Changed
30
+ - **Friction cluster ranking now breaks ties by intensity.** Antigen/episode clusters were ordered by tier then recurrence, with equal-recurrence ties left to incidental feed order — so a mild reaction could outrank a far more intense one that recurred equally. Added a final tiebreak on median peak friction (a value already computed), so the more intense reaction ranks first. Ranking-only: it reorders within what recurrence already gated and never promotes across the severity × recurrence 2×2 (a loud one-off stays an episode). Applied identically across all four packages.
31
+
32
+ ### Fixed
33
+ - **`validate-packages` failed 0/4 valid on every package.** `validatePackage` demanded a `<name>.md` for each selected command, but a command can legitimately ship as a helper subdirectory with no doc — `commands/friction/friction.js`, run by `/remember` after `/friction` was collapsed into it. The installer already bundles such subdirs; validation now matches that instead of requiring a resurrected `friction.md`. No user-facing command is re-added.
34
+
35
+ ---
36
+
20
37
  ## [2.11.1] - 2026-07-03
21
38
 
22
39
  ### Changed
@@ -583,7 +583,7 @@ class PackageManager {
583
583
  const selectedContent = await this.selectVariantContent(toolId, variant, availableContent);
584
584
 
585
585
  // Helper function to check if file/directory exists
586
- const checkContentExists = async (category, items, dirName, addExtension = false) => {
586
+ const checkContentExists = async (category, items, dirName, addExtension = false, allowBundleDir = false) => {
587
587
  const categoryDir = path.join(packageDir, dirName);
588
588
 
589
589
  // If directory doesn't exist but items are expected, that's an issue
@@ -611,6 +611,15 @@ class PackageManager {
611
611
  }
612
612
 
613
613
  if (!fs.existsSync(itemPath)) {
614
+ // A command may ship as a bundled helper subdirectory (no .md doc),
615
+ // e.g. friction/friction.js run by /remember. The installer bundles
616
+ // such subdirs; accept them here so validation matches install.
617
+ if (allowBundleDir) {
618
+ const bundleDir = path.join(categoryDir, item);
619
+ if (fs.existsSync(bundleDir) && fs.statSync(bundleDir).isDirectory()) {
620
+ continue;
621
+ }
622
+ }
614
623
  const displayPath = addExtension ? `${item}.md` : item;
615
624
  issues.push(`${category.slice(0, -1)} '${displayPath}' not found in ${dirName}/ (required by ${variant} variant)`);
616
625
  missingFiles++;
@@ -627,7 +636,7 @@ class PackageManager {
627
636
 
628
637
  // Validate commands (use dynamic directory name)
629
638
  const commandsDirName = availableContent.commandsDir || 'commands';
630
- await checkContentExists('commands', selectedContent.commands || [], commandsDirName, true);
639
+ await checkContentExists('commands', selectedContent.commands || [], commandsDirName, true, true);
631
640
 
632
641
  // Validate plugins (directories, like skills)
633
642
  await checkContentExists('plugins', selectedContent.plugins || [], 'plugins', false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liteagents",
3
- "version": "2.11.1",
3
+ "version": "2.12.1",
4
4
  "description": "AI development toolkit with 11 specialized agents and 17 commands including live-canvas UI design with click-to-annotate feedback. Simple one-question installer for Claude, Opencode, Ampcode, and Droid.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -2179,8 +2179,14 @@ function clusterCandidates(allCandidates) {
2179
2179
  });
2180
2180
 
2181
2181
  // Drop the noise tier (one-off + mild); rank by recurrence then severity.
2182
+ // Final tiebreak on median peak friction — graded intensity discriminates
2183
+ // among clusters that tie on tier and recurrence. Ranking only: it reorders
2184
+ // within what recurrence already gated, never promotes across the 2x2.
2182
2185
  const kept = out.filter(c => c.suggested_artifact !== 'drop');
2183
- kept.sort((a, b) => b.score - a.score || b.sessions - a.sessions);
2186
+ kept.sort((a, b) =>
2187
+ b.score - a.score
2188
+ || b.sessions - a.sessions
2189
+ || (b.median_peak || 0) - (a.median_peak || 0));
2184
2190
  return kept;
2185
2191
  }
2186
2192
 
@@ -23,7 +23,7 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
23
23
  project are behavioral lessons worth keeping everywhere. So point it at the tool's
24
24
  **global sessions root** (all projects), not a per-project directory.
25
25
 
26
- - **Locate `friction.js`** — it is bundled next to this command at `friction/friction.js`
26
+ - **Locate `friction.js`** — it is bundled next to this command at `remember/friction.js`
27
27
  (the same directory as `remember.md`, whether installed or run from the package). If it
28
28
  exists nowhere, skip to step 1 (stash-only) and tell the user friction.js is missing.
29
29
  - **Resolve the global sessions root** — probe this list top-to-bottom, use the first that
@@ -2179,8 +2179,14 @@ function clusterCandidates(allCandidates) {
2179
2179
  });
2180
2180
 
2181
2181
  // Drop the noise tier (one-off + mild); rank by recurrence then severity.
2182
+ // Final tiebreak on median peak friction — graded intensity discriminates
2183
+ // among clusters that tie on tier and recurrence. Ranking only: it reorders
2184
+ // within what recurrence already gated, never promotes across the 2x2.
2182
2185
  const kept = out.filter(c => c.suggested_artifact !== 'drop');
2183
- kept.sort((a, b) => b.score - a.score || b.sessions - a.sessions);
2186
+ kept.sort((a, b) =>
2187
+ b.score - a.score
2188
+ || b.sessions - a.sessions
2189
+ || (b.median_peak || 0) - (a.median_peak || 0));
2184
2190
  return kept;
2185
2191
  }
2186
2192
 
@@ -2179,8 +2179,14 @@ function clusterCandidates(allCandidates) {
2179
2179
  });
2180
2180
 
2181
2181
  // Drop the noise tier (one-off + mild); rank by recurrence then severity.
2182
+ // Final tiebreak on median peak friction — graded intensity discriminates
2183
+ // among clusters that tie on tier and recurrence. Ranking only: it reorders
2184
+ // within what recurrence already gated, never promotes across the 2x2.
2182
2185
  const kept = out.filter(c => c.suggested_artifact !== 'drop');
2183
- kept.sort((a, b) => b.score - a.score || b.sessions - a.sessions);
2186
+ kept.sort((a, b) =>
2187
+ b.score - a.score
2188
+ || b.sessions - a.sessions
2189
+ || (b.median_peak || 0) - (a.median_peak || 0));
2184
2190
  return kept;
2185
2191
  }
2186
2192
 
@@ -23,7 +23,7 @@ Reads all raw material (`.factory/stash/*.md` + `.factory/friction/antigen_clust
23
23
  project are behavioral lessons worth keeping everywhere. So point it at the tool's
24
24
  **global sessions root** (all projects), not a per-project directory.
25
25
 
26
- - **Locate `friction.js`** — it is bundled next to this command at `friction/friction.js`
26
+ - **Locate `friction.js`** — it is bundled next to this command at `remember/friction.js`
27
27
  (the same directory as `remember.md`, whether installed or run from the package). If it
28
28
  exists nowhere, skip to step 1 (stash-only) and tell the user friction.js is missing.
29
29
  - **Resolve the global sessions root** — probe this list top-to-bottom, use the first that
@@ -2179,8 +2179,14 @@ function clusterCandidates(allCandidates) {
2179
2179
  });
2180
2180
 
2181
2181
  // Drop the noise tier (one-off + mild); rank by recurrence then severity.
2182
+ // Final tiebreak on median peak friction — graded intensity discriminates
2183
+ // among clusters that tie on tier and recurrence. Ranking only: it reorders
2184
+ // within what recurrence already gated, never promotes across the 2x2.
2182
2185
  const kept = out.filter(c => c.suggested_artifact !== 'drop');
2183
- kept.sort((a, b) => b.score - a.score || b.sessions - a.sessions);
2186
+ kept.sort((a, b) =>
2187
+ b.score - a.score
2188
+ || b.sessions - a.sessions
2189
+ || (b.median_peak || 0) - (a.median_peak || 0));
2184
2190
  return kept;
2185
2191
  }
2186
2192
 
@@ -23,7 +23,7 @@ Reads all raw material (`.opencode/stash/*.md` + `.opencode/friction/antigen_clu
23
23
  project are behavioral lessons worth keeping everywhere. So point it at the tool's
24
24
  **global sessions root** (all projects), not a per-project directory.
25
25
 
26
- - **Locate `friction.js`** — it is bundled next to this command at `friction/friction.js`
26
+ - **Locate `friction.js`** — it is bundled next to this command at `remember/friction.js`
27
27
  (the same directory as `remember.md`, whether installed or run from the package). If it
28
28
  exists nowhere, skip to step 1 (stash-only) and tell the user friction.js is missing.
29
29
  - **Resolve the global sessions root** — probe this list top-to-bottom, use the first that