replen 1.0.11 → 1.0.12

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.
@@ -137,18 +137,17 @@ const DEP_TO_TAGS = [
137
137
  * repos) and by `githubFullName` (so cloning the same repo to two
138
138
  * paths doesn't create two project rows).
139
139
  *
140
- * Slug = the local directory basename (normalised). When two repos in
141
- * the discovery result would share a slug (e.g. `flight-controller`
142
- * under both `~/projects/drone/` and `~/work/sandbox/`), the second+
143
- * gets `-<owner>` appended to disambiguate. Keeps slugs short for the
144
- * common case while preventing server-side `uniq_profile_user_slug`
145
- * collisions.
140
+ * Slug = the GitHub repo NAME (normalised), so it's stable across local
141
+ * folder renames and org renames. When two distinct repos would share a
142
+ * slug (e.g. two `flight-controller` repos under different owners), the
143
+ * second+ gets `-<owner>` appended to disambiguate, preventing server-side
144
+ * `uniq_profile_user_slug` collisions.
146
145
  *
147
- * Identity is `githubFullName` on the server side; slug is just the
148
- * URL-safe display label. So a local `~/projects/drone/` whose remote
149
- * is `acme/aegis` keeps slug `drone` (matching how you think of it
150
- * locally) while still registering correctly against `acme/aegis` on
151
- * the dashboard.
146
+ * Identity is `githubFullName` on the server side (the bulk endpoint
147
+ * upserts by it); slug is the URL-safe display label derived from the
148
+ * repo name. So a local `~/projects/drone/` whose remote is
149
+ * `acme/palisade-website` registers as slug `palisade-website` — matching
150
+ * the repo, not the local folder.
152
151
  */
153
152
  export function discoverProjects(roots) {
154
153
  const seenPaths = new Set();
@@ -171,9 +170,16 @@ export function discoverProjects(roots) {
171
170
  continue;
172
171
  seenGithub.add(githubFullName);
173
172
  const { name, tags, primaryLanguage } = extractMetadata(repoPath, dirName);
173
+ // Slug from the GitHub repo NAME, not the local folder name. The repo
174
+ // name is the stable identity the server keys on; deriving the slug
175
+ // from the folder meant a folder rename (or an org rename like
176
+ // Covelent→nsokin) minted a fresh slug and the server inserted a
177
+ // duplicate row. `~/code/drone` with remote `nsokin/palisade-website`
178
+ // now registers as slug `palisade-website`, matching the dashboard.
179
+ const repoName = githubFullName.split("/").pop() || dirName;
174
180
  projects.push({
175
181
  localPath: repoPath,
176
- slug: normaliseSlug(dirName),
182
+ slug: normaliseSlug(repoName),
177
183
  name,
178
184
  githubFullName,
179
185
  tags,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "replen",
3
- "version": "1.0.11",
4
- "description": "Make your AI coding tools smarter. One command, no API keys. Replen scouts the OSS firehose against your projects and surfaces drop-in libraries, ideas to port, and dead deps to swap the match decision happens inside your AI tool's session on your subscription tokens. 1-3 actionable matches a month, by design.",
3
+ "version": "1.0.12",
4
+ "description": "Make your AI coding tools smarter. One command, no API keys, free. Replen watches what your projects actually do and surfaces a few things worth bringing in each month. Use one as is, port a piece of another, cherry pick an idea, or build it clean room. The match happens inside your AI tool's session. A few actionable matches a month, by design.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "replen": "dist/index.js"