@systemdox/mcp-server 0.1.50 → 0.1.52

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/cli.js CHANGED
@@ -592,9 +592,9 @@ function localDate(now) {
592
592
  return `${now.getFullYear()}-${p(now.getMonth() + 1)}-${p(now.getDate())}`;
593
593
  }
594
594
  function conflictCopyName(path, date, taken) {
595
- const stem = path.replace(/\.md$/, "");
595
+ const stem2 = path.replace(/\.md$/, "");
596
596
  for (let n = 1; ; n++) {
597
- const name = `${stem}.local-${date}${n === 1 ? "" : `-${n}`}.md`;
597
+ const name = `${stem2}.local-${date}${n === 1 ? "" : `-${n}`}.md`;
598
598
  if (!taken.has(name.toLowerCase())) return name;
599
599
  }
600
600
  }
@@ -1828,6 +1828,7 @@ __export(setup_mcp_exports, {
1828
1828
  writeServerEntry: () => writeServerEntry
1829
1829
  });
1830
1830
  import { existsSync as existsSync3, readFileSync } from "fs";
1831
+ import { mkdir as mkdir4 } from "fs/promises";
1831
1832
  import { join as join4 } from "path";
1832
1833
  async function validateApiKey(apiKey, apiUrl) {
1833
1834
  try {
@@ -1955,6 +1956,7 @@ async function setupMcpServer(opts) {
1955
1956
  }
1956
1957
  try {
1957
1958
  if ((await readCredentials())[workspace]?.apiKey !== apiKey) await writeCredentials(workspace, apiKey);
1959
+ await mkdir4(join4(homeDir(), ".claude", "skills"), { recursive: true });
1958
1960
  const several = Object.keys(await readCredentials()).length > 1;
1959
1961
  for (const target of selected) {
1960
1962
  const removed = await writeServerEntry(target.path, apiUrl, several ? workspace : void 0);
@@ -2000,7 +2002,7 @@ var init_setup_mcp = __esm({
2000
2002
 
2001
2003
  // src/lib/skills.ts
2002
2004
  import { createHash as createHash3 } from "crypto";
2003
- import { lstat, mkdir as mkdir4, readdir as readdir3, readFile as readFile4, rm as rm3, writeFile as writeFile4 } from "fs/promises";
2005
+ import { lstat, mkdir as mkdir5, readdir as readdir3, readFile as readFile4, rm as rm3, writeFile as writeFile4 } from "fs/promises";
2004
2006
  import { existsSync as existsSync4 } from "fs";
2005
2007
  import { homedir as homedir2 } from "os";
2006
2008
  import { dirname as dirname4, join as join5, relative, resolve as resolve3, sep } from "path";
@@ -2125,7 +2127,7 @@ async function installSkill(version, dest, { overwrite = false } = {}) {
2125
2127
  const written = [];
2126
2128
  for (const f of version.files) {
2127
2129
  const full = within(dest, f.path);
2128
- await mkdir4(dirname4(full), { recursive: true });
2130
+ await mkdir5(dirname4(full), { recursive: true });
2129
2131
  await writeFile4(full, f.content, "utf8");
2130
2132
  written.push(f.path);
2131
2133
  }
@@ -2160,6 +2162,9 @@ function fenceFor(text3) {
2160
2162
  const longest = Math.max(0, ...(text3.match(/`+/g) ?? []).map((r) => r.length));
2161
2163
  return "`".repeat(Math.max(3, longest + 1));
2162
2164
  }
2165
+ function afterInstall(skillMd) {
2166
+ return `No restart is needed: a running Claude Code session picks it up. If one does not list it yet, read ${skillMd} and follow it, or run /reload-skills.`;
2167
+ }
2163
2168
  function describeInstall(name, r) {
2164
2169
  const lines = [
2165
2170
  `Installed ${name} version ${r.version} into ${r.dest} (${r.written.length} file(s)).`
@@ -2169,7 +2174,7 @@ function describeInstall(name, r) {
2169
2174
  lines.push(`Kept, edited here and no longer in the skill: ${r.keptEdited.join(", ")}`);
2170
2175
  }
2171
2176
  if (r.keptUntracked.length) lines.push(`Kept, added here: ${r.keptUntracked.join(", ")}`);
2172
- lines.push("Start a new Claude Code session to load it.");
2177
+ lines.push(afterInstall(join5(r.dest, "SKILL.md")));
2173
2178
  return lines.join("\n");
2174
2179
  }
2175
2180
  var MANIFEST_FILE, ENTRY_FILE, PLUGIN_MANIFEST_FOLDER, MAX_FILES, MAX_FILE_BYTES, MAX_TOTAL_BYTES, NAME_RE, SEGMENT_RE, SKIPPED, SkillInstallRefused;
@@ -2296,7 +2301,7 @@ __export(plugin_path_exports, {
2296
2301
  });
2297
2302
  import { createHash as createHash4, randomBytes } from "crypto";
2298
2303
  import { existsSync as existsSync5 } from "fs";
2299
- import { mkdir as mkdir5, rename as rename2, writeFile as writeFile5 } from "fs/promises";
2304
+ import { mkdir as mkdir6, rename as rename2, writeFile as writeFile5 } from "fs/promises";
2300
2305
  import { dirname as dirname5, join as join6, resolve as resolve5, sep as sep2 } from "path";
2301
2306
  import { inflateRawSync } from "zlib";
2302
2307
  function parsePluginPathArgs(argv) {
@@ -2394,13 +2399,13 @@ async function unpackZip(zip, dest) {
2394
2399
  return full;
2395
2400
  });
2396
2401
  const data = entries2.map((e) => e.directory ? void 0 : entryData(zip, e));
2397
- await mkdir5(root, { recursive: true });
2402
+ await mkdir6(root, { recursive: true });
2398
2403
  for (const [i, entry] of entries2.entries()) {
2399
2404
  if (entry.directory) {
2400
- await mkdir5(targets[i], { recursive: true });
2405
+ await mkdir6(targets[i], { recursive: true });
2401
2406
  continue;
2402
2407
  }
2403
- await mkdir5(dirname5(targets[i]), { recursive: true });
2408
+ await mkdir6(dirname5(targets[i]), { recursive: true });
2404
2409
  await writeFile5(targets[i], data[i], { mode: entry.mode ?? 420 });
2405
2410
  }
2406
2411
  return entries2.filter((e) => !e.directory).length;
@@ -2852,6 +2857,21 @@ var init_get_guardrails = __esm({
2852
2857
  }
2853
2858
  });
2854
2859
 
2860
+ // src/lib/spec-label.ts
2861
+ function isDecisionDraft(name) {
2862
+ return name.startsWith(DECISION_PREFIX);
2863
+ }
2864
+ function specLabel(spec) {
2865
+ return isDecisionDraft(spec.name) ? "decision record" : `${spec.requirementCount} requirements`;
2866
+ }
2867
+ var DECISION_PREFIX;
2868
+ var init_spec_label = __esm({
2869
+ "src/lib/spec-label.ts"() {
2870
+ "use strict";
2871
+ DECISION_PREFIX = "ADR: ";
2872
+ }
2873
+ });
2874
+
2855
2875
  // src/tools/get-specs.ts
2856
2876
  import { z as z2 } from "zod";
2857
2877
  function registerGetSpecs(server, apiClient2) {
@@ -2918,7 +2938,7 @@ ${spec.taskContent}`);
2918
2938
  };
2919
2939
  }
2920
2940
  const text3 = filtered.map(
2921
- (s) => `- **${s.name}** (${s.draftId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
2941
+ (s) => `- **${s.name}** (${s.draftId}) \u2014 ${s.status}, ${specLabel(s)}` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
2922
2942
  ).join("\n");
2923
2943
  return {
2924
2944
  content: [
@@ -2936,11 +2956,16 @@ ${text3}`
2936
2956
  var init_get_specs = __esm({
2937
2957
  "src/tools/get-specs.ts"() {
2938
2958
  "use strict";
2959
+ init_spec_label();
2939
2960
  }
2940
2961
  });
2941
2962
 
2942
2963
  // src/tools/get-docs.ts
2943
2964
  import { z as z3 } from "zod";
2965
+ function literalPrefix(pattern) {
2966
+ const wildcard = pattern.indexOf("*");
2967
+ return wildcard < 0 ? pattern : pattern.slice(0, wildcard);
2968
+ }
2944
2969
  function matchGlob(path, pattern) {
2945
2970
  const regex = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
2946
2971
  return new RegExp(`^${regex}$`).test(path);
@@ -3001,11 +3026,17 @@ ${doc.content}`;
3001
3026
  const params = {};
3002
3027
  if (repo) params.repo = repo;
3003
3028
  if (search) params.q = search;
3029
+ if (path) {
3030
+ params.limit = PATH_FILTER_LIMIT;
3031
+ const prefix = literalPrefix(path);
3032
+ if (prefix) params.pathPrefix = prefix;
3033
+ }
3004
3034
  const response = await apiClient2.get(
3005
3035
  "/v1/docs",
3006
3036
  params
3007
3037
  );
3008
3038
  let items = response.items;
3039
+ const unread = path ? response.total - response.items.length : 0;
3009
3040
  if (path) {
3010
3041
  items = items.filter((item2) => matchGlob(item2.path, path));
3011
3042
  }
@@ -3035,16 +3066,20 @@ ${doc.content}`;
3035
3066
 
3036
3067
  ${text3}
3037
3068
 
3038
- Use doc_id for full content, or doc_id + section to fetch one section.`
3069
+ ` + (unread > 0 ? `${unread} more were not read. Start the path with a folder to narrow it.
3070
+
3071
+ ` : "") + "Use doc_id for full content, or doc_id + section to fetch one section."
3039
3072
  }
3040
3073
  ]
3041
3074
  };
3042
3075
  }
3043
3076
  );
3044
3077
  }
3078
+ var PATH_FILTER_LIMIT;
3045
3079
  var init_get_docs = __esm({
3046
3080
  "src/tools/get-docs.ts"() {
3047
3081
  "use strict";
3082
+ PATH_FILTER_LIMIT = "1000";
3048
3083
  }
3049
3084
  });
3050
3085
 
@@ -3147,7 +3182,9 @@ ${deps}`);
3147
3182
  }
3148
3183
  if (ctx.adrs.length > 0) {
3149
3184
  const adrs = ctx.adrs.map((a) => `- ${a.title}${a.repo ? ` (${a.repo})` : ""}`).join("\n");
3150
- sections.push(`## Architecture Decision Records (${ctx.adrs.length})
3185
+ const total = ctx.adrTotal ?? ctx.adrs.length;
3186
+ const count = total > ctx.adrs.length ? `${ctx.adrs.length} newest of ${total}` : `${ctx.adrs.length}`;
3187
+ sections.push(`## Architecture Decision Records (${count})
3151
3188
 
3152
3189
  ${adrs}`);
3153
3190
  }
@@ -3576,6 +3613,32 @@ function scoreSeverity(item2) {
3576
3613
  if (!item2.severity) return 0.5;
3577
3614
  return SEVERITY_SCORES[item2.severity] ?? 0.5;
3578
3615
  }
3616
+ function stem(word) {
3617
+ return word.length > 3 ? word.replace(/s$/, "") : word;
3618
+ }
3619
+ function stems(text3) {
3620
+ return new Set(
3621
+ text3.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).map(stem)
3622
+ );
3623
+ }
3624
+ function titleShare(title, keywords) {
3625
+ const wanted = stems(keywords.join(" "));
3626
+ if (wanted.size === 0) return 0;
3627
+ const held = stems(title);
3628
+ let matches = 0;
3629
+ for (const word of wanted) {
3630
+ if (held.has(word)) matches++;
3631
+ }
3632
+ return matches / wanted.size;
3633
+ }
3634
+ function scoreReference(item2, keywords) {
3635
+ const share = titleShare(item2.title, keywords);
3636
+ const score = Math.max(
3637
+ item2.relevance ?? 0,
3638
+ share >= MIN_TITLE_SHARE ? share : 0
3639
+ );
3640
+ return RECORD_PATH.test(item2.path ?? "") ? score * RECORD_FACTOR : score;
3641
+ }
3579
3642
  function extractKeywords(text3) {
3580
3643
  const stopWords = /* @__PURE__ */ new Set([
3581
3644
  "the",
@@ -3672,7 +3735,8 @@ function scoreItems(items, taskDescription, filePaths) {
3672
3735
  const keywordScore = scoreKeywordMatch(item2, keywords);
3673
3736
  const recencyScore = scoreRecency(item2);
3674
3737
  const severityScore = scoreSeverity(item2);
3675
- const score = pathScore * WEIGHT_PATH + keywordScore * WEIGHT_KEYWORD + recencyScore * WEIGHT_RECENCY + severityScore * WEIGHT_SEVERITY;
3738
+ const isReference2 = item2.type === "spec" || item2.type === "doc";
3739
+ const score = isReference2 && keywords.length > 0 ? scoreReference(item2, keywords) : pathScore * WEIGHT_PATH + keywordScore * WEIGHT_KEYWORD + recencyScore * WEIGHT_RECENCY + severityScore * WEIGHT_SEVERITY;
3676
3740
  return {
3677
3741
  type: item2.type,
3678
3742
  id: item2.id,
@@ -3681,7 +3745,7 @@ function scoreItems(items, taskDescription, filePaths) {
3681
3745
  score,
3682
3746
  tokenEstimate: estimateTokens(item2.content)
3683
3747
  };
3684
- }).sort((a, b) => b.score - a.score);
3748
+ }).filter((item2) => item2.score > 0).sort((a, b) => b.score - a.score);
3685
3749
  }
3686
3750
  function selectWithinBudget(items, maxTokens) {
3687
3751
  const selected = [];
@@ -3693,7 +3757,7 @@ function selectWithinBudget(items, maxTokens) {
3693
3757
  }
3694
3758
  return { selected, tokensUsed, totalItems: items.length };
3695
3759
  }
3696
- var WEIGHT_PATH, WEIGHT_KEYWORD, WEIGHT_RECENCY, WEIGHT_SEVERITY, SEVERITY_SCORES, CHARS_PER_TOKEN;
3760
+ var WEIGHT_PATH, WEIGHT_KEYWORD, WEIGHT_RECENCY, WEIGHT_SEVERITY, SEVERITY_SCORES, MIN_TITLE_SHARE, RECORD_PATH, RECORD_FACTOR, CHARS_PER_TOKEN;
3697
3761
  var init_scoring = __esm({
3698
3762
  "src/lib/scoring.ts"() {
3699
3763
  "use strict";
@@ -3708,6 +3772,9 @@ var init_scoring = __esm({
3708
3772
  medium: 0.5,
3709
3773
  low: 0.25
3710
3774
  };
3775
+ MIN_TITLE_SHARE = 1 / 3;
3776
+ RECORD_PATH = /(^|\/)changelog\//;
3777
+ RECORD_FACTOR = 0.5;
3711
3778
  CHARS_PER_TOKEN = 4;
3712
3779
  }
3713
3780
  });
@@ -3731,7 +3798,7 @@ ${g.fix}
3731
3798
  }
3732
3799
  function formatSpecHeadline(s) {
3733
3800
  return `### ${s.name}
3734
- \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
3801
+ \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${specLabel(s)}`;
3735
3802
  }
3736
3803
  function formatDocHeadline(d) {
3737
3804
  return `### ${d.title}
@@ -3742,6 +3809,21 @@ function formatStack(entries2) {
3742
3809
  (e) => `- ${e.name}${e.version ? ` v${e.version}` : ""}${e.notes ? ` \u2014 ${e.notes}` : ""}`
3743
3810
  ).join("\n");
3744
3811
  }
3812
+ function selectStack(entries2, words, maxTokens) {
3813
+ const named = (e) => {
3814
+ const entry = `${e.name} ${e.notes ?? ""}`.toLowerCase();
3815
+ return words.some((w) => entry.includes(w));
3816
+ };
3817
+ const ordered = [...entries2.filter(named), ...entries2.filter((e) => !named(e))];
3818
+ const shown = [];
3819
+ for (const entry of ordered) {
3820
+ if (shown.length > 0 && estimateTokens(formatStack([...shown, entry])) > maxTokens) {
3821
+ break;
3822
+ }
3823
+ shown.push(entry);
3824
+ }
3825
+ return { text: formatStack(shown), hidden: entries2.length - shown.length };
3826
+ }
3745
3827
  function formatRules(rules) {
3746
3828
  const byCategory = /* @__PURE__ */ new Map();
3747
3829
  for (const r of rules) {
@@ -3763,6 +3845,21 @@ function formatRules(rules) {
3763
3845
 
3764
3846
  ${text3.trim()}`;
3765
3847
  }
3848
+ async function findDocs(api, taskDescription) {
3849
+ const query = taskDescription.trim().slice(0, MAX_QUERY_CHARS);
3850
+ if (query) {
3851
+ try {
3852
+ const found = await api.get("/v1/docs", {
3853
+ q: query,
3854
+ limit: String(SEARCH_RESULTS)
3855
+ });
3856
+ if (found.items.length > 0) return { ...found, searched: true };
3857
+ } catch {
3858
+ }
3859
+ }
3860
+ const listed = await api.get("/v1/docs");
3861
+ return { ...listed, searched: false };
3862
+ }
3766
3863
  async function fetchSpecBody(api, draftId) {
3767
3864
  const spec = await api.get(
3768
3865
  `/v1/specs/${encodeURIComponent(draftId)}`
@@ -3841,7 +3938,9 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3841
3938
  const [rawGuardrails, rawSpecs, docs, stack, rules, docRepos] = await Promise.all([
3842
3939
  api.get("/v1/guardrails").catch(orEmpty([])),
3843
3940
  api.get("/v1/specs").catch(orEmpty([])),
3844
- api.get("/v1/docs").catch(orEmpty({ items: [] })),
3941
+ findDocs(api, taskDescription).catch(
3942
+ orEmpty({ items: [], searched: false })
3943
+ ),
3845
3944
  api.get("/v1/ai/settings/stack").catch(orEmpty([])),
3846
3945
  api.get("/v1/standards/rules").catch(orEmpty([])),
3847
3946
  // Capability states — FAIL-OPEN: an unreadable config (older backend, a
@@ -3854,6 +3953,8 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3854
3953
  const specs = disabled("requirements") && disabled("design") && disabled("specs") ? [] : rawSpecs;
3855
3954
  const refs = /* @__PURE__ */ new Map();
3856
3955
  const key = (type, id) => `${type}:${id}`;
3956
+ const docTitles = new Set(docs.items.map((d) => d.title));
3957
+ const isCopyOfDoc = (s) => isDecisionDraft(s.name) && docTitles.has(s.name.slice("ADR: ".length));
3857
3958
  const scorable = [
3858
3959
  ...guardrails.map((g) => ({
3859
3960
  type: "guardrail",
@@ -3864,12 +3965,12 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3864
3965
  severity: g.severity,
3865
3966
  updatedAt: g.updatedAt
3866
3967
  })),
3867
- ...specs.filter((s) => s.status !== "archived").map((s) => {
3968
+ ...specs.filter((s) => s.status !== "archived" && !isCopyOfDoc(s)).map((s) => {
3868
3969
  refs.set(key("spec", s.draftId), {
3869
3970
  type: "spec",
3870
3971
  id: s.draftId,
3871
3972
  title: s.name,
3872
- listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${s.requirementCount} requirements)`,
3973
+ listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${specLabel(s)})`,
3873
3974
  fetchHint: `get_specs(draft_id="${s.draftId}")`
3874
3975
  });
3875
3976
  return {
@@ -3880,7 +3981,7 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3880
3981
  updatedAt: s.updatedAt
3881
3982
  };
3882
3983
  }),
3883
- ...docs.items.map((d) => {
3984
+ ...docs.items.map((d, position) => {
3884
3985
  const section = selectSection(d.outline, taskDescription);
3885
3986
  const pointer = section ? formatSectionPointer(d.repo_full_name, d.path, section) : void 0;
3886
3987
  refs.set(key("doc", d.id), {
@@ -3899,7 +4000,9 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3899
4000
  title: d.title,
3900
4001
  content: formatDocHeadline(d),
3901
4002
  category: d.doc_type === "adr" ? "architecture" : void 0,
3902
- updatedAt: d.synced_at
4003
+ updatedAt: d.synced_at,
4004
+ path: d.path,
4005
+ relevance: docs.searched ? 1 - position / (2 * docs.items.length) : void 0
3903
4006
  };
3904
4007
  })
3905
4008
  ];
@@ -3907,9 +4010,16 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
3907
4010
  const sections = [];
3908
4011
  let overhead = 0;
3909
4012
  if (stack.length > 0) {
4013
+ const { text: text3, hidden } = selectStack(
4014
+ stack,
4015
+ [...extractKeywords(taskDescription), ...detectLanguages(filePaths)],
4016
+ Math.floor(budget * STACK_SHARE)
4017
+ );
3910
4018
  const section = `## Tech Stack
3911
4019
 
3912
- ${formatStack(stack)}`;
4020
+ ${text3}` + (hidden > 0 ? `
4021
+
4022
+ _${hidden} more with \`get_tech_stack\`._` : "");
3913
4023
  sections.push(section);
3914
4024
  overhead += estimateTokens(section);
3915
4025
  }
@@ -4028,9 +4138,10 @@ _Highest-ranked items \u2014 docs are scoped to their most relevant section. Eac
4028
4138
  const tailLines = [];
4029
4139
  for (const meta of tailCandidates) {
4030
4140
  const cost = estimateTokens(meta.listLine);
4031
- if (cost > remaining) break;
4141
+ const named = blocks.length + tailLines.length;
4142
+ if (cost > remaining && named >= MIN_REFERENCES) break;
4032
4143
  tailLines.push(meta.listLine);
4033
- remaining -= cost;
4144
+ remaining = Math.max(0, remaining - cost);
4034
4145
  }
4035
4146
  if (tailLines.length > 0) {
4036
4147
  sections.push(
@@ -4064,11 +4175,13 @@ _Ranked lower \u2014 fetch with \`get_specs\` / \`get_docs\` if you need them._
4064
4175
  _Context: ${itemsWithBody} full text, ${itemsListed} listed, ${stats.itemsOmitted} omitted \xB7 ~${tokensUsed} of ${budget} tokens` + (bodyFailures > 0 ? ` \xB7 ${bodyFailures} body fetch(es) failed` : "") + (failures.length > 0 ? ` \xB7 ${failures.length} of 5 reads failed` : "") + `_`;
4065
4176
  return { text: body + footer, stats };
4066
4177
  }
4067
- var DEFAULT_BUDGET, RESERVE_TOKENS, GUARDRAIL_SHARE, MIN_BODY_TOKENS, MAX_HYDRATED, MAX_TAIL, TAIL_SHARE, TRUNCATION_NOTICE_TOKENS, SECTION_STOP_WORDS;
4178
+ var DEFAULT_BUDGET, RESERVE_TOKENS, GUARDRAIL_SHARE, MIN_BODY_TOKENS, MAX_HYDRATED, MAX_TAIL, TAIL_SHARE, TRUNCATION_NOTICE_TOKENS, STACK_SHARE, MIN_REFERENCES, SEARCH_RESULTS, MAX_QUERY_CHARS, SECTION_STOP_WORDS;
4068
4179
  var init_context_builder = __esm({
4069
4180
  "src/lib/context-builder.ts"() {
4070
4181
  "use strict";
4182
+ init_language();
4071
4183
  init_scoring();
4184
+ init_spec_label();
4072
4185
  init_scoring();
4073
4186
  DEFAULT_BUDGET = 4e3;
4074
4187
  RESERVE_TOKENS = 200;
@@ -4078,6 +4191,10 @@ var init_context_builder = __esm({
4078
4191
  MAX_TAIL = 10;
4079
4192
  TAIL_SHARE = 0.15;
4080
4193
  TRUNCATION_NOTICE_TOKENS = 30;
4194
+ STACK_SHARE = 0.1;
4195
+ MIN_REFERENCES = 3;
4196
+ SEARCH_RESULTS = 30;
4197
+ MAX_QUERY_CHARS = 300;
4081
4198
  SECTION_STOP_WORDS = /* @__PURE__ */ new Set([
4082
4199
  "the",
4083
4200
  "a",
@@ -4953,7 +5070,7 @@ ${fence}
4953
5070
  ${f.content}${f.content.endsWith("\n") ? "" : "\n"}${fence}`;
4954
5071
  }).join("\n\n");
4955
5072
  return text(
4956
- `Skill **${version.name}** version ${version.version}: write these ${version.files.length} file(s) into ${dest}/ exactly as shown (the content between the fences), creating folders as needed. If a file there differs from ${MANIFEST_FILE}'s hash for it, it was edited: ask before replacing it. Then write ${MANIFEST_FILE} with this content, and tell the user to start a new Claude Code session.
5073
+ `Skill **${version.name}** version ${version.version}: write these ${version.files.length} file(s) into ${dest}/ exactly as shown (the content between the fences), creating folders as needed. If a file there differs from ${MANIFEST_FILE}'s hash for it, it was edited: ask before replacing it. Then write ${MANIFEST_FILE} with this content. ${afterInstall(`${dest}/SKILL.md`)}
4957
5074
 
4958
5075
  ### ${MANIFEST_FILE}
4959
5076
 
@@ -5229,7 +5346,7 @@ var init_server = __esm({
5229
5346
  init_create_prompt_template();
5230
5347
  init_skills2();
5231
5348
  init_team_setup();
5232
- SERVER_VERSION = true ? "0.1.50" : "0.0.0-dev";
5349
+ SERVER_VERSION = true ? "0.1.52" : "0.0.0-dev";
5233
5350
  }
5234
5351
  });
5235
5352