@handsupmin/gc-tree 0.8.6 → 0.8.8

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/dist/src/hook.js CHANGED
@@ -42,11 +42,15 @@ function buildNoMatchContext({ gcBranch, currentRepo, cached, }) {
42
42
  return `[gc-tree] no match: gc-branch="${gcBranch}" repo="${currentRepo || 'unscoped'}"${cached ? ' cached=true' : ''}.`;
43
43
  }
44
44
  function buildMatchContext({ gcBranch, currentRepo, repoScopeStatus, matches, }) {
45
- return [
45
+ const lines = [
46
46
  `[gc-tree] USE FIRST: ${Math.min(matches.length, 3)} docs gc-branch="${gcBranch}" repo="${currentRepo || 'unscoped'}" scope=${repoScopeStatus}.`,
47
47
  formatMatches(matches),
48
48
  `Rule: apply these docs before tools; if insufficient, open full doc: gctree resolve --id <id>`,
49
- ].join('\n');
49
+ ];
50
+ if (repoScopeStatus === 'unmapped' && currentRepo) {
51
+ lines.push(`Note: repo "${currentRepo}" is unmapped. If it belongs here, offer to run: gctree set-repo-scope --branch ${gcBranch} --include`);
52
+ }
53
+ return lines.join('\n');
50
54
  }
51
55
  function buildSelfReviewAppend(promptCount) {
52
56
  return [
@@ -81,6 +85,7 @@ function nextCacheState(previous, { sessionId, gcBranch, currentRepo, repoScopeS
81
85
  branch_empty: changed ? false : previous.branch_empty,
82
86
  branch_excluded: changed ? false : previous.branch_excluded,
83
87
  no_match_signatures: changed ? [] : previous.no_match_signatures,
88
+ unmapped_shown_repos: previous?.unmapped_shown_repos ?? [],
84
89
  prompt_count: (previous?.prompt_count ?? 0) + 1,
85
90
  last_session_start_signature: previous?.last_session_start_signature,
86
91
  last_session_start_at: previous?.last_session_start_at,
@@ -119,6 +124,7 @@ export async function dispatchGcTreeHook({ event, home, payload, }) {
119
124
  branch_empty: previousCache?.branch_empty ?? false,
120
125
  branch_excluded: previousCache?.branch_excluded ?? false,
121
126
  no_match_signatures: previousCache?.no_match_signatures ?? [],
127
+ unmapped_shown_repos: previousCache?.unmapped_shown_repos ?? [],
122
128
  prompt_count: previousCache?.prompt_count ?? 0,
123
129
  last_session_start_signature: signature,
124
130
  last_session_start_at: now.toISOString(),
@@ -169,21 +175,42 @@ export async function dispatchGcTreeHook({ event, home, payload, }) {
169
175
  cache.branch_empty = true;
170
176
  additionalContext = buildEmptyBranchContext({ gcBranch, currentRepo, cached: wasCached });
171
177
  }
178
+ else if (repoScopeStatus === 'unmapped' && currentRepo && cache.unmapped_shown_repos.includes(currentRepo)) {
179
+ // Already showed context for this unmapped repo this session — skip silently.
180
+ cache.updated_at = now.toISOString();
181
+ await writeHookCache(home, cache);
182
+ return null;
183
+ }
172
184
  else {
173
- const query = currentRepo ? `${currentRepo} ${prompt}` : prompt;
185
+ // For unmapped repos: use prompt only (no repo prefix) to avoid bias; apply higher score threshold.
186
+ const isUnmapped = repoScopeStatus === 'unmapped';
187
+ const query = !isUnmapped && currentRepo ? `${currentRepo} ${prompt}` : prompt;
174
188
  const signature = hashQuery(query);
175
- if (cache.no_match_signatures.includes(signature)) {
189
+ if (!isUnmapped && cache.no_match_signatures.includes(signature)) {
176
190
  additionalContext = buildNoMatchContext({ gcBranch, currentRepo, cached: true });
177
191
  }
178
192
  else {
179
193
  const result = await resolveContext({ home, branch: gcBranch, query });
180
- if (result.matches.length === 0) {
194
+ const effectiveMatches = result.matches;
195
+ if (effectiveMatches.length === 0) {
196
+ if (isUnmapped) {
197
+ // Unmapped + no strong match: skip silently, no noise.
198
+ cache.updated_at = now.toISOString();
199
+ await writeHookCache(home, cache);
200
+ return null;
201
+ }
181
202
  cache.no_match_signatures = [...new Set([...cache.no_match_signatures, signature])];
182
203
  additionalContext = buildNoMatchContext({ gcBranch, currentRepo, cached: false });
183
204
  }
184
205
  else {
185
- cache.no_match_signatures = cache.no_match_signatures.filter((entry) => entry !== signature);
186
- additionalContext = buildMatchContext({ gcBranch, currentRepo, repoScopeStatus, matches: result.matches });
206
+ if (!isUnmapped) {
207
+ cache.no_match_signatures = cache.no_match_signatures.filter((entry) => entry !== signature);
208
+ }
209
+ else if (currentRepo) {
210
+ // Mark this unmapped repo as shown so we don't repeat next prompt.
211
+ cache.unmapped_shown_repos = [...new Set([...cache.unmapped_shown_repos, currentRepo])];
212
+ }
213
+ additionalContext = buildMatchContext({ gcBranch, currentRepo, repoScopeStatus, matches: effectiveMatches });
187
214
  }
188
215
  }
189
216
  if (cache.prompt_count > 0 && cache.prompt_count % SELF_REVIEW_INTERVAL === 0) {
@@ -8,8 +8,9 @@ function renderCodexAgentsSnippet() {
8
8
  '',
9
9
  '- Treat the active gctree branch as a **gc-branch** when you describe it to users.',
10
10
  '- gctree init installs SessionStart and UserPromptSubmit hooks that auto-check gc-tree before work.',
11
- '- When you encounter an unfamiliar term, acronym, concept, or domain word, follow this scope-aware protocol **before** grepping or reading code files:',
12
- ' 1. Always run `gctree resolve --query "<term>"` first. If matched, use the result directly.',
11
+ '- Before starting ANY codebase task — new feature, schema change, bug fix, admin work, or any question about how something works — run `gctree resolve` first. Do not assume you know the domain from code alone. Field names, model names, repo names, and feature names are NOT self-explanatory; always verify workflows and cross-repo relationships via gc-tree before touching code.',
12
+ '- Follow this scope-aware protocol before any grep, file read, or code exploration:',
13
+ ' 1. Always run `gctree resolve --query "<task or term>"` first. If matched, use the result directly.',
13
14
  ' 2. Only if the current repo scope is **included** (not unmapped/excluded): if step 1 found nothing, try broader related queries to check if the concept exists in any doc.',
14
15
  ' 3. If the concept exists in a doc but was not indexed → propose adding it as an Index Entry to that doc.',
15
16
  ' 4. If it does not exist anywhere → decide whether a new doc is needed and propose it to the user.',
@@ -28,8 +29,8 @@ function renderCodexBootstrapPrompt() {
28
29
  '# gctree Bootstrap',
29
30
  '',
30
31
  '- Keep the active gc-branch explicit whenever global context matters.',
31
- '- If you encounter an unfamiliar term, acronym, concept, domain word, or internal name, do **not** grep or read code first. Follow this exact order:',
32
- ' 1. Run `gctree resolve --query "<term>"`.',
32
+ '- Before any codebase task feature, schema change, bug fix, admin work do **not** grep or read code first. Follow this exact order:',
33
+ ' 1. Run `gctree resolve --query "<task or term>"`.',
33
34
  ' 2. If that misses, run broader related `gctree resolve` queries.',
34
35
  ' 3. If the concept is documented but not indexed, propose adding it as an Index Entry to the right doc.',
35
36
  ' 4. Only if gc-tree still does not answer it should you search code or repo docs.',
@@ -124,8 +125,9 @@ function renderClaudeSnippet() {
124
125
  '',
125
126
  '- Treat the active gctree branch as a **gc-branch** in user-facing language.',
126
127
  '- gctree init installs SessionStart and UserPromptSubmit hooks that auto-inject gc-tree context before every prompt.',
127
- '- When you encounter an unfamiliar term, acronym, concept, or domain word, follow this scope-aware protocol **before** grepping or reading code files:',
128
- ' 1. Always run `gctree resolve --query "<term>"` first. If matched, use the result directly.',
128
+ '- Before starting ANY codebase task — new feature, schema change, bug fix, admin work, or any question about how something works — run `gctree resolve` first. Do not assume you know the domain from code alone. Field names, model names, repo names, and feature names are NOT self-explanatory; always verify workflows and cross-repo relationships via gc-tree before touching code.',
129
+ '- Follow this scope-aware protocol before any grep, file read, or code exploration:',
130
+ ' 1. Always run `gctree resolve --query "<task or term>"` first. If matched, use the result directly.',
129
131
  ' 2. Only if the current repo scope is **included** (not unmapped/excluded): if step 1 found nothing, try broader related queries to check if the concept exists in any doc.',
130
132
  ' 3. If the concept exists in a doc but was not indexed → propose adding it as an Index Entry to that doc.',
131
133
  ' 4. If it does not exist anywhere → decide whether a new doc is needed and propose it to the user.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@handsupmin/gc-tree",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "description": "Global Context Tree, a lightweight branch-aware global context orchestrator for AI coding tools",
5
5
  "type": "module",
6
6
  "private": false,