wayfind 2.0.20 → 2.0.21

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.
@@ -2215,13 +2215,24 @@ Commands:
2215
2215
  const repoSlug = getRepoSlug();
2216
2216
  const repoName = path.basename(process.cwd());
2217
2217
 
2218
- // Read recent journal entries or README for context
2218
+ // Gather context from multiple signals for better suggestions
2219
2219
  let context = `Repository: ${repoSlug}\n`;
2220
+
2221
+ // 1. team-state.md (richest signal — architecture, domain language, sprint focus)
2222
+ const teamStatePath = path.join(process.cwd(), '.claude', 'team-state.md');
2223
+ if (fs.existsSync(teamStatePath)) {
2224
+ const teamState = fs.readFileSync(teamStatePath, 'utf8');
2225
+ context += `Team state (first 2000 chars):\n${teamState.slice(0, 2000)}\n`;
2226
+ }
2227
+
2228
+ // 2. README
2220
2229
  const readmePath = ['README.md', 'readme.md', 'Readme.md'].find(f => fs.existsSync(path.join(process.cwd(), f)));
2221
2230
  if (readmePath) {
2222
2231
  const readme = fs.readFileSync(path.join(process.cwd(), readmePath), 'utf8');
2223
2232
  context += `README (first 1000 chars):\n${readme.slice(0, 1000)}\n`;
2224
2233
  }
2234
+
2235
+ // 3. package.json (Node repos)
2225
2236
  const packagePath = path.join(process.cwd(), 'package.json');
2226
2237
  if (fs.existsSync(packagePath)) {
2227
2238
  const pkg = readJSONFile(packagePath);
@@ -2229,17 +2240,64 @@ Commands:
2229
2240
  if (pkg && pkg.keywords) context += `keywords: ${(pkg.keywords || []).join(', ')}\n`;
2230
2241
  }
2231
2242
 
2243
+ // 4. Top-level directory listing (reveals project structure)
2244
+ try {
2245
+ const entries = fs.readdirSync(process.cwd(), { withFileTypes: true });
2246
+ const dirs = entries.filter(e => e.isDirectory() && !e.name.startsWith('.')).map(e => e.name);
2247
+ const files = entries.filter(e => e.isFile() && !e.name.startsWith('.')).map(e => e.name);
2248
+ context += `Top-level dirs: ${dirs.join(', ')}\n`;
2249
+ context += `Top-level files: ${files.slice(0, 20).join(', ')}\n`;
2250
+ } catch { /* best effort */ }
2251
+
2252
+ // 5. Recent journal entries mentioning this repo (from team-context)
2253
+ const teamPath = getTeamContextPath();
2254
+ if (teamPath) {
2255
+ const journalsDir = path.join(teamPath, 'journals');
2256
+ if (fs.existsSync(journalsDir)) {
2257
+ try {
2258
+ const journalFiles = fs.readdirSync(journalsDir)
2259
+ .filter(f => f.endsWith('.md'))
2260
+ .sort()
2261
+ .slice(-10); // last 10 journals
2262
+ const repoBasename = path.basename(process.cwd());
2263
+ let journalContext = '';
2264
+ for (const jf of journalFiles) {
2265
+ const content = fs.readFileSync(path.join(journalsDir, jf), 'utf8');
2266
+ if (content.includes(repoBasename) || content.includes(repoSlug)) {
2267
+ // Extract lines mentioning this repo (± context)
2268
+ const lines = content.split('\n');
2269
+ const relevant = lines.filter(l =>
2270
+ l.includes(repoBasename) || l.includes(repoSlug)
2271
+ );
2272
+ if (relevant.length > 0) {
2273
+ journalContext += relevant.slice(0, 10).join('\n') + '\n';
2274
+ }
2275
+ }
2276
+ }
2277
+ if (journalContext) {
2278
+ context += `Recent journal mentions:\n${journalContext.slice(0, 1500)}\n`;
2279
+ }
2280
+ } catch { /* best effort */ }
2281
+ }
2282
+ }
2283
+
2232
2284
  const llmConfig = {
2233
2285
  provider: 'anthropic',
2234
2286
  model: process.env.TEAM_CONTEXT_HAIKU_MODEL || 'claude-haiku-4-5-20251001',
2235
2287
  api_key_env: 'ANTHROPIC_API_KEY',
2236
2288
  };
2237
2289
 
2238
- const systemPrompt = `You suggest concise feature tags for a software repository. Tags describe what features live in this repo, in both technical terms (component names, services) and business/domain language (user-facing features). Return a JSON object with two fields: "tags" (array of 5-15 short lowercase tags) and "description" (one sentence describing the repo's purpose). Return only valid JSON.`;
2290
+ const systemPrompt = `You suggest concise feature tags for a software repository. These tags help non-engineers (PMs, designers) find the right repo when asking questions like "how do RFPs work?" or "what changed with hotel matching?"
2291
+
2292
+ Prioritize business/domain language (rfp, bookings, hotel import, proposals) over technical terms (azure-functions, cosmos-db). Include a few technical tags for engineers, but lead with what the product DOES, not how it's built.
2293
+
2294
+ Return a JSON object with two fields: "tags" (array of 5-15 short lowercase tags, business terms first) and "description" (one sentence describing the repo's purpose in product language). Return only valid JSON, no markdown.`;
2239
2295
 
2240
2296
  console.log(`Analyzing ${repoSlug}...`);
2241
2297
  try {
2242
- const raw = await llm.call(llmConfig, systemPrompt, context);
2298
+ let raw = await llm.call(llmConfig, systemPrompt, context);
2299
+ // Strip markdown code fences if the LLM wraps the JSON
2300
+ raw = raw.trim().replace(/^```(?:json)?\s*\n?/i, '').replace(/\n?```\s*$/,'');
2243
2301
  const parsed = JSON.parse(raw.trim());
2244
2302
  console.log(`\nSuggested tags: ${(parsed.tags || []).join(', ')}`);
2245
2303
  if (parsed.description) console.log(`Description: ${parsed.description}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wayfind",
3
- "version": "2.0.20",
3
+ "version": "2.0.21",
4
4
  "description": "Team decision trail for AI-assisted development. The connective tissue between product, engineering, and strategy.",
5
5
  "bin": {
6
6
  "wayfind": "./bin/team-context.js"