@tanstack/intent 0.0.6 → 0.0.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/README.md +11 -12
- package/dist/cli.mjs +155 -129
- package/dist/display-D_XzuGnu.mjs +54 -0
- package/dist/index.d.mts +3 -17
- package/dist/index.mjs +245 -4
- package/dist/intent-library.mjs +3 -52
- package/dist/library-scanner.d.mts +1 -1
- package/dist/library-scanner.mjs +1 -1
- package/dist/{setup-BvrZZLsA.mjs → setup-DGvdyKEq.mjs} +29 -11
- package/dist/setup.d.mts +1 -1
- package/dist/setup.mjs +1 -1
- package/meta/domain-discovery/SKILL.md +40 -5
- package/meta/feedback-collection/SKILL.md +73 -62
- package/meta/tree-generator/SKILL.md +9 -1
- package/package.json +2 -1
- package/dist/feedback-BTSaBAS_.mjs +0 -299
- package/dist/feedback-PR8JNBfM.mjs +0 -3
- package/dist/init-BU1ZnUbK.mjs +0 -3
- package/dist/init-DUiDMMrN.mjs +0 -72
- /package/dist/{library-scanner-D0aP7is_.mjs → library-scanner-V9sTOhrb.mjs} +0 -0
- /package/dist/{setup-D2Bwubpw.d.mts → setup-BJ4giTKA.d.mts} +0 -0
- /package/dist/{types-B20LP96b.d.mts → types-BmnI8kFB.d.mts} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,249 @@
|
|
|
1
1
|
import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
|
|
2
2
|
import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
|
|
3
3
|
import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { t as runSetup } from "./setup-DGvdyKEq.mjs";
|
|
5
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { execFileSync, execSync } from "node:child_process";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
//#region src/feedback.ts
|
|
10
|
+
const META_FEEDBACK_REPO = "TanStack/intent";
|
|
11
|
+
const SECRET_PATTERNS = [
|
|
12
|
+
/(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/,
|
|
13
|
+
/(?:sk|pk)[-_](?:live|test)[-_][A-Za-z0-9]{24,}/,
|
|
14
|
+
/AKIA[0-9A-Z]{16}/,
|
|
15
|
+
/-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/,
|
|
16
|
+
/eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/,
|
|
17
|
+
/(?:Bearer|token)\s+[A-Za-z0-9_\-.~+/]{20,}/i,
|
|
18
|
+
/[A-Za-z0-9]{32,}(?=.*(?:key|secret|token|password))/i
|
|
19
|
+
];
|
|
20
|
+
function containsSecrets(text) {
|
|
21
|
+
return SECRET_PATTERNS.some((pattern) => pattern.test(text));
|
|
22
|
+
}
|
|
23
|
+
function hasGhCli() {
|
|
24
|
+
try {
|
|
25
|
+
execSync("gh --version", { stdio: "ignore" });
|
|
26
|
+
return true;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getHomeConfigDir() {
|
|
32
|
+
return process.env.XDG_CONFIG_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".config");
|
|
33
|
+
}
|
|
34
|
+
function resolveFrequency(root) {
|
|
35
|
+
const userConfigPath = join(getHomeConfigDir(), "intent", "config.json");
|
|
36
|
+
try {
|
|
37
|
+
const userCfg = JSON.parse(readFileSync(userConfigPath, "utf8"));
|
|
38
|
+
if (userCfg.feedback?.frequency) return userCfg.feedback.frequency;
|
|
39
|
+
} catch {}
|
|
40
|
+
const projectConfigPath = join(root, "intent.config.json");
|
|
41
|
+
try {
|
|
42
|
+
const projCfg = JSON.parse(readFileSync(projectConfigPath, "utf8"));
|
|
43
|
+
if (projCfg.feedback?.frequency) return projCfg.feedback.frequency;
|
|
44
|
+
} catch {}
|
|
45
|
+
return "every-5";
|
|
46
|
+
}
|
|
47
|
+
const REQUIRED_FIELDS = [
|
|
48
|
+
"skill",
|
|
49
|
+
"package",
|
|
50
|
+
"skillVersion",
|
|
51
|
+
"task",
|
|
52
|
+
"whatWorked",
|
|
53
|
+
"whatFailed",
|
|
54
|
+
"missing",
|
|
55
|
+
"selfCorrections",
|
|
56
|
+
"userRating"
|
|
57
|
+
];
|
|
58
|
+
function validatePayload(payload) {
|
|
59
|
+
const errors = [];
|
|
60
|
+
if (!payload || typeof payload !== "object") return {
|
|
61
|
+
valid: false,
|
|
62
|
+
errors: ["Payload must be a JSON object"]
|
|
63
|
+
};
|
|
64
|
+
const obj = payload;
|
|
65
|
+
for (const field of REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
|
|
66
|
+
if (obj.userRating && ![
|
|
67
|
+
"good",
|
|
68
|
+
"mixed",
|
|
69
|
+
"bad"
|
|
70
|
+
].includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
|
|
71
|
+
if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
|
|
72
|
+
return {
|
|
73
|
+
valid: errors.length === 0,
|
|
74
|
+
errors
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const META_REQUIRED_FIELDS = [
|
|
78
|
+
"metaSkill",
|
|
79
|
+
"library",
|
|
80
|
+
"agentUsed",
|
|
81
|
+
"artifactQuality",
|
|
82
|
+
"whatWorked",
|
|
83
|
+
"whatFailed",
|
|
84
|
+
"suggestions",
|
|
85
|
+
"userRating"
|
|
86
|
+
];
|
|
87
|
+
const VALID_META_SKILLS = [
|
|
88
|
+
"domain-discovery",
|
|
89
|
+
"tree-generator",
|
|
90
|
+
"generate-skill",
|
|
91
|
+
"skill-staleness-check"
|
|
92
|
+
];
|
|
93
|
+
const VALID_AGENTS = [
|
|
94
|
+
"claude-code",
|
|
95
|
+
"cursor",
|
|
96
|
+
"copilot",
|
|
97
|
+
"codex",
|
|
98
|
+
"other"
|
|
99
|
+
];
|
|
100
|
+
const VALID_QUALITY_RATINGS = [
|
|
101
|
+
"good",
|
|
102
|
+
"mixed",
|
|
103
|
+
"bad"
|
|
104
|
+
];
|
|
105
|
+
function validateMetaPayload(payload) {
|
|
106
|
+
const errors = [];
|
|
107
|
+
if (!payload || typeof payload !== "object") return {
|
|
108
|
+
valid: false,
|
|
109
|
+
errors: ["Payload must be a JSON object"]
|
|
110
|
+
};
|
|
111
|
+
const obj = payload;
|
|
112
|
+
for (const field of META_REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
|
|
113
|
+
if (obj.metaSkill && !VALID_META_SKILLS.includes(obj.metaSkill)) errors.push(`metaSkill must be one of: ${VALID_META_SKILLS.join(", ")}`);
|
|
114
|
+
if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed)) errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(", ")}`);
|
|
115
|
+
if (obj.artifactQuality && !VALID_QUALITY_RATINGS.includes(obj.artifactQuality)) errors.push("artifactQuality must be one of: good, mixed, bad");
|
|
116
|
+
if (obj.userRating && !VALID_QUALITY_RATINGS.includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
|
|
117
|
+
if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
|
|
118
|
+
return {
|
|
119
|
+
valid: errors.length === 0,
|
|
120
|
+
errors
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function metaToMarkdown(payload) {
|
|
124
|
+
const lines = [
|
|
125
|
+
`# Meta-Skill Feedback: ${payload.metaSkill}`,
|
|
126
|
+
"",
|
|
127
|
+
`**Library:** ${payload.library}`,
|
|
128
|
+
`**Agent:** ${payload.agentUsed}`,
|
|
129
|
+
`**Artifact quality:** ${payload.artifactQuality}`,
|
|
130
|
+
`**Rating:** ${payload.userRating}`
|
|
131
|
+
];
|
|
132
|
+
if (payload.interviewQuality) lines.push(`**Interview quality:** ${payload.interviewQuality}`);
|
|
133
|
+
if (payload.failureModeQuality) lines.push(`**Failure mode quality:** ${payload.failureModeQuality}`);
|
|
134
|
+
lines.push("", "## What Worked", payload.whatWorked, "", "## What Failed", payload.whatFailed, "", "## Suggestions", payload.suggestions);
|
|
135
|
+
return lines.join("\n") + "\n";
|
|
136
|
+
}
|
|
137
|
+
function toMarkdown(payload) {
|
|
138
|
+
const lines = [
|
|
139
|
+
`# Skill Feedback: ${payload.skill}`,
|
|
140
|
+
"",
|
|
141
|
+
`**Package:** ${payload.package}`,
|
|
142
|
+
`**Skill version:** ${payload.skillVersion}`,
|
|
143
|
+
`**Rating:** ${payload.userRating}`,
|
|
144
|
+
"",
|
|
145
|
+
"## Task",
|
|
146
|
+
payload.task,
|
|
147
|
+
"",
|
|
148
|
+
"## What Worked",
|
|
149
|
+
payload.whatWorked,
|
|
150
|
+
"",
|
|
151
|
+
"## What Failed",
|
|
152
|
+
payload.whatFailed,
|
|
153
|
+
"",
|
|
154
|
+
"## Missing",
|
|
155
|
+
payload.missing,
|
|
156
|
+
"",
|
|
157
|
+
"## Self-Corrections",
|
|
158
|
+
payload.selfCorrections
|
|
159
|
+
];
|
|
160
|
+
if (payload.userComments) lines.push("", "## User Comments", payload.userComments);
|
|
161
|
+
return lines.join("\n") + "\n";
|
|
162
|
+
}
|
|
163
|
+
function submitFeedback(payload, repo, opts) {
|
|
164
|
+
const md = toMarkdown(payload);
|
|
165
|
+
if (opts.ghAvailable) try {
|
|
166
|
+
execFileSync("gh", [
|
|
167
|
+
"issue",
|
|
168
|
+
"create",
|
|
169
|
+
"--repo",
|
|
170
|
+
repo,
|
|
171
|
+
"--title",
|
|
172
|
+
`Skill Feedback: ${payload.skill} (${payload.userRating})`,
|
|
173
|
+
"--body",
|
|
174
|
+
"-"
|
|
175
|
+
], {
|
|
176
|
+
input: md,
|
|
177
|
+
stdio: [
|
|
178
|
+
"pipe",
|
|
179
|
+
"pipe",
|
|
180
|
+
"pipe"
|
|
181
|
+
]
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
method: "gh",
|
|
185
|
+
detail: `Submitted issue to ${repo}`
|
|
186
|
+
};
|
|
187
|
+
} catch (err) {
|
|
188
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
189
|
+
console.error(`GitHub submission failed: ${msg}`);
|
|
190
|
+
console.error("Falling back to file output.");
|
|
191
|
+
}
|
|
192
|
+
if (opts.outputPath) {
|
|
193
|
+
writeFileSync(opts.outputPath, md, "utf8");
|
|
194
|
+
return {
|
|
195
|
+
method: "file",
|
|
196
|
+
detail: `Saved to ${opts.outputPath}`
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
method: "stdout",
|
|
201
|
+
detail: md
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function submitMetaFeedback(payload, opts) {
|
|
205
|
+
const md = metaToMarkdown(payload);
|
|
206
|
+
if (opts.ghAvailable) try {
|
|
207
|
+
execFileSync("gh", [
|
|
208
|
+
"issue",
|
|
209
|
+
"create",
|
|
210
|
+
"--repo",
|
|
211
|
+
META_FEEDBACK_REPO,
|
|
212
|
+
"--title",
|
|
213
|
+
`Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})`,
|
|
214
|
+
"--label",
|
|
215
|
+
`feedback:${payload.metaSkill}`,
|
|
216
|
+
"--body",
|
|
217
|
+
"-"
|
|
218
|
+
], {
|
|
219
|
+
input: md,
|
|
220
|
+
stdio: [
|
|
221
|
+
"pipe",
|
|
222
|
+
"pipe",
|
|
223
|
+
"pipe"
|
|
224
|
+
]
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
method: "gh",
|
|
228
|
+
detail: `Submitted issue to ${META_FEEDBACK_REPO}`
|
|
229
|
+
};
|
|
230
|
+
} catch (err) {
|
|
231
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
232
|
+
console.error(`GitHub submission failed: ${msg}`);
|
|
233
|
+
console.error("Falling back to file output.");
|
|
234
|
+
}
|
|
235
|
+
if (opts.outputPath) {
|
|
236
|
+
writeFileSync(opts.outputPath, md, "utf8");
|
|
237
|
+
return {
|
|
238
|
+
method: "file",
|
|
239
|
+
detail: `Saved to ${opts.outputPath}`
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
method: "stdout",
|
|
244
|
+
detail: md
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
//#endregion
|
|
249
|
+
export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runSetup, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|
package/dist/intent-library.mjs
CHANGED
|
@@ -1,57 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./utils-DH3jY3CI.mjs";
|
|
3
|
-
import { t as
|
|
3
|
+
import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-D_XzuGnu.mjs";
|
|
4
|
+
import { t as scanLibrary } from "./library-scanner-V9sTOhrb.mjs";
|
|
4
5
|
|
|
5
6
|
//#region src/intent-library.ts
|
|
6
|
-
function padColumn(text, width) {
|
|
7
|
-
return text.length >= width ? text + " " : text.padEnd(width);
|
|
8
|
-
}
|
|
9
|
-
function printTable(headers, rows) {
|
|
10
|
-
const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)) + 2);
|
|
11
|
-
const headerLine = headers.map((h, i) => padColumn(h, widths[i])).join("");
|
|
12
|
-
const separator = widths.map((w) => "─".repeat(w)).join("");
|
|
13
|
-
console.log(headerLine);
|
|
14
|
-
console.log(separator);
|
|
15
|
-
for (const row of rows) console.log(row.map((cell, i) => padColumn(cell, widths[i])).join(""));
|
|
16
|
-
}
|
|
17
|
-
function printSkillTree(skills, opts) {
|
|
18
|
-
const roots = [];
|
|
19
|
-
const children = /* @__PURE__ */ new Map();
|
|
20
|
-
for (const skill of skills) {
|
|
21
|
-
const slashIdx = skill.name.indexOf("/");
|
|
22
|
-
if (slashIdx === -1) roots.push(skill.name);
|
|
23
|
-
else {
|
|
24
|
-
const parent = skill.name.slice(0, slashIdx);
|
|
25
|
-
if (!children.has(parent)) children.set(parent, []);
|
|
26
|
-
children.get(parent).push(skill);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (roots.length === 0) {
|
|
30
|
-
for (const skill of skills) if (!roots.includes(skill.name)) roots.push(skill.name);
|
|
31
|
-
}
|
|
32
|
-
for (const rootName of roots) {
|
|
33
|
-
const rootSkill = skills.find((s) => s.name === rootName);
|
|
34
|
-
if (!rootSkill) continue;
|
|
35
|
-
printSkillLine(rootName, rootSkill, 4, opts);
|
|
36
|
-
for (const sub of children.get(rootName) ?? []) printSkillLine(sub.name.slice(sub.name.indexOf("/") + 1), sub, 6, opts);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function printSkillLine(displayName, skill, indent, opts) {
|
|
40
|
-
const nameStr = " ".repeat(indent) + displayName;
|
|
41
|
-
const padding = " ".repeat(Math.max(2, opts.nameWidth - nameStr.length));
|
|
42
|
-
const typeCol = opts.showTypes ? (skill.type ? `[${skill.type}]` : "").padEnd(14) : "";
|
|
43
|
-
console.log(`${nameStr}${padding}${typeCol}${skill.description}`);
|
|
44
|
-
}
|
|
45
|
-
function computeSkillNameWidth(allPackageSkills) {
|
|
46
|
-
let max = 0;
|
|
47
|
-
for (const skills of allPackageSkills) for (const s of skills) {
|
|
48
|
-
const slashIdx = s.name.indexOf("/");
|
|
49
|
-
const displayName = slashIdx === -1 ? s.name : s.name.slice(slashIdx + 1);
|
|
50
|
-
const indent = slashIdx === -1 ? 4 : 6;
|
|
51
|
-
max = Math.max(max, indent + displayName.length);
|
|
52
|
-
}
|
|
53
|
-
return max + 2;
|
|
54
|
-
}
|
|
55
7
|
async function cmdList() {
|
|
56
8
|
let result;
|
|
57
9
|
try {
|
|
@@ -92,8 +44,7 @@ async function cmdList() {
|
|
|
92
44
|
}
|
|
93
45
|
console.log(`Feedback:`);
|
|
94
46
|
console.log(` After completing your task, collect feedback on skill usage.`);
|
|
95
|
-
console.log(`
|
|
96
|
-
console.log(` Submit: npx intent feedback --submit --file intent-feedback.json`);
|
|
47
|
+
console.log(` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`);
|
|
97
48
|
console.log();
|
|
98
49
|
if (result.warnings.length > 0) {
|
|
99
50
|
console.log(`Warnings:`);
|
package/dist/library-scanner.mjs
CHANGED
|
@@ -47,30 +47,47 @@ function copyTemplates(srcDir, destDir, vars) {
|
|
|
47
47
|
skipped
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
function getShimContent(ext) {
|
|
51
|
+
return `#!/usr/bin/env node
|
|
51
52
|
// Auto-generated by @tanstack/intent setup
|
|
52
53
|
// Exposes the intent end-user CLI for consumers of this library.
|
|
53
54
|
// Commit this file, then add to your package.json:
|
|
54
|
-
// "bin": { "intent": "./bin/intent
|
|
55
|
+
// "bin": { "intent": "./bin/intent.${ext}" }
|
|
55
56
|
await import('@tanstack/intent/intent-library')
|
|
56
57
|
`;
|
|
58
|
+
}
|
|
59
|
+
function detectShimExtension(root) {
|
|
60
|
+
try {
|
|
61
|
+
if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
|
|
62
|
+
} catch {}
|
|
63
|
+
return "mjs";
|
|
64
|
+
}
|
|
65
|
+
function findExistingShim(root) {
|
|
66
|
+
const shimJs = join(root, "bin", "intent.js");
|
|
67
|
+
if (existsSync(shimJs)) return shimJs;
|
|
68
|
+
const shimMjs = join(root, "bin", "intent.mjs");
|
|
69
|
+
if (existsSync(shimMjs)) return shimMjs;
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
57
72
|
function generateShim(root, result) {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
result.skipped.push(
|
|
73
|
+
const existingShim = findExistingShim(root);
|
|
74
|
+
if (existingShim) {
|
|
75
|
+
result.skipped.push(existingShim);
|
|
61
76
|
return;
|
|
62
77
|
}
|
|
78
|
+
const ext = detectShimExtension(root);
|
|
79
|
+
const shimPath = join(root, "bin", `intent.${ext}`);
|
|
63
80
|
mkdirSync(join(root, "bin"), { recursive: true });
|
|
64
|
-
writeFileSync(shimPath,
|
|
81
|
+
writeFileSync(shimPath, getShimContent(ext));
|
|
65
82
|
result.shim = shimPath;
|
|
66
83
|
}
|
|
67
84
|
function runSetup(root, metaDir, args) {
|
|
68
85
|
const doAll = args.includes("--all");
|
|
69
86
|
const doWorkflows = doAll || args.includes("--workflows");
|
|
70
87
|
const doShim = doAll || args.includes("--shim");
|
|
71
|
-
const
|
|
72
|
-
const installWorkflows = doWorkflows ||
|
|
73
|
-
const installShim = doShim ||
|
|
88
|
+
const noFlagsGiven = !doWorkflows && !doShim;
|
|
89
|
+
const installWorkflows = doWorkflows || noFlagsGiven;
|
|
90
|
+
const installShim = doShim || noFlagsGiven;
|
|
74
91
|
const vars = detectVars(root);
|
|
75
92
|
const result = {
|
|
76
93
|
workflows: [],
|
|
@@ -87,10 +104,11 @@ function runSetup(root, metaDir, args) {
|
|
|
87
104
|
for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
|
|
88
105
|
for (const f of result.skipped) console.log(` Already exists: ${f}`);
|
|
89
106
|
if (result.shim) {
|
|
107
|
+
const shimRelative = result.shim.replace(root + "/", "./");
|
|
90
108
|
console.log(`✓ Generated intent shim: ${result.shim}`);
|
|
91
109
|
console.log(`\n Add to your package.json:`);
|
|
92
|
-
console.log(` "bin": { "intent": "
|
|
93
|
-
console.log(`\n Add bin
|
|
110
|
+
console.log(` "bin": { "intent": "${shimRelative}" }`);
|
|
111
|
+
console.log(`\n Add "bin" to your package.json "files" array.`);
|
|
94
112
|
}
|
|
95
113
|
if (result.workflows.length === 0 && result.shim === null && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
|
|
96
114
|
else if (result.workflows.length > 0) {
|
package/dist/setup.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as runSetup, t as SetupResult } from "./setup-
|
|
1
|
+
import { n as runSetup, t as SetupResult } from "./setup-BJ4giTKA.mjs";
|
|
2
2
|
export { SetupResult, runSetup };
|
package/dist/setup.mjs
CHANGED
|
@@ -337,7 +337,30 @@ only considers one side.
|
|
|
337
337
|
Target 2–4 tensions. If you find none, the skills may be too isolated —
|
|
338
338
|
revisit whether you're missing cross-connections.
|
|
339
339
|
|
|
340
|
-
### 3f —
|
|
340
|
+
### 3f — Map cross-references
|
|
341
|
+
|
|
342
|
+
Beyond tensions (conflicts) and shared failure modes, identify skills
|
|
343
|
+
that illuminate each other without conflicting. A cross-reference means:
|
|
344
|
+
"an agent loading skill A would produce better code if it knew about
|
|
345
|
+
skill B." These become "See also" pointers in the generated SKILL.md
|
|
346
|
+
files.
|
|
347
|
+
|
|
348
|
+
For each pair, note:
|
|
349
|
+
|
|
350
|
+
- Which skill references which (can be bidirectional)
|
|
351
|
+
- Why awareness of the other skill improves output
|
|
352
|
+
|
|
353
|
+
Examples:
|
|
354
|
+
|
|
355
|
+
- A quickstart skill references the security checklist ("after setup, audit")
|
|
356
|
+
- A state management skill references an SSR skill ("state hydration
|
|
357
|
+
requires understanding SSR lifecycle")
|
|
358
|
+
- A data writing skill references a data reading skill ("writes affect
|
|
359
|
+
how queries invalidate")
|
|
360
|
+
|
|
361
|
+
Output these in the `cross_references` section of domain_map.yaml.
|
|
362
|
+
|
|
363
|
+
### 3g — Identify gaps
|
|
341
364
|
|
|
342
365
|
For each skill, explicitly list what you could NOT determine from docs
|
|
343
366
|
and source alone. These become interview questions in Phase 4.
|
|
@@ -351,7 +374,7 @@ Common gaps:
|
|
|
351
374
|
- "GitHub issues show confusion about X but docs don't address it"
|
|
352
375
|
- "I found two patterns for doing X — unclear which is current/preferred"
|
|
353
376
|
|
|
354
|
-
###
|
|
377
|
+
### 3h — Discover composition targets
|
|
355
378
|
|
|
356
379
|
Scan `package.json` for peer dependencies, optional dependencies, and
|
|
357
380
|
`peerDependenciesMeta`. Scan example directories and integration tests
|
|
@@ -363,7 +386,7 @@ for import patterns. For each frequently co-used library, log:
|
|
|
363
386
|
|
|
364
387
|
These become targeted composition questions in Phase 4e.
|
|
365
388
|
|
|
366
|
-
###
|
|
389
|
+
### 3i — Produce the draft
|
|
367
390
|
|
|
368
391
|
Write the full `domain_map.yaml` (format in Output Artifacts below) with
|
|
369
392
|
a `status: draft` field. Flag every gap in the `gaps` section.
|
|
@@ -405,7 +428,7 @@ Follow up on any corrections. Then:
|
|
|
405
428
|
|
|
406
429
|
### 4b — Gap-targeted questions (3–8 questions)
|
|
407
430
|
|
|
408
|
-
For each gap flagged in Phase
|
|
431
|
+
For each gap flagged in Phase 3g, ask a specific question. These are not
|
|
409
432
|
generic — they reference what you found:
|
|
410
433
|
|
|
411
434
|
**Instead of:** "What do developers get wrong?"
|
|
@@ -472,7 +495,7 @@ These surface knowledge that doesn't appear in any docs:
|
|
|
472
495
|
|
|
473
496
|
### 4e — Composition questions (if library interacts with others)
|
|
474
497
|
|
|
475
|
-
Use what you discovered in Phase
|
|
498
|
+
Use what you discovered in Phase 3h. For each integration target
|
|
476
499
|
identified from peer dependencies and example code, ask targeted
|
|
477
500
|
questions:
|
|
478
501
|
|
|
@@ -573,6 +596,11 @@ tensions:
|
|
|
573
596
|
description: '[what conflicts — one sentence]'
|
|
574
597
|
implication: '[what an agent gets wrong when it only considers one side]'
|
|
575
598
|
|
|
599
|
+
cross_references:
|
|
600
|
+
- from: '[skill-slug]'
|
|
601
|
+
to: '[skill-slug]'
|
|
602
|
+
reason: '[why loading one skill benefits from awareness of the other]'
|
|
603
|
+
|
|
576
604
|
gaps:
|
|
577
605
|
- skill: '[skill slug]'
|
|
578
606
|
question: '[what still needs input]'
|
|
@@ -618,6 +646,12 @@ not promotional.]
|
|
|
618
646
|
| -------------- | ------------------- | ----------------------- |
|
|
619
647
|
| [short phrase] | [slug-a] ↔ [slug-b] | [what agents get wrong] |
|
|
620
648
|
|
|
649
|
+
## Cross-References
|
|
650
|
+
|
|
651
|
+
| From | To | Reason |
|
|
652
|
+
| ------ | ------ | ----------------------------------------- |
|
|
653
|
+
| [slug] | [slug] | [why awareness of one improves the other] |
|
|
654
|
+
|
|
621
655
|
## Subsystems & Reference Candidates
|
|
622
656
|
|
|
623
657
|
| Skill | Subsystems | Reference candidates |
|
|
@@ -672,6 +706,7 @@ not promotional.]
|
|
|
672
706
|
| Subsystems flagged | Skills with 3+ adapters/backends list them as subsystems |
|
|
673
707
|
| Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates |
|
|
674
708
|
| Lifecycle skills considered | Suggest journey skills when docs have the material |
|
|
709
|
+
| Cross-references mapped | Skills that illuminate each other get "See also" pointers |
|
|
675
710
|
|
|
676
711
|
---
|
|
677
712
|
|
|
@@ -4,12 +4,11 @@ description: >
|
|
|
4
4
|
Collect structured feedback about skill usage after completing a coding task.
|
|
5
5
|
Activate at the end of any session where one or more SKILL.md files were
|
|
6
6
|
loaded. Captures agent signals (gaps, errors, corrections, human interventions)
|
|
7
|
-
and brief human input, then submits via
|
|
7
|
+
and brief human input, then submits directly via gh CLI or provides manual
|
|
8
|
+
submission instructions.
|
|
8
9
|
metadata:
|
|
9
|
-
version: '
|
|
10
|
+
version: '2.0'
|
|
10
11
|
category: meta-tooling
|
|
11
|
-
output_artifacts:
|
|
12
|
-
- intent-feedback.json
|
|
13
12
|
---
|
|
14
13
|
|
|
15
14
|
# Skill Feedback Collection
|
|
@@ -83,74 +82,86 @@ If the human gives an explicit rating, use that instead.
|
|
|
83
82
|
|
|
84
83
|
---
|
|
85
84
|
|
|
86
|
-
## Phase 3 — Build the
|
|
87
|
-
|
|
88
|
-
Construct one JSON payload per skill used. The schema must match exactly:
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"skill": "<skill name from SKILL.md frontmatter>",
|
|
93
|
-
"package": "<npm package name that contains the skill>",
|
|
94
|
-
"skillVersion": "<metadata.version from SKILL.md frontmatter, or library_version>",
|
|
95
|
-
"task": "<one-sentence summary of what the human asked you to do>",
|
|
96
|
-
"whatWorked": "<patterns/instructions from the skill that were accurate and helpful>",
|
|
97
|
-
"whatFailed": "<errors from 1b — what the skill got wrong>",
|
|
98
|
-
"missing": "<gaps from 1a — what the skill should have covered>",
|
|
99
|
-
"selfCorrections": "<fixes you applied from 1b + interventions from 1c>",
|
|
100
|
-
"userRating": "good | mixed | bad",
|
|
101
|
-
"userComments": "<optional — direct quotes or paraphrased human input from Phase 2>"
|
|
102
|
-
}
|
|
103
|
-
```
|
|
85
|
+
## Phase 3 — Build the Feedback
|
|
104
86
|
|
|
105
|
-
|
|
87
|
+
Write one Markdown feedback file per skill used. Only include skills that were
|
|
88
|
+
actually used during the session — skip any that were loaded but never
|
|
89
|
+
referenced.
|
|
90
|
+
|
|
91
|
+
### Template
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
# Skill Feedback: [skill name from SKILL.md frontmatter]
|
|
95
|
+
|
|
96
|
+
**Package:** [npm package name that contains the skill]
|
|
97
|
+
**Skill version:** [metadata.version or library_version from frontmatter]
|
|
98
|
+
**Rating:** [good | mixed | bad]
|
|
99
|
+
|
|
100
|
+
## Task
|
|
101
|
+
|
|
102
|
+
[one-sentence summary of what the human asked you to do]
|
|
103
|
+
|
|
104
|
+
## What Worked
|
|
105
|
+
|
|
106
|
+
[patterns/instructions from the skill that were accurate and helpful]
|
|
107
|
+
|
|
108
|
+
## What Failed
|
|
109
|
+
|
|
110
|
+
[from 1b — skill instructions that produced errors]
|
|
111
|
+
|
|
112
|
+
## Missing
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
| `selfCorrections` | From 1b fixes + 1c human interventions, combined |
|
|
117
|
-
| `userRating` | From Phase 2 sentiment analysis or explicit rating |
|
|
118
|
-
| `userComments` | From Phase 2 answers, keep brief |
|
|
119
|
-
|
|
120
|
-
### Example
|
|
121
|
-
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"skill": "tanstack-query/core",
|
|
125
|
-
"package": "@anthropic/tanstack-query-intent",
|
|
126
|
-
"skillVersion": "1.0",
|
|
127
|
-
"task": "Add optimistic updates to a mutation with rollback on error",
|
|
128
|
-
"whatWorked": "Setup pattern was correct. onMutate/onError/onSettled lifecycle was accurate.",
|
|
129
|
-
"whatFailed": "Cache key format used array syntax that doesn't match v5 — had to switch to queryOptions pattern.",
|
|
130
|
-
"missing": "No guidance on TypeScript generics for mutation variables. Had to read source.",
|
|
131
|
-
"selfCorrections": "Fixed cache key format. Human corrected the rollback type to include undefined.",
|
|
132
|
-
"userRating": "mixed",
|
|
133
|
-
"userComments": "The optimistic update pattern was helpful but the cache key thing wasted 10 minutes."
|
|
134
|
-
}
|
|
114
|
+
[from 1a — gaps where the skill should have covered]
|
|
115
|
+
|
|
116
|
+
## Self-Corrections
|
|
117
|
+
|
|
118
|
+
[from 1b fixes + 1c human interventions, combined]
|
|
119
|
+
|
|
120
|
+
## User Comments
|
|
121
|
+
|
|
122
|
+
[optional — direct quotes or paraphrased human input from Phase 2]
|
|
135
123
|
```
|
|
136
124
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
### Field derivation guide
|
|
126
|
+
|
|
127
|
+
| Field | Source |
|
|
128
|
+
| ---------------- | ------------------------------------------------------------------ |
|
|
129
|
+
| Skill name | Frontmatter `name` field of the SKILL.md you loaded |
|
|
130
|
+
| Package | The npm package the skill lives in (e.g. `@tanstack/query-intent`) |
|
|
131
|
+
| Skill version | Frontmatter `metadata.version` or `library_version` |
|
|
132
|
+
| Task | Summarize the human's original request in one sentence |
|
|
133
|
+
| What Worked | List skill sections/patterns that were correct and useful |
|
|
134
|
+
| What Failed | From 1b — skill instructions that produced errors |
|
|
135
|
+
| Missing | From 1a — gaps where the skill was silent |
|
|
136
|
+
| Self-Corrections | From 1b fixes + 1c human interventions, combined |
|
|
137
|
+
| Rating | From Phase 2 sentiment analysis or explicit rating |
|
|
138
|
+
| User Comments | From Phase 2 answers, keep brief |
|
|
140
139
|
|
|
141
140
|
---
|
|
142
141
|
|
|
143
142
|
## Phase 4 — Submit
|
|
144
143
|
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
Determine the target repo from the skill's package. The repo is typically
|
|
145
|
+
derivable from the `repository` field in the package's `package.json`, or
|
|
146
|
+
from the `sources` field in the SKILL.md frontmatter.
|
|
147
|
+
|
|
148
|
+
### If `gh` CLI is available
|
|
149
|
+
|
|
150
|
+
Submit directly as a GitHub issue:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
gh issue create --repo [owner/repo] --title "Skill Feedback: [skill-name] ([rating])" --label "feedback:[skill-name]" --body-file intent-feedback.md
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If the label doesn't exist, omit the `--label` flag — don't let a missing
|
|
157
|
+
label block submission.
|
|
147
158
|
|
|
148
|
-
|
|
159
|
+
If submission succeeds, delete the feedback file.
|
|
149
160
|
|
|
150
|
-
|
|
151
|
-
npx intent feedback --submit --file intent-feedback.json
|
|
152
|
-
```
|
|
161
|
+
### If `gh` CLI is not available
|
|
153
162
|
|
|
154
|
-
|
|
163
|
+
Tell the human:
|
|
155
164
|
|
|
156
|
-
|
|
165
|
+
> "I've written skill feedback to `intent-feedback.md`. To submit it,
|
|
166
|
+
> open an issue at https://github.com/[owner/repo]/issues and paste the
|
|
167
|
+
> contents."
|