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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/skills/research/CHANGELOG.md +3 -0
- package/skills/research/SKILL.md +4 -4
- package/skills/think-different/CHANGELOG.md +5 -0
- package/skills/think-different/SKILL.md +8 -6
- package/skills/think-different/scripts/think_different.py +18 -7
package/package.json
CHANGED
|
@@ -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.
|
package/skills/research/SKILL.md
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
#
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
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},
|