@rubytech/taskmaster 1.19.1 → 1.19.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.
@@ -120,3 +120,82 @@ export function resolveSkillInvocationPolicy(frontmatter) {
120
120
  export function resolveSkillKey(skill, entry) {
121
121
  return entry?.taskmaster?.skillKey ?? skill.name;
122
122
  }
123
+ /**
124
+ * Extract whether `embed: true` is set in the taskmaster metadata of a SKILL.md content string.
125
+ */
126
+ export function extractEmbedFlag(content) {
127
+ const frontmatter = parseFrontmatter(content);
128
+ const meta = resolveTaskmasterMetadata(frontmatter);
129
+ return meta?.embed === true;
130
+ }
131
+ /**
132
+ * Set or remove the `embed` flag in a SKILL.md content string's frontmatter metadata.
133
+ * Preserves other metadata fields. Handles the case where no metadata block exists yet.
134
+ */
135
+ export function applyEmbedFlag(content, embed) {
136
+ const normalized = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
137
+ // Parse existing metadata to preserve other fields.
138
+ const frontmatter = parseFrontmatter(normalized);
139
+ const rawMeta = frontmatter.metadata;
140
+ let metaObj = {};
141
+ if (rawMeta) {
142
+ try {
143
+ metaObj = JSON5.parse(rawMeta);
144
+ }
145
+ catch {
146
+ // If metadata is unparseable, start fresh.
147
+ }
148
+ }
149
+ // Update the taskmaster.embed field.
150
+ const taskmaster = metaObj.taskmaster && typeof metaObj.taskmaster === "object"
151
+ ? { ...metaObj.taskmaster }
152
+ : {};
153
+ if (embed) {
154
+ taskmaster.embed = true;
155
+ }
156
+ else {
157
+ delete taskmaster.embed;
158
+ }
159
+ // Clean up: if taskmaster object is empty, remove it; if metaObj is empty, remove metadata line.
160
+ const hasTaskmasterKeys = Object.keys(taskmaster).length > 0;
161
+ if (hasTaskmasterKeys) {
162
+ metaObj.taskmaster = taskmaster;
163
+ }
164
+ else {
165
+ delete metaObj.taskmaster;
166
+ }
167
+ const hasMetaKeys = Object.keys(metaObj).length > 0;
168
+ const newMetaValue = hasMetaKeys ? JSON.stringify(metaObj) : "";
169
+ // Now splice the metadata line into the frontmatter block.
170
+ if (!normalized.startsWith("---")) {
171
+ // No frontmatter at all — add one if we need metadata.
172
+ if (!newMetaValue)
173
+ return content;
174
+ return `---\nmetadata: ${newMetaValue}\n---\n${normalized}`;
175
+ }
176
+ const endIndex = normalized.indexOf("\n---", 3);
177
+ if (endIndex === -1)
178
+ return content; // Malformed frontmatter — don't touch.
179
+ const block = normalized.slice(4, endIndex);
180
+ const after = normalized.slice(endIndex + 4); // After closing ---
181
+ // Replace or add the metadata line within the frontmatter block.
182
+ const lines = block.split("\n");
183
+ let replaced = false;
184
+ const newLines = [];
185
+ for (const line of lines) {
186
+ if (/^metadata:\s/.test(line)) {
187
+ replaced = true;
188
+ if (newMetaValue) {
189
+ newLines.push(`metadata: ${newMetaValue}`);
190
+ }
191
+ // else: drop the line entirely (no metadata needed)
192
+ }
193
+ else {
194
+ newLines.push(line);
195
+ }
196
+ }
197
+ if (!replaced && newMetaValue) {
198
+ newLines.push(`metadata: ${newMetaValue}`);
199
+ }
200
+ return `---\n${newLines.join("\n")}\n---${after}`;
201
+ }
@@ -84,6 +84,7 @@ function buildSkillStatus(entry, config, prefs, eligibility, bundledSkillNames)
84
84
  const allowBundled = resolveBundledAllowlist(config);
85
85
  const blockedByAllowlist = !isBundledSkillAllowed(entry, allowBundled);
86
86
  const always = entry.taskmaster?.always === true;
87
+ const alwaysActive = entry.taskmaster?.embed === true;
87
88
  const emoji = entry.taskmaster?.emoji ?? entry.frontmatter.emoji;
88
89
  const homepageRaw = entry.taskmaster?.homepage ??
89
90
  entry.frontmatter.homepage ??
@@ -146,9 +147,7 @@ function buildSkillStatus(entry, config, prefs, eligibility, bundledSkillNames)
146
147
  missing.env.length === 0 &&
147
148
  missing.config.length === 0 &&
148
149
  missing.os.length === 0));
149
- const preloaded = bundledSkillNames
150
- ? bundledSkillNames.has(entry.skill.name)
151
- : false;
150
+ const preloaded = bundledSkillNames ? bundledSkillNames.has(entry.skill.name) : false;
152
151
  return {
153
152
  name: entry.skill.name,
154
153
  description: entry.skill.description,
@@ -160,6 +159,7 @@ function buildSkillStatus(entry, config, prefs, eligibility, bundledSkillNames)
160
159
  emoji,
161
160
  homepage,
162
161
  always,
162
+ alwaysActive,
163
163
  disabled,
164
164
  blockedByAllowlist,
165
165
  eligible,
@@ -8,11 +8,12 @@ function buildSkillsSection(params) {
8
8
  return [];
9
9
  return [
10
10
  "## Skills (mandatory)",
11
- "Before taking any action (including tool calls): scan <available_skills> <description> entries.",
12
- `- If exactly one skill clearly applies: read its SKILL.md at <location> with \`${params.readToolName}\`, then follow it.`,
11
+ "Before taking any action (including tool calls): scan ALL <available_skills> <description> entries for relevance.",
12
+ `- If one or more skills could apply (even partially): read the best match SKILL.md at <location> with \`${params.readToolName}\`, then follow it.`,
13
13
  "- If multiple could apply: choose the most specific one, then read/follow it.",
14
- "- If none clearly apply: do not read any SKILL.md.",
15
- "Skills encode expertise that improves output quality. Skipping them produces worse results even when the task seems simple.",
14
+ "- Only skip skills when the question is clearly unrelated to every skill description.",
15
+ "- When in doubt, read the skill the cost of reading is low; the cost of missing relevant knowledge is high.",
16
+ "Skills encode expertise and knowledge sources that you do not have in your training data. Skipping them produces worse results even when the task seems simple.",
16
17
  "Constraints: never read more than one skill up front; only read after selecting.",
17
18
  trimmed,
18
19
  "",
@@ -28,6 +29,7 @@ function buildMemorySection(params) {
28
29
  "## Memory Recall",
29
30
  "Memory is your knowledge base — customer profiles, business data, preferences, prior interactions, lessons, and instructions all live there. Proactively use memory_search whenever a topic might have stored context: who a person is, what was discussed before, business rules, pricing, product details, or anything that could have been recorded. Do not rely on conversation history alone — it only covers the current session. Use memory_get to pull specific lines when you know the file. If a search returns no results, say you checked.",
30
31
  "Paths for memory_get and memory_write accept either form: `memory/public/data.md` or `public/data.md` — the `memory/` prefix is added automatically when missing. Never use read or skill_read for memory content.",
32
+ "If memory_search returns no useful results for a technical or platform question, check your skills — a skill may provide an alternative knowledge source (e.g. live documentation) before you give up.",
31
33
  "",
32
34
  ];
33
35
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.19.1",
3
- "commit": "30511004b7e6a6d7a2e6bc573cacd5eedf07620c",
4
- "builtAt": "2026-03-06T14:26:40.923Z"
2
+ "version": "1.19.8",
3
+ "commit": "2776d5020a5836fa4ff5de337d0a4ba51e239d95",
4
+ "builtAt": "2026-03-06T16:01:44.873Z"
5
5
  }