@tanstack/intent 0.0.9 → 0.0.12
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 +37 -16
- package/dist/cli.mjs +24 -13
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/scanner-DQeiZRzp.mjs +4 -0
- package/dist/{scanner-OmHt14bs.mjs → scanner-dIYdkHQ1.mjs} +2 -2
- package/dist/setup-BYOg-Ii-.mjs +197 -0
- package/dist/setup-CANkTz55.d.mts +18 -0
- package/dist/setup.d.mts +2 -2
- package/dist/setup.mjs +2 -2
- package/meta/domain-discovery/SKILL.md +131 -53
- package/meta/feedback-collection/SKILL.md +27 -0
- package/meta/generate-skill/SKILL.md +17 -43
- package/meta/tree-generator/SKILL.md +3 -46
- package/package.json +1 -1
- package/dist/scanner-DkShtCWX.mjs +0 -4
- package/dist/setup-BJ4giTKA.d.mts +0 -9
- package/dist/setup-DGvdyKEq.mjs +0 -125
package/README.md
CHANGED
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Ship compositional knowledge for AI coding agents alongside your npm packages.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## The problem
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Your docs are good. Your types are solid. Your agent still gets it wrong.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal.
|
|
12
|
+
|
|
13
|
+
## Skills: the fourth artifact
|
|
14
|
+
|
|
15
|
+
You ship code, docs, and types. Skills are the fourth artifact — knowledge encoded for the thing writing most of your code.
|
|
16
|
+
|
|
17
|
+
Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates.
|
|
18
|
+
|
|
19
|
+
Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync.
|
|
14
20
|
|
|
15
21
|
## Quick Start
|
|
16
22
|
|
|
@@ -22,6 +28,8 @@ Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .
|
|
|
22
28
|
npx @tanstack/intent install
|
|
23
29
|
```
|
|
24
30
|
|
|
31
|
+
No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too.
|
|
32
|
+
|
|
25
33
|
List available skills from installed packages:
|
|
26
34
|
|
|
27
35
|
```bash
|
|
@@ -44,23 +52,36 @@ Validate your skill files:
|
|
|
44
52
|
npx @tanstack/intent validate
|
|
45
53
|
```
|
|
46
54
|
|
|
47
|
-
|
|
55
|
+
Check for skills that have fallen behind their sources:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx @tanstack/intent stale
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Copy CI workflow templates into your repo so validation and staleness checks run on every push:
|
|
48
62
|
|
|
49
63
|
```bash
|
|
50
64
|
npx @tanstack/intent setup
|
|
51
65
|
```
|
|
52
66
|
|
|
67
|
+
## Keeping skills current
|
|
68
|
+
|
|
69
|
+
The real risk with any derived artifact is staleness. `npx @tanstack/intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships.
|
|
70
|
+
|
|
71
|
+
The feedback loop runs both directions. `npx @tanstack/intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`.
|
|
72
|
+
|
|
53
73
|
## CLI Commands
|
|
54
74
|
|
|
55
|
-
| Command
|
|
56
|
-
|
|
|
57
|
-
| `intent install` | Set up skill-to-task mappings in agent config files |
|
|
58
|
-
| `intent list [--json]` | Discover intent-enabled packages |
|
|
59
|
-
| `intent meta` | List meta-skills for library maintainers |
|
|
60
|
-
| `intent scaffold` | Print the guided skill generation prompt |
|
|
61
|
-
| `intent validate [dir]` | Validate SKILL.md files |
|
|
62
|
-
| `intent setup` | Copy CI templates, generate shim, create labels |
|
|
63
|
-
| `intent stale [--json]` | Check skills for version drift |
|
|
75
|
+
| Command | Description |
|
|
76
|
+
| ------------------------------------- | --------------------------------------------------- |
|
|
77
|
+
| `npx @tanstack/intent install` | Set up skill-to-task mappings in agent config files |
|
|
78
|
+
| `npx @tanstack/intent list [--json]` | Discover intent-enabled packages |
|
|
79
|
+
| `npx @tanstack/intent meta` | List meta-skills for library maintainers |
|
|
80
|
+
| `npx @tanstack/intent scaffold` | Print the guided skill generation prompt |
|
|
81
|
+
| `npx @tanstack/intent validate [dir]` | Validate SKILL.md files |
|
|
82
|
+
| `npx @tanstack/intent setup` | Copy CI templates, generate shim, create labels |
|
|
83
|
+
| `npx @tanstack/intent stale [--json]` | Check skills for version drift |
|
|
84
|
+
| `npx @tanstack/intent feedback` | Submit skill feedback |
|
|
64
85
|
|
|
65
86
|
## License
|
|
66
87
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
|
|
3
|
-
import { t as scanForIntents } from "./scanner-
|
|
3
|
+
import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
|
|
4
4
|
import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-D_XzuGnu.mjs";
|
|
5
5
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
6
6
|
import { dirname, join, relative, sep } from "node:path";
|
|
@@ -101,7 +101,7 @@ function collectPackagingWarnings(root) {
|
|
|
101
101
|
if (!pkgJson.bin?.intent) warnings.push("Missing \"bin\": { \"intent\": ... } entry in package.json");
|
|
102
102
|
const shimJs = join(root, "bin", "intent.js");
|
|
103
103
|
const shimMjs = join(root, "bin", "intent.mjs");
|
|
104
|
-
if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent
|
|
104
|
+
if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent add-library-bin)");
|
|
105
105
|
const files = pkgJson.files;
|
|
106
106
|
if (Array.isArray(files)) {
|
|
107
107
|
if (!files.includes("skills")) warnings.push("\"skills\" is not in the \"files\" array — skills won't be published");
|
|
@@ -287,12 +287,11 @@ This produces: individual SKILL.md files.
|
|
|
287
287
|
|
|
288
288
|
1. Run \`npx @tanstack/intent validate\` in each package directory
|
|
289
289
|
2. Commit skills/ and artifacts
|
|
290
|
-
3. For each publishable package, run: \`npx @tanstack/intent
|
|
291
|
-
4.
|
|
292
|
-
5.
|
|
293
|
-
6.
|
|
294
|
-
7.
|
|
295
|
-
8. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`"
|
|
290
|
+
3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
|
|
291
|
+
4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
|
|
292
|
+
5. Ensure each package has \`@tanstack/intent\` as a devDependency
|
|
293
|
+
6. Create a \`feedback:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
|
|
294
|
+
7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`"
|
|
296
295
|
`;
|
|
297
296
|
console.log(prompt);
|
|
298
297
|
}
|
|
@@ -304,7 +303,9 @@ Usage:
|
|
|
304
303
|
intent validate [<dir>] Validate skill files (default: skills/)
|
|
305
304
|
intent install Print a skill that guides your coding agent to set up skill-to-task mappings
|
|
306
305
|
intent scaffold Print maintainer scaffold prompt
|
|
307
|
-
intent
|
|
306
|
+
intent add-library-bin Generate bin/intent.{js,mjs} bridge file
|
|
307
|
+
intent edit-package-json Wire package.json (files, bin) for skill publishing
|
|
308
|
+
intent setup-github-actions Copy CI workflow templates to .github/workflows/
|
|
308
309
|
intent stale Check skills for staleness`;
|
|
309
310
|
const command = process.argv[2];
|
|
310
311
|
const commandArgs = process.argv.slice(3);
|
|
@@ -371,7 +372,7 @@ skills:
|
|
|
371
372
|
break;
|
|
372
373
|
case "stale": {
|
|
373
374
|
const { checkStaleness } = await import("./staleness-B5gUj7FR.mjs");
|
|
374
|
-
const { scanForIntents: scanStale } = await import("./scanner-
|
|
375
|
+
const { scanForIntents: scanStale } = await import("./scanner-DQeiZRzp.mjs");
|
|
375
376
|
let staleResult;
|
|
376
377
|
try {
|
|
377
378
|
staleResult = await scanStale();
|
|
@@ -402,9 +403,19 @@ skills:
|
|
|
402
403
|
}
|
|
403
404
|
break;
|
|
404
405
|
}
|
|
405
|
-
case "
|
|
406
|
-
const {
|
|
407
|
-
|
|
406
|
+
case "add-library-bin": {
|
|
407
|
+
const { runAddLibraryBin } = await import("./setup.mjs");
|
|
408
|
+
runAddLibraryBin(process.cwd());
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
case "edit-package-json": {
|
|
412
|
+
const { runEditPackageJson } = await import("./setup.mjs");
|
|
413
|
+
runEditPackageJson(process.cwd());
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
case "setup-github-actions": {
|
|
417
|
+
const { runSetupGithubActions } = await import("./setup.mjs");
|
|
418
|
+
runSetupGithubActions(process.cwd(), getMetaDir());
|
|
408
419
|
break;
|
|
409
420
|
}
|
|
410
421
|
default:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as IntentProjectConfig, c as ScanResult, d as StalenessReport, i as IntentPackage, l as SkillEntry, n as FeedbackPayload, o as MetaFeedbackPayload, r as IntentConfig, s as MetaSkillName, t as AgentName, u as SkillStaleness } from "./types-BmnI8kFB.mjs";
|
|
2
|
-
import { n as
|
|
2
|
+
import { a as runEditPackageJson, i as runAddLibraryBin, n as EditPackageJsonResult, o as runSetupGithubActions, r as SetupGithubActionsResult, t as AddLibraryBinResult } from "./setup-CANkTz55.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/scanner.d.ts
|
|
5
5
|
declare function scanForIntents(root?: string): Promise<ScanResult>;
|
|
@@ -44,4 +44,4 @@ declare function findSkillFiles(dir: string): string[];
|
|
|
44
44
|
*/
|
|
45
45
|
declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
|
|
46
46
|
//#endregion
|
|
47
|
-
export { type AgentName, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency,
|
|
47
|
+
export { type AddLibraryBinResult, type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
|
|
2
|
-
import { t as scanForIntents } from "./scanner-
|
|
2
|
+
import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
|
|
3
3
|
import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
|
|
4
|
-
import { t as
|
|
4
|
+
import { n as runEditPackageJson, r as runSetupGithubActions, t as runAddLibraryBin } from "./setup-BYOg-Ii-.mjs";
|
|
5
5
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { execFileSync, execSync } from "node:child_process";
|
|
@@ -246,4 +246,4 @@ function submitMetaFeedback(payload, opts) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
//#endregion
|
|
249
|
-
export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency,
|
|
249
|
+
export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|
|
@@ -125,7 +125,7 @@ async function scanForIntents(root) {
|
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
for (const entry of topEntries) {
|
|
128
|
-
if (!entry.isDirectory()) continue;
|
|
128
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
129
129
|
const dirPath = join(nodeModulesDir, entry.name);
|
|
130
130
|
if (entry.name.startsWith("@")) {
|
|
131
131
|
let scopedEntries;
|
|
@@ -138,7 +138,7 @@ async function scanForIntents(root) {
|
|
|
138
138
|
continue;
|
|
139
139
|
}
|
|
140
140
|
for (const scoped of scopedEntries) {
|
|
141
|
-
if (!scoped.isDirectory()) continue;
|
|
141
|
+
if (!scoped.isDirectory() && !scoped.isSymbolicLink()) continue;
|
|
142
142
|
packageDirs.push({ dirPath: join(dirPath, scoped.name) });
|
|
143
143
|
}
|
|
144
144
|
} else if (!entry.name.startsWith(".")) packageDirs.push({ dirPath });
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
//#region src/setup.ts
|
|
5
|
+
function detectVars(root) {
|
|
6
|
+
const pkgPath = join(root, "package.json");
|
|
7
|
+
let pkgJson = {};
|
|
8
|
+
try {
|
|
9
|
+
pkgJson = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
10
|
+
} catch (err) {
|
|
11
|
+
if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) console.error(`Warning: could not read ${pkgPath}: ${err instanceof Error ? err.message : err}`);
|
|
12
|
+
}
|
|
13
|
+
const name = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
|
|
14
|
+
const intent = pkgJson.intent;
|
|
15
|
+
const repo = typeof intent?.repo === "string" ? intent.repo : name.replace(/^@/, "").replace(/\//, "/");
|
|
16
|
+
const docs = typeof intent?.docs === "string" ? intent.docs : "docs/";
|
|
17
|
+
let srcPath = `packages/${name.replace(/^@[^/]+\//, "")}/src/**`;
|
|
18
|
+
if (existsSync(join(root, "src"))) srcPath = "src/**";
|
|
19
|
+
return {
|
|
20
|
+
PACKAGE_NAME: name,
|
|
21
|
+
REPO: repo,
|
|
22
|
+
DOCS_PATH: docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**",
|
|
23
|
+
SRC_PATH: srcPath
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function applyVars(content, vars) {
|
|
27
|
+
return content.replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME).replace(/\{\{REPO\}\}/g, vars.REPO).replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH).replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH);
|
|
28
|
+
}
|
|
29
|
+
function copyTemplates(srcDir, destDir, vars) {
|
|
30
|
+
const copied = [];
|
|
31
|
+
const skipped = [];
|
|
32
|
+
if (!existsSync(srcDir)) return {
|
|
33
|
+
copied,
|
|
34
|
+
skipped
|
|
35
|
+
};
|
|
36
|
+
mkdirSync(destDir, { recursive: true });
|
|
37
|
+
for (const entry of readdirSync(srcDir)) {
|
|
38
|
+
const srcPath = join(srcDir, entry);
|
|
39
|
+
const destPath = join(destDir, entry);
|
|
40
|
+
if (existsSync(destPath)) {
|
|
41
|
+
skipped.push(destPath);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
writeFileSync(destPath, applyVars(readFileSync(srcPath, "utf8"), vars));
|
|
45
|
+
copied.push(destPath);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
copied,
|
|
49
|
+
skipped
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function getShimContent(ext) {
|
|
53
|
+
return `#!/usr/bin/env node
|
|
54
|
+
// Auto-generated by @tanstack/intent setup
|
|
55
|
+
// Exposes the intent end-user CLI for consumers of this library.
|
|
56
|
+
// Commit this file, then add to your package.json:
|
|
57
|
+
// "bin": { "intent": "./bin/intent.${ext}" }
|
|
58
|
+
await import('@tanstack/intent/intent-library')
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
function detectShimExtension(root) {
|
|
62
|
+
try {
|
|
63
|
+
if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) console.error(`Warning: could not read package.json: ${err instanceof Error ? err.message : err}`);
|
|
66
|
+
}
|
|
67
|
+
return "mjs";
|
|
68
|
+
}
|
|
69
|
+
function findExistingShim(root) {
|
|
70
|
+
const shimJs = join(root, "bin", "intent.js");
|
|
71
|
+
if (existsSync(shimJs)) return shimJs;
|
|
72
|
+
const shimMjs = join(root, "bin", "intent.mjs");
|
|
73
|
+
if (existsSync(shimMjs)) return shimMjs;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function runAddLibraryBin(root) {
|
|
77
|
+
const result = {
|
|
78
|
+
shim: null,
|
|
79
|
+
skipped: null
|
|
80
|
+
};
|
|
81
|
+
const existingShim = findExistingShim(root);
|
|
82
|
+
if (existingShim) {
|
|
83
|
+
result.skipped = existingShim;
|
|
84
|
+
console.log(` Already exists: ${existingShim}`);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
const ext = detectShimExtension(root);
|
|
88
|
+
const shimPath = join(root, "bin", `intent.${ext}`);
|
|
89
|
+
mkdirSync(join(root, "bin"), { recursive: true });
|
|
90
|
+
writeFileSync(shimPath, getShimContent(ext));
|
|
91
|
+
result.shim = shimPath;
|
|
92
|
+
console.log(`✓ Generated intent shim: ${shimPath}`);
|
|
93
|
+
console.log(`\n Run \`npx @tanstack/intent edit-package-json\` to wire package.json.`);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
function runEditPackageJson(root) {
|
|
97
|
+
const result = {
|
|
98
|
+
added: [],
|
|
99
|
+
alreadyPresent: []
|
|
100
|
+
};
|
|
101
|
+
const pkgPath = join(root, "package.json");
|
|
102
|
+
if (!existsSync(pkgPath)) {
|
|
103
|
+
console.error("No package.json found in " + root);
|
|
104
|
+
process.exitCode = 1;
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
const raw = readFileSync(pkgPath, "utf8");
|
|
108
|
+
let pkg;
|
|
109
|
+
try {
|
|
110
|
+
pkg = JSON.parse(raw);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
const detail = err instanceof SyntaxError ? err.message : String(err);
|
|
113
|
+
console.error(`Failed to parse ${pkgPath}: ${detail}`);
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
const indentMatch = raw.match(/^(\s+)"/m);
|
|
117
|
+
const indentSize = indentMatch?.[1] ? indentMatch[1].length : 2;
|
|
118
|
+
if (!Array.isArray(pkg.files)) pkg.files = [];
|
|
119
|
+
const files = pkg.files;
|
|
120
|
+
const requiredFiles = (() => {
|
|
121
|
+
let dir = join(root, "..");
|
|
122
|
+
for (let i = 0; i < 5; i++) {
|
|
123
|
+
const parentPkg = join(dir, "package.json");
|
|
124
|
+
if (existsSync(parentPkg)) {
|
|
125
|
+
try {
|
|
126
|
+
const parent = JSON.parse(readFileSync(parentPkg, "utf8"));
|
|
127
|
+
if (Array.isArray(parent.workspaces) || parent.workspaces?.packages) return true;
|
|
128
|
+
} catch {}
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const next = join(dir, "..");
|
|
132
|
+
if (next === dir) break;
|
|
133
|
+
dir = next;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
})() ? ["skills", "bin"] : [
|
|
137
|
+
"skills",
|
|
138
|
+
"bin",
|
|
139
|
+
"!skills/_artifacts"
|
|
140
|
+
];
|
|
141
|
+
for (const entry of requiredFiles) if (files.includes(entry)) result.alreadyPresent.push(`files: "${entry}"`);
|
|
142
|
+
else {
|
|
143
|
+
files.push(entry);
|
|
144
|
+
result.added.push(`files: "${entry}"`);
|
|
145
|
+
}
|
|
146
|
+
const existingShim = findExistingShim(root);
|
|
147
|
+
let ext;
|
|
148
|
+
if (existingShim) ext = existingShim.endsWith(".mjs") ? "mjs" : "js";
|
|
149
|
+
else ext = pkg.type === "module" ? "js" : "mjs";
|
|
150
|
+
const shimRelative = `./bin/intent.${ext}`;
|
|
151
|
+
if (typeof pkg.bin === "object" && pkg.bin !== null) {
|
|
152
|
+
const binObj = pkg.bin;
|
|
153
|
+
if (binObj.intent) result.alreadyPresent.push(`bin.intent`);
|
|
154
|
+
else {
|
|
155
|
+
binObj.intent = shimRelative;
|
|
156
|
+
result.added.push(`bin.intent: "${shimRelative}"`);
|
|
157
|
+
}
|
|
158
|
+
} else if (!pkg.bin) {
|
|
159
|
+
pkg.bin = { intent: shimRelative };
|
|
160
|
+
result.added.push(`bin.intent: "${shimRelative}"`);
|
|
161
|
+
} else if (typeof pkg.bin === "string") {
|
|
162
|
+
const pkgName = typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : "unknown";
|
|
163
|
+
pkg.bin = {
|
|
164
|
+
[pkgName]: pkg.bin,
|
|
165
|
+
intent: shimRelative
|
|
166
|
+
};
|
|
167
|
+
result.added.push(`bin.intent: "${shimRelative}" (converted bin from string to object)`);
|
|
168
|
+
}
|
|
169
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, indentSize) + "\n");
|
|
170
|
+
for (const a of result.added) console.log(`✓ Added ${a}`);
|
|
171
|
+
for (const a of result.alreadyPresent) console.log(` Already present: ${a}`);
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
function runSetupGithubActions(root, metaDir) {
|
|
175
|
+
const vars = detectVars(root);
|
|
176
|
+
const result = {
|
|
177
|
+
workflows: [],
|
|
178
|
+
skipped: []
|
|
179
|
+
};
|
|
180
|
+
const { copied, skipped } = copyTemplates(join(metaDir, "templates", "workflows"), join(root, ".github", "workflows"), vars);
|
|
181
|
+
result.workflows = copied;
|
|
182
|
+
result.skipped = skipped;
|
|
183
|
+
for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
|
|
184
|
+
for (const f of result.skipped) console.log(` Already exists: ${f}`);
|
|
185
|
+
if (result.workflows.length === 0 && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
|
|
186
|
+
else if (result.workflows.length > 0) {
|
|
187
|
+
console.log(`\nTemplate variables applied:`);
|
|
188
|
+
console.log(` Package: ${vars.PACKAGE_NAME}`);
|
|
189
|
+
console.log(` Repo: ${vars.REPO}`);
|
|
190
|
+
console.log(` Docs: ${vars.DOCS_PATH}`);
|
|
191
|
+
console.log(` Src: ${vars.SRC_PATH}`);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
//#endregion
|
|
197
|
+
export { runEditPackageJson as n, runSetupGithubActions as r, runAddLibraryBin as t };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/setup.d.ts
|
|
2
|
+
interface AddLibraryBinResult {
|
|
3
|
+
shim: string | null;
|
|
4
|
+
skipped: string | null;
|
|
5
|
+
}
|
|
6
|
+
interface EditPackageJsonResult {
|
|
7
|
+
added: string[];
|
|
8
|
+
alreadyPresent: string[];
|
|
9
|
+
}
|
|
10
|
+
interface SetupGithubActionsResult {
|
|
11
|
+
workflows: string[];
|
|
12
|
+
skipped: string[];
|
|
13
|
+
}
|
|
14
|
+
declare function runAddLibraryBin(root: string): AddLibraryBinResult;
|
|
15
|
+
declare function runEditPackageJson(root: string): EditPackageJsonResult;
|
|
16
|
+
declare function runSetupGithubActions(root: string, metaDir: string): SetupGithubActionsResult;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { runEditPackageJson as a, runAddLibraryBin as i, EditPackageJsonResult as n, runSetupGithubActions as o, SetupGithubActionsResult as r, AddLibraryBinResult as t };
|
package/dist/setup.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
export {
|
|
1
|
+
import { a as runEditPackageJson, i as runAddLibraryBin, n as EditPackageJsonResult, o as runSetupGithubActions, r as SetupGithubActionsResult, t as AddLibraryBinResult } from "./setup-CANkTz55.mjs";
|
|
2
|
+
export { AddLibraryBinResult, EditPackageJsonResult, SetupGithubActionsResult, runAddLibraryBin, runEditPackageJson, runSetupGithubActions };
|
package/dist/setup.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { n as runEditPackageJson, r as runSetupGithubActions, t as runAddLibraryBin } from "./setup-BYOg-Ii-.mjs";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { runAddLibraryBin, runEditPackageJson, runSetupGithubActions };
|
|
@@ -42,9 +42,12 @@ path applies (see below).
|
|
|
42
42
|
|
|
43
43
|
### Lightweight path (small libraries)
|
|
44
44
|
|
|
45
|
-
After Phase 1,
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
After Phase 1, decide whether the library warrants the full five-phase
|
|
46
|
+
flow or the compressed flow below. This is a judgment call — lean toward
|
|
47
|
+
full discovery unless the library is obviously small (single-purpose
|
|
48
|
+
utility, 2–3 distinct developer tasks max). Use a compressed flow when
|
|
49
|
+
the skill surface is small enough that two interview rounds would be
|
|
50
|
+
redundant:
|
|
48
51
|
|
|
49
52
|
1. **Phase 1** — Quick scan (same as full flow)
|
|
50
53
|
2. **Phase 2+4 combined** — Single interview round. Combine the
|
|
@@ -59,6 +62,42 @@ The lightweight path produces identical output artifacts (domain_map.yaml
|
|
|
59
62
|
and skill_spec.md). It just avoids two separate interview rounds when the
|
|
60
63
|
library is small enough that one round covers everything.
|
|
61
64
|
|
|
65
|
+
### Hard rules — interview phases are mandatory and interactive
|
|
66
|
+
|
|
67
|
+
These rules override any other reasoning. No exceptions.
|
|
68
|
+
|
|
69
|
+
1. **Phases 2 and 4 are interactive interviews conducted with the
|
|
70
|
+
maintainer.** You must ask the questions specified in each sub-section
|
|
71
|
+
and wait for the maintainer's response before continuing. Documentation,
|
|
72
|
+
source code, and other automated analysis are NOT substitutes for the
|
|
73
|
+
maintainer's answers.
|
|
74
|
+
2. **Every question in Phases 2 and 4 must be asked as an open-ended
|
|
75
|
+
question and sent as a message to the maintainer.** You must then
|
|
76
|
+
STOP and WAIT for their reply. Do not answer your own questions. Do
|
|
77
|
+
not infer answers from documentation. Do not skip questions because
|
|
78
|
+
you believe you already know the answer.
|
|
79
|
+
3. **Do not convert open-ended questions into multiple-choice,
|
|
80
|
+
yes/no, or confirmation prompts.** The question templates in each
|
|
81
|
+
sub-section are open-ended by design. Present them as open-ended
|
|
82
|
+
questions. The maintainer's unprompted answers surface knowledge that
|
|
83
|
+
pre-structured options suppress.
|
|
84
|
+
4. **Minimum question counts are enforced.** Each sub-section specifies
|
|
85
|
+
a question count range (e.g. "2–4 questions"). You must ask at least
|
|
86
|
+
the minimum number. Asking zero questions in any sub-section is a
|
|
87
|
+
protocol violation.
|
|
88
|
+
5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──`
|
|
89
|
+
below, you must halt execution and wait for the maintainer's response
|
|
90
|
+
or acknowledgment before proceeding. Do not continue past a STOP gate
|
|
91
|
+
in the same message.
|
|
92
|
+
6. **If the maintainer asks to skip an interview phase**, explain the
|
|
93
|
+
value of the phase and what will be lost. Proceed with skipping only
|
|
94
|
+
if they confirm a second time.
|
|
95
|
+
7. **Rich documentation makes interviews MORE valuable, not less.**
|
|
96
|
+
When docs are comprehensive, the interview surfaces what docs miss:
|
|
97
|
+
implicit knowledge, AI-specific failure modes, undocumented tradeoffs,
|
|
98
|
+
and the maintainer's prioritization of what matters most. Never
|
|
99
|
+
rationalize skipping interviews because documentation is thorough.
|
|
100
|
+
|
|
62
101
|
---
|
|
63
102
|
|
|
64
103
|
## Phase 1 — Quick scan (autonomous, ~10 minutes)
|
|
@@ -105,20 +144,37 @@ Log (but do not group yet):
|
|
|
105
144
|
- Which frameworks it supports
|
|
106
145
|
- Any existing skill files, agent configs, or intents
|
|
107
146
|
- Whether the library is a monorepo and which packages matter
|
|
147
|
+
- Peer dependency constraints — read `peerDependencies` and
|
|
148
|
+
`peerDependenciesMeta` from each client-facing package.json to
|
|
149
|
+
understand version ranges and optional integrations early
|
|
150
|
+
|
|
151
|
+
Present your initial impressions to the maintainer as a brief summary
|
|
152
|
+
(3–5 bullets). This orients them on what you found and primes them for
|
|
153
|
+
the interview.
|
|
154
|
+
|
|
155
|
+
**── STOP ── Do not proceed to Phase 2 until the maintainer has
|
|
156
|
+
acknowledged your summary or responded.**
|
|
108
157
|
|
|
109
158
|
---
|
|
110
159
|
|
|
111
|
-
## Phase 2 — High-level interview
|
|
160
|
+
## Phase 2 — High-level interview (interactive — requires maintainer)
|
|
112
161
|
|
|
113
162
|
The maintainer's mental model of developer tasks IS the skill map. Your
|
|
114
163
|
job in this phase is to extract it — not to propose your own structure.
|
|
115
164
|
|
|
165
|
+
You must ask the questions below to the maintainer and wait for their
|
|
166
|
+
responses. Do not infer answers from documentation or source code.
|
|
167
|
+
|
|
116
168
|
### Rules for Phase 2
|
|
117
169
|
|
|
118
170
|
1. One topic per message for open-ended questions. You may batch 2–3
|
|
119
171
|
yes/no or short-confirmation questions together.
|
|
120
|
-
2.
|
|
121
|
-
|
|
172
|
+
2. Ask each question as written (you may adapt phrasing to context, but
|
|
173
|
+
keep questions open-ended — never convert to multiple-choice).
|
|
174
|
+
3. Wait for the maintainer's response after each question before asking
|
|
175
|
+
the next.
|
|
176
|
+
4. Take notes silently. Do not summarize back unless asked.
|
|
177
|
+
5. If the maintainer gives a short answer, probe deeper before moving on.
|
|
122
178
|
|
|
123
179
|
### 2a — Developer tasks (2–4 questions)
|
|
124
180
|
|
|
@@ -135,6 +191,13 @@ Follow up to enumerate distinct tasks:
|
|
|
135
191
|
> things like 'set up the client', 'implement auth', 'debug sync issues'
|
|
136
192
|
> — each one a separate moment where they'd want focused guidance."
|
|
137
193
|
|
|
194
|
+
For monorepo libraries, also ask about cross-package tasks:
|
|
195
|
+
|
|
196
|
+
> "Are there tasks that touch multiple packages in your monorepo? For
|
|
197
|
+
> example, a getting-started flow that requires imports from both the
|
|
198
|
+
> client and server packages? I want to make sure skills that span
|
|
199
|
+
> package boundaries are captured correctly."
|
|
200
|
+
|
|
138
201
|
### 2b — Developer journeys (1–2 questions)
|
|
139
202
|
|
|
140
203
|
Surface lifecycle/journey skills that cross-cut task areas:
|
|
@@ -144,13 +207,22 @@ Surface lifecycle/journey skills that cross-cut task areas:
|
|
|
144
207
|
> a migrate-from-v4 walkthrough. Which of these exist in your docs
|
|
145
208
|
> or would be valuable as standalone skills?"
|
|
146
209
|
|
|
147
|
-
### 2c — Composition and ecosystem (1–
|
|
210
|
+
### 2c — Composition and ecosystem (1–3 questions)
|
|
148
211
|
|
|
149
212
|
> "Which other libraries does yours compose with most often? Are there
|
|
150
213
|
> integration patterns important enough to warrant their own skill —
|
|
151
214
|
> for example, using your library with [framework/ORM/router]?"
|
|
152
215
|
|
|
153
|
-
|
|
216
|
+
> "Are there tasks that developers might expect your library to handle,
|
|
217
|
+
> but that are actually handled by a companion library? Which tasks
|
|
218
|
+
> should we explicitly exclude from your library's skills?"
|
|
219
|
+
|
|
220
|
+
### 2d — Exclude experimental features (1 question)
|
|
221
|
+
|
|
222
|
+
> "Are there any features that are experimental, unstable, or not yet
|
|
223
|
+
> ready to document for agents? We'll exclude these from the skill set."
|
|
224
|
+
|
|
225
|
+
### 2e — Confirm initial skill map
|
|
154
226
|
|
|
155
227
|
Synthesize what you heard into a proposed skill list and present it:
|
|
156
228
|
|
|
@@ -158,6 +230,9 @@ Synthesize what you heard into a proposed skill list and present it:
|
|
|
158
230
|
> [enumerate skills with one-line descriptions]. Does this match how
|
|
159
231
|
> you think about your library? What would you add, remove, or rename?"
|
|
160
232
|
|
|
233
|
+
**── STOP ── Do not proceed to Phase 3 until the maintainer has
|
|
234
|
+
reviewed and confirmed (or corrected) the skill list.**
|
|
235
|
+
|
|
161
236
|
---
|
|
162
237
|
|
|
163
238
|
## Phase 3 — Deep read (autonomous)
|
|
@@ -170,7 +245,14 @@ gotchas.
|
|
|
170
245
|
|
|
171
246
|
Read in this order. Each step builds context for the next.
|
|
172
247
|
|
|
173
|
-
|
|
248
|
+
Before starting, list every file in the docs directory (and subdirectories).
|
|
249
|
+
Use this list as a checklist — every narrative file must be read. Do not
|
|
250
|
+
sample a subset and extrapolate.
|
|
251
|
+
|
|
252
|
+
1. **Narrative guides** — read as many as needed to build confidence in
|
|
253
|
+
your understanding. Prioritize getting-started, migration, and guides
|
|
254
|
+
covering the skill areas from Phase 2. Skip exhaustive reading of large
|
|
255
|
+
online-only doc sets.
|
|
174
256
|
2. **Migration guides** — highest-yield source for failure modes; every
|
|
175
257
|
breaking change is exactly what agents trained on older versions produce
|
|
176
258
|
3. **API reference** — scan for exports, type signatures, option shapes
|
|
@@ -417,20 +499,35 @@ Present the draft to the maintainer before starting Phase 4:
|
|
|
417
499
|
> [N] skills and [M] failure modes. I've flagged [K] specific gaps where
|
|
418
500
|
> I need your input."
|
|
419
501
|
|
|
502
|
+
Include the full draft domain_map.yaml in your message so the maintainer
|
|
503
|
+
can review it. Also include a checklist of all docs files you read.
|
|
504
|
+
|
|
505
|
+
**── STOP ── Do not proceed to Phase 4 until the maintainer has
|
|
506
|
+
reviewed the draft and responded. Their feedback on the draft informs
|
|
507
|
+
the detail interview questions.**
|
|
508
|
+
|
|
420
509
|
---
|
|
421
510
|
|
|
422
|
-
## Phase 4 — Detail interview (
|
|
511
|
+
## Phase 4 — Detail interview (interactive — requires maintainer)
|
|
423
512
|
|
|
424
513
|
You have the maintainer's task map and a deep read. The interview now
|
|
425
514
|
fills gaps, validates your understanding, and surfaces implicit knowledge.
|
|
426
515
|
|
|
516
|
+
You must ask the questions below to the maintainer and wait for their
|
|
517
|
+
responses. Do not infer answers from documentation or source code —
|
|
518
|
+
even for gaps you think you can answer from your reading.
|
|
519
|
+
|
|
427
520
|
### Rules for Phase 4
|
|
428
521
|
|
|
429
522
|
1. One topic per message for open-ended questions. You may batch 2–3
|
|
430
523
|
yes/no or short-confirmation questions together.
|
|
431
|
-
2.
|
|
432
|
-
|
|
433
|
-
|
|
524
|
+
2. Ask each question as written (you may adapt phrasing to context, but
|
|
525
|
+
keep questions open-ended — never convert to multiple-choice).
|
|
526
|
+
3. Each question must reference something specific from your reading.
|
|
527
|
+
4. Wait for the maintainer's response after each question before asking
|
|
528
|
+
the next.
|
|
529
|
+
5. If the maintainer gives a short answer, probe deeper before moving on.
|
|
530
|
+
6. Take notes silently. Do not summarize back unless asked.
|
|
434
531
|
|
|
435
532
|
### 4a — Draft review (2–3 questions)
|
|
436
533
|
|
|
@@ -538,6 +635,10 @@ Merge interview findings into the draft. For each interview answer:
|
|
|
538
635
|
4. If it reveals a new skill — add it
|
|
539
636
|
5. If it fills a gap — remove from gaps section
|
|
540
637
|
|
|
638
|
+
Validate the domain_map.yaml by parsing it with a YAML parser. Check for
|
|
639
|
+
duplicate keys, invalid syntax, and structural correctness. Fix any issues
|
|
640
|
+
before presenting the final artifact.
|
|
641
|
+
|
|
541
642
|
Update `status: draft` to `status: reviewed`.
|
|
542
643
|
|
|
543
644
|
---
|
|
@@ -580,6 +681,9 @@ skills:
|
|
|
580
681
|
domain: '[parent domain slug]'
|
|
581
682
|
description: '[what a developer is doing — matches a specific task/moment]'
|
|
582
683
|
type: '[core | framework | lifecycle | composition]'
|
|
684
|
+
packages: # required for monorepo; omit for single-package libraries
|
|
685
|
+
- '[primary package name]'
|
|
686
|
+
- '[secondary package name, if skill spans multiple packages]'
|
|
583
687
|
covers:
|
|
584
688
|
- '[API/hook/concept 1]'
|
|
585
689
|
- '[API/hook/concept 2]'
|
|
@@ -710,6 +814,11 @@ not promotional.]
|
|
|
710
814
|
| ------------------------------------- | -------------------------------------------------------------------------- |
|
|
711
815
|
| Quick scan before interview | Never interview without at least reading README and package structure |
|
|
712
816
|
| High-level interview before deep read | The maintainer's task map informs what you read deeply |
|
|
817
|
+
| **Interview phases are interactive** | Phases 2 and 4 require sending questions to the maintainer and waiting |
|
|
818
|
+
| **Docs are not a substitute** | Documentation cannot replace maintainer answers — even comprehensive docs |
|
|
819
|
+
| **Open-ended questions stay open** | Never convert interview questions to multiple-choice or yes/no |
|
|
820
|
+
| **Minimum question counts enforced** | Each sub-section's minimum count must be met; zero questions = violation |
|
|
821
|
+
| **STOP gates are mandatory** | Do not proceed past a STOP gate without maintainer response |
|
|
713
822
|
| Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message |
|
|
714
823
|
| Questions reference findings | No generic questions — cite what you found |
|
|
715
824
|
| Skills are task-focused | Each skill matches a developer moment, not a conceptual area |
|
|
@@ -719,6 +828,7 @@ not promotional.]
|
|
|
719
828
|
| No marketing prose | Library description is factual, not promotional |
|
|
720
829
|
| domain_map.yaml is valid YAML | Parseable by any YAML parser |
|
|
721
830
|
| Draft before detail interview | Present draft for review before Phase 4 |
|
|
831
|
+
| **Draft reviewed before Phase 4** | Maintainer must acknowledge or respond to draft before detail interview |
|
|
722
832
|
| Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c |
|
|
723
833
|
| Compositions discovered from code | Scan peer deps and examples before asking composition questions |
|
|
724
834
|
| Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs |
|
|
@@ -727,6 +837,7 @@ not promotional.]
|
|
|
727
837
|
| Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates |
|
|
728
838
|
| Lifecycle skills considered | Suggest journey skills when docs have the material |
|
|
729
839
|
| Cross-references mapped | Skills that illuminate each other get "See also" pointers |
|
|
840
|
+
| **All docs files read** | List docs directory contents and read every narrative file — no sampling |
|
|
730
841
|
|
|
731
842
|
---
|
|
732
843
|
|
|
@@ -736,49 +847,16 @@ This skill is designed to produce consistent results across Claude, GPT-4+,
|
|
|
736
847
|
Gemini, and open-source models. To achieve this:
|
|
737
848
|
|
|
738
849
|
- All instructions use imperative sentences, not suggestions
|
|
850
|
+
- Interview phases use explicit STOP gates to prevent models from
|
|
851
|
+
continuing autonomously past interactive checkpoints
|
|
852
|
+
- Hard rules at the top override any model tendency to rationalize
|
|
853
|
+
skipping interactive phases when documentation is available
|
|
854
|
+
- Open-ended questions are explicitly protected from conversion to
|
|
855
|
+
multiple-choice or confirmation prompts, which models default to
|
|
856
|
+
when they have enough context to pre-populate answers
|
|
739
857
|
- Output formats use YAML (universally parsed) and Markdown tables
|
|
740
858
|
(universally rendered)
|
|
741
859
|
- Examples use concrete values, not placeholders like "[your value here]"
|
|
742
860
|
- Section boundaries use Markdown headers (##) for navigation and --- for
|
|
743
861
|
phase separation
|
|
744
862
|
- No model-specific features (no XML tags in output, no tool_use assumptions)
|
|
745
|
-
|
|
746
|
-
---
|
|
747
|
-
|
|
748
|
-
## Meta-skill feedback (alpha default)
|
|
749
|
-
|
|
750
|
-
After finalizing artifacts, create or update a single Markdown feedback draft
|
|
751
|
-
for all three meta skills used in scaffolding. Use this exact template and
|
|
752
|
-
fill only the **Domain Discovery** section now. Leave the other sections in
|
|
753
|
-
place for later steps to complete.
|
|
754
|
-
|
|
755
|
-
```
|
|
756
|
-
# Intent Meta Skill Feedback
|
|
757
|
-
|
|
758
|
-
## Domain Discovery
|
|
759
|
-
- What worked well:
|
|
760
|
-
- What was confusing or missing:
|
|
761
|
-
- Suggestions for improvement:
|
|
762
|
-
- Overall rating: good | mixed | bad
|
|
763
|
-
|
|
764
|
-
## Tree Generator
|
|
765
|
-
- What worked well:
|
|
766
|
-
- What was confusing or missing:
|
|
767
|
-
- Suggestions for improvement:
|
|
768
|
-
- Overall rating: good | mixed | bad
|
|
769
|
-
|
|
770
|
-
## Generate Skill
|
|
771
|
-
- What worked well:
|
|
772
|
-
- What was confusing or missing:
|
|
773
|
-
- Suggestions for improvement:
|
|
774
|
-
- Overall rating: good | mixed | bad
|
|
775
|
-
|
|
776
|
-
## Context (optional)
|
|
777
|
-
- Library:
|
|
778
|
-
- Repo:
|
|
779
|
-
- Docs:
|
|
780
|
-
- Notes:
|
|
781
|
-
```
|
|
782
|
-
|
|
783
|
-
Do not submit feedback yet. Tell the maintainer to carry this draft forward
|
|
784
|
-
to the next meta skill step.
|
|
@@ -17,6 +17,12 @@ Run this at the end of any session where you loaded one or more SKILL.md files.
|
|
|
17
17
|
The goal is to capture what worked, what didn't, and what was missing — so skill
|
|
18
18
|
maintainers can improve future versions.
|
|
19
19
|
|
|
20
|
+
This skill also covers **meta-skill feedback** — feedback about the scaffolding
|
|
21
|
+
process itself. When invoked after running domain-discovery, tree-generator, and
|
|
22
|
+
generate-skill, treat those three meta skills as the "skills" being evaluated.
|
|
23
|
+
Capture what worked and what didn't in each scaffolding phase so the meta skills
|
|
24
|
+
can be improved.
|
|
25
|
+
|
|
20
26
|
---
|
|
21
27
|
|
|
22
28
|
## Phase 1 — Automated Signal Collection
|
|
@@ -145,6 +151,27 @@ Determine the target repo from the skill's package. The repo is typically
|
|
|
145
151
|
derivable from the `repository` field in the package's `package.json`, or
|
|
146
152
|
from the `sources` field in the SKILL.md frontmatter.
|
|
147
153
|
|
|
154
|
+
### Privacy check
|
|
155
|
+
|
|
156
|
+
Before submitting, determine whether the user's project is public or private.
|
|
157
|
+
Check with `gh repo view --json visibility` or look for a `private` field in
|
|
158
|
+
the project's `package.json`. If you can't determine visibility, assume private.
|
|
159
|
+
|
|
160
|
+
**Private repos:** Feedback is submitted to a public issue tracker, so it must
|
|
161
|
+
not contain project-specific details. Before submission:
|
|
162
|
+
|
|
163
|
+
1. Strip any project-specific code, file paths, internal API names, service
|
|
164
|
+
URLs, or business logic from all fields
|
|
165
|
+
2. Rewrite the "Task" field to describe the _type_ of task generically
|
|
166
|
+
(e.g. "set up authenticated data fetching" not "set up auth for our
|
|
167
|
+
internal billing API at api.acme.corp/billing")
|
|
168
|
+
3. Rewrite "What Failed" and "Missing" entries to reference only the
|
|
169
|
+
skill's own APIs and patterns, not the user's code
|
|
170
|
+
4. Show the sanitized feedback to the user and ask them to confirm it's
|
|
171
|
+
safe to submit before proceeding
|
|
172
|
+
|
|
173
|
+
**Public repos:** No sanitization needed. Proceed directly to submission.
|
|
174
|
+
|
|
148
175
|
### If `gh` CLI is available
|
|
149
176
|
|
|
150
177
|
Submit directly as a GitHub issue:
|
|
@@ -79,6 +79,15 @@ skill-tree-generator for the full spec of each type.
|
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
82
|
+
### Subagent guidance for batch generation
|
|
83
|
+
|
|
84
|
+
When generating multiple skills, spawn a separate subagent for each skill
|
|
85
|
+
(or per-package group). Each subagent receives the domain_map.yaml,
|
|
86
|
+
skill_tree.yaml, and the source docs relevant to its skill. This prevents
|
|
87
|
+
context bleed between skills and allows parallel generation.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
82
91
|
## Step 2 — Extract content from sources
|
|
83
92
|
|
|
84
93
|
**Line budget:** Each SKILL.md must stay under 500 lines. Before writing,
|
|
@@ -319,6 +328,10 @@ Run every check before outputting. Fix any failures.
|
|
|
319
328
|
|
|
320
329
|
## Step 6 — Output
|
|
321
330
|
|
|
331
|
+
Before generating, ask the maintainer: "Would you like to review each skill
|
|
332
|
+
individually before I generate the next one, or should I generate all skills
|
|
333
|
+
and you review them together?" Respect their preference.
|
|
334
|
+
|
|
322
335
|
Output the complete SKILL.md file content. If reference files are needed,
|
|
323
336
|
output those as well with their relative paths.
|
|
324
337
|
|
|
@@ -381,48 +394,9 @@ Output is consumed by all major AI coding agents. To ensure consistency:
|
|
|
381
394
|
|
|
382
395
|
---
|
|
383
396
|
|
|
384
|
-
## Meta-skill feedback
|
|
385
|
-
|
|
386
|
-
After generating the first iteration of skills, complete a single Markdown
|
|
387
|
-
feedback draft for all three meta skills used in scaffolding. If a draft
|
|
388
|
-
exists from previous steps, keep it and fill the **Generate Skill** section.
|
|
389
|
-
If no draft exists, create it using this exact template.
|
|
390
|
-
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
# Intent Meta Skill Feedback
|
|
394
|
-
|
|
395
|
-
## Domain Discovery
|
|
396
|
-
|
|
397
|
-
- What worked well:
|
|
398
|
-
- What was confusing or missing:
|
|
399
|
-
- Suggestions for improvement:
|
|
400
|
-
- Overall rating: good | mixed | bad
|
|
401
|
-
|
|
402
|
-
## Tree Generator
|
|
403
|
-
|
|
404
|
-
- What worked well:
|
|
405
|
-
- What was confusing or missing:
|
|
406
|
-
- Suggestions for improvement:
|
|
407
|
-
- Overall rating: good | mixed | bad
|
|
408
|
-
|
|
409
|
-
## Generate Skill
|
|
410
|
-
|
|
411
|
-
- What worked well:
|
|
412
|
-
- What was confusing or missing:
|
|
413
|
-
- Suggestions for improvement:
|
|
414
|
-
- Overall rating: good | mixed | bad
|
|
415
|
-
|
|
416
|
-
## Context (optional)
|
|
417
|
-
|
|
418
|
-
- Library:
|
|
419
|
-
- Repo:
|
|
420
|
-
- Docs:
|
|
421
|
-
- Notes:
|
|
422
|
-
|
|
423
|
-
```
|
|
397
|
+
## Meta-skill feedback
|
|
424
398
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
399
|
+
After generating all skills, run the `skill-feedback-collection` skill to
|
|
400
|
+
capture feedback about the scaffolding process (domain-discovery,
|
|
401
|
+
tree-generator, and generate-skill).
|
|
428
402
|
```
|
|
@@ -274,14 +274,9 @@ packages/
|
|
|
274
274
|
│ └── package.json # Add "skills" to files array
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
```json
|
|
281
|
-
{
|
|
282
|
-
"files": ["dist", "src", "skills"]
|
|
283
|
-
}
|
|
284
|
-
```
|
|
277
|
+
Run `intent edit-package-json` to wire each package's `package.json`
|
|
278
|
+
automatically (adds `"skills"`, `"bin"`, and `"!skills/_artifacts"` to the
|
|
279
|
+
`files` array, and adds the `bin` entry if missing).
|
|
285
280
|
|
|
286
281
|
### Step 2 — Write the core skill
|
|
287
282
|
|
|
@@ -852,41 +847,3 @@ When updating:
|
|
|
852
847
|
3. CHANGELOG.md entry
|
|
853
848
|
|
|
854
849
|
---
|
|
855
|
-
|
|
856
|
-
## Meta-skill feedback (alpha default)
|
|
857
|
-
|
|
858
|
-
After producing the skill tree artifact, update a single Markdown feedback
|
|
859
|
-
draft for all three meta skills used in scaffolding. If a draft exists from
|
|
860
|
-
Domain Discovery, keep it and fill only the **Tree Generator** section. If
|
|
861
|
-
no draft exists, create it using this exact template.
|
|
862
|
-
|
|
863
|
-
```
|
|
864
|
-
# Intent Meta Skill Feedback
|
|
865
|
-
|
|
866
|
-
## Domain Discovery
|
|
867
|
-
- What worked well:
|
|
868
|
-
- What was confusing or missing:
|
|
869
|
-
- Suggestions for improvement:
|
|
870
|
-
- Overall rating: good | mixed | bad
|
|
871
|
-
|
|
872
|
-
## Tree Generator
|
|
873
|
-
- What worked well:
|
|
874
|
-
- What was confusing or missing:
|
|
875
|
-
- Suggestions for improvement:
|
|
876
|
-
- Overall rating: good | mixed | bad
|
|
877
|
-
|
|
878
|
-
## Generate Skill
|
|
879
|
-
- What worked well:
|
|
880
|
-
- What was confusing or missing:
|
|
881
|
-
- Suggestions for improvement:
|
|
882
|
-
- Overall rating: good | mixed | bad
|
|
883
|
-
|
|
884
|
-
## Context (optional)
|
|
885
|
-
- Library:
|
|
886
|
-
- Repo:
|
|
887
|
-
- Docs:
|
|
888
|
-
- Notes:
|
|
889
|
-
```
|
|
890
|
-
|
|
891
|
-
Do not submit feedback yet. Carry this draft forward to the generate-skill
|
|
892
|
-
step.
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/setup.d.ts
|
|
2
|
-
interface SetupResult {
|
|
3
|
-
workflows: string[];
|
|
4
|
-
skipped: string[];
|
|
5
|
-
shim: string | null;
|
|
6
|
-
}
|
|
7
|
-
declare function runSetup(root: string, metaDir: string, args: string[]): SetupResult;
|
|
8
|
-
//#endregion
|
|
9
|
-
export { runSetup as n, SetupResult as t };
|
package/dist/setup-DGvdyKEq.mjs
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
//#region src/setup.ts
|
|
5
|
-
function detectVars(root) {
|
|
6
|
-
const pkgPath = join(root, "package.json");
|
|
7
|
-
let pkgJson = {};
|
|
8
|
-
try {
|
|
9
|
-
pkgJson = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
10
|
-
} catch {}
|
|
11
|
-
const name = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
|
|
12
|
-
const intent = pkgJson.intent;
|
|
13
|
-
const repo = typeof intent?.repo === "string" ? intent.repo : name.replace(/^@/, "").replace(/\//, "/");
|
|
14
|
-
const docs = typeof intent?.docs === "string" ? intent.docs : "docs/";
|
|
15
|
-
let srcPath = `packages/${name.replace(/^@[^/]+\//, "")}/src/**`;
|
|
16
|
-
if (existsSync(join(root, "src"))) srcPath = "src/**";
|
|
17
|
-
return {
|
|
18
|
-
PACKAGE_NAME: name,
|
|
19
|
-
REPO: repo,
|
|
20
|
-
DOCS_PATH: docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**",
|
|
21
|
-
SRC_PATH: srcPath
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function applyVars(content, vars) {
|
|
25
|
-
return content.replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME).replace(/\{\{REPO\}\}/g, vars.REPO).replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH).replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH);
|
|
26
|
-
}
|
|
27
|
-
function copyTemplates(srcDir, destDir, vars) {
|
|
28
|
-
const copied = [];
|
|
29
|
-
const skipped = [];
|
|
30
|
-
if (!existsSync(srcDir)) return {
|
|
31
|
-
copied,
|
|
32
|
-
skipped
|
|
33
|
-
};
|
|
34
|
-
mkdirSync(destDir, { recursive: true });
|
|
35
|
-
for (const entry of readdirSync(srcDir)) {
|
|
36
|
-
const srcPath = join(srcDir, entry);
|
|
37
|
-
const destPath = join(destDir, entry);
|
|
38
|
-
if (existsSync(destPath)) {
|
|
39
|
-
skipped.push(destPath);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
writeFileSync(destPath, applyVars(readFileSync(srcPath, "utf8"), vars));
|
|
43
|
-
copied.push(destPath);
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
copied,
|
|
47
|
-
skipped
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function getShimContent(ext) {
|
|
51
|
-
return `#!/usr/bin/env node
|
|
52
|
-
// Auto-generated by @tanstack/intent setup
|
|
53
|
-
// Exposes the intent end-user CLI for consumers of this library.
|
|
54
|
-
// Commit this file, then add to your package.json:
|
|
55
|
-
// "bin": { "intent": "./bin/intent.${ext}" }
|
|
56
|
-
await import('@tanstack/intent/intent-library')
|
|
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
|
-
}
|
|
72
|
-
function generateShim(root, result) {
|
|
73
|
-
const existingShim = findExistingShim(root);
|
|
74
|
-
if (existingShim) {
|
|
75
|
-
result.skipped.push(existingShim);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const ext = detectShimExtension(root);
|
|
79
|
-
const shimPath = join(root, "bin", `intent.${ext}`);
|
|
80
|
-
mkdirSync(join(root, "bin"), { recursive: true });
|
|
81
|
-
writeFileSync(shimPath, getShimContent(ext));
|
|
82
|
-
result.shim = shimPath;
|
|
83
|
-
}
|
|
84
|
-
function runSetup(root, metaDir, args) {
|
|
85
|
-
const doAll = args.includes("--all");
|
|
86
|
-
const doWorkflows = doAll || args.includes("--workflows");
|
|
87
|
-
const doShim = doAll || args.includes("--shim");
|
|
88
|
-
const noFlagsGiven = !doWorkflows && !doShim;
|
|
89
|
-
const installWorkflows = doWorkflows || noFlagsGiven;
|
|
90
|
-
const installShim = doShim || noFlagsGiven;
|
|
91
|
-
const vars = detectVars(root);
|
|
92
|
-
const result = {
|
|
93
|
-
workflows: [],
|
|
94
|
-
skipped: [],
|
|
95
|
-
shim: null
|
|
96
|
-
};
|
|
97
|
-
const templatesDir = join(metaDir, "templates");
|
|
98
|
-
if (installWorkflows) {
|
|
99
|
-
const { copied, skipped } = copyTemplates(join(templatesDir, "workflows"), join(root, ".github", "workflows"), vars);
|
|
100
|
-
result.workflows = copied;
|
|
101
|
-
result.skipped.push(...skipped);
|
|
102
|
-
}
|
|
103
|
-
if (installShim) generateShim(root, result);
|
|
104
|
-
for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
|
|
105
|
-
for (const f of result.skipped) console.log(` Already exists: ${f}`);
|
|
106
|
-
if (result.shim) {
|
|
107
|
-
const shimRelative = result.shim.replace(root + "/", "./");
|
|
108
|
-
console.log(`✓ Generated intent shim: ${result.shim}`);
|
|
109
|
-
console.log(`\n Add to your package.json:`);
|
|
110
|
-
console.log(` "bin": { "intent": "${shimRelative}" }`);
|
|
111
|
-
console.log(`\n Add "bin" to your package.json "files" array.`);
|
|
112
|
-
}
|
|
113
|
-
if (result.workflows.length === 0 && result.shim === null && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
|
|
114
|
-
else if (result.workflows.length > 0) {
|
|
115
|
-
console.log(`\nTemplate variables applied:`);
|
|
116
|
-
console.log(` Package: ${vars.PACKAGE_NAME}`);
|
|
117
|
-
console.log(` Repo: ${vars.REPO}`);
|
|
118
|
-
console.log(` Docs: ${vars.DOCS_PATH}`);
|
|
119
|
-
console.log(` Src: ${vars.SRC_PATH}`);
|
|
120
|
-
}
|
|
121
|
-
return result;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
//#endregion
|
|
125
|
-
export { runSetup as t };
|