replen 1.0.12 → 1.0.13

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.
@@ -169,14 +169,15 @@ export function discoverProjects(roots) {
169
169
  if (seenGithub.has(githubFullName))
170
170
  continue;
171
171
  seenGithub.add(githubFullName);
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.
172
+ // Slug + display name both anchor on the GitHub repo NAME, not the
173
+ // local folder name. Deriving from the folder meant a folder rename (or
174
+ // an org rename like Covelent→nsokin) minted a fresh slug and the server
175
+ // inserted a duplicate row. `~/code/drone` with remote
176
+ // `nsokin/palisade-website` now registers as slug `palisade-website`.
177
+ // The repo name is also the fallback display name, so a generic
178
+ // package.json name (the Next.js starter's "nextn", etc.) doesn't stick.
179
179
  const repoName = githubFullName.split("/").pop() || dirName;
180
+ const { name, tags, primaryLanguage } = extractMetadata(repoPath, repoName);
180
181
  projects.push({
181
182
  localPath: repoPath,
182
183
  slug: normaliseSlug(repoName),
@@ -292,6 +293,17 @@ function readGitRemote(repoPath) {
292
293
  return null;
293
294
  return `${m[1]}/${m[2]}`;
294
295
  }
296
+ // Scaffold/template default package.json names that aren't real project
297
+ // names — repos cloned from the same starter all share one (the Next.js
298
+ // starter's "nextn"). Mirrors the server's GENERIC_NAMES guard.
299
+ const GENERIC_PROJECT_NAMES = new Set([
300
+ "nextn", "next-app", "create-next-app", "nextjs", "next", "my-app", "myapp",
301
+ "my-project", "myproject", "app", "web", "webapp", "frontend", "backend",
302
+ "client", "server", "project", "vite-project", "vite-app", "react-app",
303
+ "turborepo", "my-turborepo", "monorepo", "example", "template", "starter",
304
+ "boilerplate", "hello-world", "test", "demo", "untitled",
305
+ ]);
306
+ const isGenericProjectName = (n) => GENERIC_PROJECT_NAMES.has(n.trim().toLowerCase());
295
307
  function extractMetadata(repoPath, fallbackName) {
296
308
  const tags = new Set();
297
309
  let name = fallbackName;
@@ -302,7 +314,7 @@ function extractMetadata(repoPath, fallbackName) {
302
314
  primaryLanguage = "TypeScript"; // updated below if no TS detected
303
315
  try {
304
316
  const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
305
- if (typeof pkg.name === "string" && pkg.name.length > 0)
317
+ if (typeof pkg.name === "string" && pkg.name.length > 0 && !isGenericProjectName(pkg.name))
306
318
  name = pkg.name;
307
319
  if (Array.isArray(pkg.keywords)) {
308
320
  for (const k of pkg.keywords) {
@@ -41,6 +41,17 @@ Parse the JSON response. Note:
41
41
  - `filterMode` — `tags`, `zero-knowledge`, or `fingerprint`
42
42
  - `scopedTo` — confirms the project context the user has open
43
43
  - `candidates[]` — the actual list to triage
44
+ - `candidates[].priorContext` — server-attached MEMORY: the user's earlier
45
+ verdicts on this repo, and whether the matched capability is already
46
+ covered by something they adopted/ported. Trust it — fold it into your
47
+ verdict instead of re-deriving history, and don't push a candidate whose
48
+ capability is covered unless it's materially better than the incumbent.
49
+ - `candidates[].source === "re-checked"` — a repo the user DEFERRED months
50
+ ago that is still actively developed. Re-evaluate it against today's
51
+ state of the project; the original "not now" note is in `priorContext`.
52
+ - `leap` — on quiet days the response may carry ONE portfolio connection
53
+ (a cross-project / adjacency / cross-user leap) instead of candidates.
54
+ `displayText` already words it; relay that and offer to explore it.
44
55
 
45
56
  If `candidates.length === 0`, tell the user "No new candidates today for
46
57
  `<owner/name>`. Calm-cadence working as designed — 1-3 actionable
@@ -85,6 +96,10 @@ Verdicts:
85
96
  candidate's runtime is incompatible, or the candidate's not actively
86
97
  maintained. Honest skips are valuable signal; don't manufacture
87
98
  reasons to keep something.
99
+ - **defer** — genuinely interesting but not NOW (too early / v0.x churn /
100
+ blocked on a milestone the project hasn't hit). Defer is a real promise,
101
+ not a soft skip: Replen automatically re-surfaces a deferred repo after
102
+ ~3 months if it's still actively developed (`source: "re-checked"`).
88
103
 
89
104
  **Watch for word-collisions** — the most common bad match. The candidate
90
105
  shares a *word* with the matched capability but its real domain diverges:
@@ -296,6 +311,21 @@ The user hasn't set up filter-mode B's tag list. Mention it once: "Heads
296
311
  up — you'd get sharper matches if you set project tags at /settings.
297
312
  Continuing with unfiltered for now."
298
313
 
314
+ ## The Atlas vault — local memory for any agent
315
+
316
+ Replen keeps an agent-readable markdown vault at `~/.replen/atlas/` — the
317
+ user's whole portfolio as linked notes: every project and what it does,
318
+ every capability (with how it's known: `grounded`/`extracted`/`inferred`),
319
+ every past decision with its reason code, plus themes and blind spots.
320
+ The MCP server refreshes it in the background (at most twice a day);
321
+ `replen atlas` forces a rewrite.
322
+
323
+ Use it whenever you need CROSS-PROJECT context: "what else does this user
324
+ build?", "have we solved X in another repo?", "what did we decide about
325
+ Y last quarter?". Start at `MAP.md`, or call `replen_recall` for a direct
326
+ query. Reading the vault beats re-deriving the portfolio from scratch —
327
+ it's the memory layer, and it's already on disk.
328
+
299
329
  ## When NOT to run this skill
300
330
 
301
331
  - The user is mid-task and just wants help with the current thing. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replen",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
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": {