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.
- package/bin/team-context.js +61 -3
- package/package.json +1 -1
package/bin/team-context.js
CHANGED
|
@@ -2215,13 +2215,24 @@ Commands:
|
|
|
2215
2215
|
const repoSlug = getRepoSlug();
|
|
2216
2216
|
const repoName = path.basename(process.cwd());
|
|
2217
2217
|
|
|
2218
|
-
//
|
|
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.
|
|
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
|
-
|
|
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