luckiest-co 1.0.58 → 1.0.59

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.
@@ -9,7 +9,7 @@
9
9
  "name": "luckiest",
10
10
  "source": "./",
11
11
  "description": "Plan, go, finish, plus bundled free Luckiest skills that work in Claude Code, web chat, and Cowork.",
12
- "version": "0.1.57",
12
+ "version": "0.1.58",
13
13
  "author": { "name": "Luckiest" }
14
14
  }
15
15
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luckiest",
3
3
  "description": "Plan, go, finish. Guided planning, progress dashboards, and your luckiest.co tribe inside Claude Code.",
4
- "version": "0.1.57",
4
+ "version": "0.1.58",
5
5
  "author": { "name": "Luckiest" }
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luckiest-co",
3
- "version": "1.0.58",
3
+ "version": "1.0.59",
4
4
  "description": "Luckiest for Claude Code: plan, go, finish. Your luckiest.co skills and tribe, inside Claude.",
5
5
  "bin": {
6
6
  "luckiest-co": "./bin/install.js"
@@ -1,5 +1,8 @@
1
1
  # Changelog — luckiest-research
2
2
 
3
+ ## 1.2.1 - 2026-10-31
4
+ - Think Different hand-off gathers 12 to 20 sources, up from 6.
5
+
3
6
  ## 1.2.0 - 2026-10-31
4
7
  - Routes "find a research direction nobody has tried" to **luckiest-think-different**
5
8
  and gathers 6 to 20 sources across 3+ fields when it hands off.
@@ -4,7 +4,7 @@ description: "Look anything up on the internet and come back with a sourced answ
4
4
  license: See ATTRIBUTION.md
5
5
  allowed-tools: Bash, Read, Write, WebSearch, WebFetch, AskUserQuestion
6
6
  metadata:
7
- version: "1.2.0"
7
+ version: "1.2.1"
8
8
  listing_id: luckiest-research
9
9
  author: luckiest
10
10
  ---
@@ -22,13 +22,13 @@ holding the raw fetches.
22
22
  ## Staying current
23
23
 
24
24
  On activation, call the Luckiest MCP `check_updates` tool with
25
- `{ listingId: "ab31351c-0b55-4d0d-a310-92abdc2b60aa", installedSemver: "1.2.0" }`. If it returns
25
+ `{ listingId: "ab31351c-0b55-4d0d-a310-92abdc2b60aa", installedSemver: "1.2.1" }`. If it returns
26
26
  `upToDate: false`, surface the `notice` to the user once, then continue. Do nothing
27
27
  further if `upToDate: true`. Never block on this check; if the tool is unavailable,
28
28
  proceed.
29
29
 
30
30
  When the skill's work is done, call the Luckiest MCP `report_usage` tool once with
31
- `{ listing_id: "luckiest-research", skill_version: "1.2.0", matched: true, success: <true if the skill completed, false otherwise> }`.
31
+ `{ listing_id: "luckiest-research", skill_version: "1.2.1", matched: true, success: <true if the skill completed, false otherwise> }`.
32
32
  Metadata only, never prompt text. Never block on it; if the tool is unavailable,
33
33
  skip silently.
34
34
 
@@ -68,7 +68,7 @@ Route away when another skill fits better, and say so in one line:
68
68
  - "X vs Y" or "alternatives to X" pages: **luckiest-competitors**.
69
69
  - "Find a research direction nobody has tried" or "combine ideas from these
70
70
  papers": **luckiest-think-different**. When it hands off to you for sources,
71
- gather 6 to 20 across at least 3 fields and return a list with title, URL, and
71
+ gather 12 to 20 across at least 3 fields and return a list with title, URL, and
72
72
  field per source.
73
73
 
74
74
  ## Step 2: Doctor
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1 - 2026-10-31
4
+
5
+ - Structural unavailability is graded (source Jaccard distance, field spread, field rarity) so it no longer maxes out with few sources. On a 6-source test run, the largest tie fell from 24 of 60 to 12 of 60.
6
+ - Step 1 asks for 12 to 20 sources, up from 6.
7
+
3
8
  ## 1.0.0 - 2026-10-30
4
9
 
5
10
  First Luckiest edition, adapted from alejandrohdez00/alien-space-of-science
@@ -17,7 +17,7 @@ user-invocable: true
17
17
  license: MIT. See ATTRIBUTION.md
18
18
  allowed-tools: Bash, Read, Write, WebSearch, WebFetch, AskUserQuestion
19
19
  metadata:
20
- version: "1.0.0"
20
+ version: "1.0.1"
21
21
  listing_id: luckiest-think-different
22
22
  author: luckiest
23
23
  ---
@@ -36,11 +36,11 @@ to 3 written proposals under `./think-different/<slug>/`.
36
36
  ## Staying current
37
37
 
38
38
  On activation, call the Luckiest MCP `check_updates` tool with
39
- `{ listingId: "luckiest-think-different", installedSemver: "1.0.0" }`. If
39
+ `{ listingId: "luckiest-think-different", installedSemver: "1.0.1" }`. If
40
40
  `upToDate: false`, surface the `notice` once and continue. Never block on it.
41
41
 
42
42
  When done, call `report_usage` once with
43
- `{ listing_id: "luckiest-think-different", skill_version: "1.0.0", matched: true, success: <true|false> }`.
43
+ `{ listing_id: "luckiest-think-different", skill_version: "1.0.1", matched: true, success: <true|false> }`.
44
44
  Metadata only, never prompt text. Skip silently if unavailable.
45
45
 
46
46
  ## Safety
@@ -57,12 +57,13 @@ lowercase letters, numbers, and hyphens only.
57
57
  Work in `./think-different/<slug>/`, where `<slug>` is a short name for the topic.
58
58
  Prompts for steps 2 to 4 and 7 are in `references/prompts.md`. Use them as written.
59
59
 
60
- ### 1. Gather 6 to 20 sources
60
+ ### 1. Gather 12 to 20 sources
61
61
 
62
62
  Use what the user gave (files, links, a folder). If they gave only a topic, hand
63
63
  off to **luckiest-research** to find sources across at least 3 different fields,
64
64
  then come back. Diversity of fields matters more than count: atoms from one field
65
- only produce combinations that field already knows. Save `sources.json` with an id,
65
+ only produce combinations that field already knows. Below 12 sources few atoms
66
+ are shared across sources, so step 4 has little to merge. Save `sources.json` with an id,
66
67
  title, URL or path, and field per source.
67
68
 
68
69
  ### 2. Summarize each source (methodology only)
@@ -89,7 +90,8 @@ python3 -I <skill dir>/scripts/think_different.py sample atoms.json --k 3 --n 60
89
90
  ```
90
91
 
91
92
  Do not hand-pick or reorder candidates. The script also adds a structural
92
- unavailability score: how often the atoms come from different sources and fields.
93
+ unavailability score from three parts: how little the atoms share sources, how
94
+ many fields they span, and how far they sit from the pool's crowded fields.
93
95
 
94
96
  ### 6. Score each candidate
95
97
 
@@ -9,6 +9,7 @@ scored.json: candidates.json with "coherence" (1-10) and "typical" (1-10) added
9
9
  Stdlib only. Run `python3 think_different.py selftest` to check the math.
10
10
  """
11
11
  import argparse
12
+ import collections
12
13
  import itertools
13
14
  import json
14
15
  import random
@@ -16,13 +17,20 @@ import statistics
16
17
  import sys
17
18
 
18
19
 
19
- def struct_unavailability(atoms):
20
- # Share of atom pairs that never appear in the same source, plus field spread.
20
+ def struct_unavailability(atoms, pool=None):
21
+ # Mean of three 0-1 parts, each graded so few sources do not saturate it:
22
+ # apart - mean source-set Jaccard distance over atom pairs
23
+ # spread - share of distinct fields
24
+ # rare - atoms from outside the pool's crowded fields, cited by fewer sources
21
25
  # ponytail: source co-occurrence stands in for the paper's trained author model; upgrade = full-model.md recipe
26
+ pool = pool or atoms
27
+ fields = collections.Counter(a.get("field", "") for a in pool)
22
28
  pairs = list(itertools.combinations(atoms, 2))
23
- apart = sum(1 for a, b in pairs if not set(a["sources"]) & set(b["sources"])) / len(pairs)
29
+ apart = sum(1 - len(set(a["sources"]) & set(b["sources"])) / len(set(a["sources"]) | set(b["sources"]))
30
+ for a, b in pairs) / len(pairs)
24
31
  spread = (len({a.get("field", "") for a in atoms}) - 1) / (len(atoms) - 1)
25
- return round(0.5 * apart + 0.5 * spread, 4)
32
+ rare = sum((1 - fields[a.get("field", "")] / len(pool)) / len(a["sources"]) for a in atoms) / len(atoms)
33
+ return round((apart + spread + rare) / 3, 4)
26
34
 
27
35
 
28
36
  def sample(atoms, k, n, seed=None):
@@ -41,7 +49,7 @@ def sample(atoms, k, n, seed=None):
41
49
  seen.add(combo)
42
50
  picked = [atoms[i] for i in combo]
43
51
  out.append({"id": f"C{len(out) + 1}", "atoms": [a["id"] for a in picked],
44
- "struct_unavailability": struct_unavailability(picked)})
52
+ "struct_unavailability": struct_unavailability(picked, atoms)})
45
53
  return out
46
54
 
47
55
 
@@ -65,8 +73,11 @@ def rank(cands, beta, top, floor):
65
73
 
66
74
  def selftest():
67
75
  atoms = [{"id": f"A{i}", "field": f"f{i % 3}", "sources": [f"s{i // 2}"]} for i in range(8)]
68
- assert struct_unavailability(atoms[:2]) == 0.5 # same source, two fields
69
- assert struct_unavailability([atoms[0], atoms[2], atoms[4]]) == 1.0 # all apart, three fields
76
+ same = struct_unavailability(atoms[:2], atoms) # same source, two fields
77
+ apart = struct_unavailability([atoms[0], atoms[2], atoms[4]], atoms) # all apart, three fields
78
+ assert same < apart, (same, apart)
79
+ merged = [dict(atoms[0], sources=["s0", "s1"]), atoms[2], atoms[4]] # A0 now cited twice, shares s1 with A2
80
+ assert struct_unavailability(merged, atoms) < apart # graded, not saturated at the same value
70
81
  cands = sample(atoms, 3, 1000, seed=1)
71
82
  assert len(cands) == 56 and len({tuple(c["atoms"]) for c in cands}) == 56
72
83
  pool = [{"id": "x", "coherence": 9, "typical": 2, "struct_unavailability": 0.9},