wayfind 2.0.48 → 2.0.49

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.
@@ -59,6 +59,10 @@ function splitAndLabel(content, startId) {
59
59
  * @param {Object} llmConfig - LLM config for the scoring call
60
60
  * @returns {Promise<Array<{id: number, [personaId]: number}>|null>} Scores array or null on failure
61
61
  */
62
+ // Maximum characters to send to the scoring LLM in a single call.
63
+ // Beyond this, scoring is skipped and budget truncation handles content selection.
64
+ const SCORE_MAX_CHARS = 40000;
65
+
62
66
  async function scoreItems(signalContent, journalContent, personas, llmConfig) {
63
67
  const signalResult = splitAndLabel(signalContent, 0);
64
68
  const journalResult = splitAndLabel(journalContent, signalResult.items.length);
@@ -66,6 +70,11 @@ async function scoreItems(signalContent, journalContent, personas, llmConfig) {
66
70
  const totalItems = signalResult.items.length + journalResult.items.length;
67
71
  if (totalItems === 0) return null;
68
72
 
73
+ // Skip scoring if content is too large for a reliable single LLM call.
74
+ // The token budget step will handle content selection without scoring.
75
+ const totalChars = (signalResult.labeled || '').length + (journalResult.labeled || '').length;
76
+ if (totalChars > SCORE_MAX_CHARS) return null;
77
+
69
78
  const systemPrompt = buildScoringPrompt(personas);
70
79
 
71
80
  const userParts = [];
@@ -425,7 +425,7 @@ async function teamJoin(args) {
425
425
  console.log(` Semantic search: available | ${containerEndpoint}`);
426
426
  } else {
427
427
  console.log(` Semantic search: not configured`);
428
- console.log(` Ask your team admin: wayfind deploy set-endpoint ${teamId} <url>`);
428
+ console.log(` Ask your team admin: wayfind deploy set-endpoint <url> --team ${teamId}`);
429
429
  }
430
430
  if (keyReady) {
431
431
  console.log(` Search API key: ready — rotates daily, committed to team repo`);
@@ -1053,12 +1053,26 @@ async function runDigest(args) {
1053
1053
  process.exit(1);
1054
1054
  }
1055
1055
 
1056
+ // Sanitize configured paths — connectors.json may have been written from inside a container
1057
+ // with paths like /home/node/... or /data/... that don't exist on the host. Fall back to
1058
+ // local defaults for any path that doesn't resolve on this machine.
1059
+ const digestConfig = { ...config.digest };
1060
+ if (digestConfig.store_path && !fs.existsSync(digestConfig.store_path)) {
1061
+ digestConfig.store_path = contentStore.resolveStorePath();
1062
+ }
1063
+ if (digestConfig.journal_dir && !fs.existsSync(digestConfig.journal_dir)) {
1064
+ digestConfig.journal_dir = contentStore.DEFAULT_JOURNAL_DIR;
1065
+ }
1066
+ if (digestConfig.signals_dir && !fs.existsSync(digestConfig.signals_dir)) {
1067
+ digestConfig.signals_dir = contentStore.resolveSignalsDir();
1068
+ }
1069
+
1056
1070
  // Generate digests
1057
1071
  console.log(`Generating digests for: ${personaIds.join(', ')}`);
1058
1072
  console.log(`Period: ${sinceDate} to today`);
1059
1073
  console.log('');
1060
1074
 
1061
- const result = await digest.generateDigest(config.digest, personaIds, sinceDate, (progress) => {
1075
+ const result = await digest.generateDigest(digestConfig, personaIds, sinceDate, (progress) => {
1062
1076
  if (progress.phase === 'start') {
1063
1077
  process.stdout.write(` ${progress.personaId} (${progress.index + 1}/${progress.total})... `);
1064
1078
  } else if (progress.phase === 'done') {
@@ -2139,6 +2153,15 @@ function journalSync(args) {
2139
2153
  teamFiles[teamId].push({ file, srcPath: path.join(journalDir, file) });
2140
2154
  }
2141
2155
 
2156
+ // Always update member version stamp for all registered teams, even if no files to sync.
2157
+ // This ensures the stamp stays current regardless of whether journals are flowing.
2158
+ if (config.teams) {
2159
+ for (const teamId of Object.keys(config.teams)) {
2160
+ const teamPath = getTeamContextPath(teamId);
2161
+ if (teamPath) stampMemberVersion(teamPath);
2162
+ }
2163
+ }
2164
+
2142
2165
  if (Object.keys(teamFiles).length === 0) {
2143
2166
  console.log('No journal files to sync.');
2144
2167
  return;
@@ -4033,7 +4056,8 @@ function deployTeamInit(teamId, { port } = {}) {
4033
4056
  let composeContent = fs.readFileSync(templatePath, 'utf8');
4034
4057
  composeContent = composeContent
4035
4058
  .replace(/container_name: wayfind/, `container_name: ${containerName}`)
4036
- .replace(/- "3141:3141"/, `- "${assignedPort}:3141"`);
4059
+ .replace(/- "3141:3141"/, `- "${assignedPort}:3141"`)
4060
+ .replace(/^(services:)/m, `name: ${containerName}\n\n$1`);
4037
4061
 
4038
4062
  // Inject Docker label for discovery
4039
4063
  composeContent = composeContent.replace(
@@ -4824,7 +4848,7 @@ async function indexJournalsIfAvailable() {
4824
4848
  console.log('No journal files found — skipping index.');
4825
4849
  return;
4826
4850
  }
4827
- const hasEmbeddingKey = !!process.env.OPENAI_API_KEY;
4851
+ const hasEmbeddingKey = !!(process.env.OPENAI_API_KEY || process.env.AZURE_OPENAI_EMBEDDING_ENDPOINT);
4828
4852
  console.log(`Indexing ${entries.length} journal files from ${journalDir}${hasEmbeddingKey ? ' (with embeddings)' : ''}...`);
4829
4853
  try {
4830
4854
  const stats = await contentStore.indexJournals({
@@ -5901,6 +5925,21 @@ const COMMANDS = {
5901
5925
  // Also sync public-staging docs if they exist
5902
5926
  const publicDocsDir = path.join(sourceRoot, 'public-staging', 'docs');
5903
5927
 
5928
+ // Keep plugin.json version in sync with package.json before syncing
5929
+ const pluginJsonPath = path.join(sourceRoot, 'plugin', '.claude-plugin', 'plugin.json');
5930
+ const pkgJsonPath = path.join(sourceRoot, 'package.json');
5931
+ if (fs.existsSync(pluginJsonPath) && fs.existsSync(pkgJsonPath)) {
5932
+ try {
5933
+ const pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf8'));
5934
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
5935
+ if (pluginJson.version !== pkgJson.version) {
5936
+ pluginJson.version = pkgJson.version;
5937
+ fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 2) + '\n');
5938
+ console.log(`Updated plugin.json version to ${pkgJson.version}`);
5939
+ }
5940
+ } catch {}
5941
+ }
5942
+
5904
5943
  console.log('Syncing files...');
5905
5944
  for (const item of syncItems) {
5906
5945
  const isDir = item.endsWith('/');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wayfind",
3
- "version": "2.0.48",
3
+ "version": "2.0.49",
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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wayfind",
3
- "version": "2.0.20",
3
+ "version": "2.0.48",
4
4
  "description": "Team decision trail for AI-assisted development. Session memory, decision journals, and team digests.",
5
5
  "author": {
6
6
  "name": "Wayfind",
@@ -37,7 +37,8 @@ LAST_RUN_FILE="$HOME/.claude/team-context/.last-reindex"
37
37
  if [ -f "$LAST_RUN_FILE" ]; then
38
38
  CHANGED=$(find "$HOME/.claude/projects" -name "*.jsonl" -newer "$LAST_RUN_FILE" -print -quit 2>/dev/null)
39
39
  if [ -z "$CHANGED" ]; then
40
- # No conversation files changed — skip expensive reindex, just sync journals
40
+ # No conversation files changed — skip expensive reindex, just split and sync journals
41
+ $WAYFIND journal split 2>/dev/null
41
42
  $WAYFIND journal sync 2>/dev/null &
42
43
  exit 0
43
44
  fi
@@ -50,5 +51,6 @@ $WAYFIND reindex --conversations-only --export --detect-shifts --write-stats 2>/
50
51
  mkdir -p "$HOME/.claude/team-context"
51
52
  touch "$LAST_RUN_FILE"
52
53
 
53
- # Sync authored journals to team-context repo (backgrounded)
54
+ # Split any unsuffixed journals, then sync to team-context repo (sync backgrounded)
55
+ $WAYFIND journal split 2>/dev/null
54
56
  $WAYFIND journal sync 2>/dev/null &