@skill-map/cli 0.67.0 → 0.68.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/tutorial/sm-tutorial/SKILL.md +30 -23
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/agents-hub/providers/agent-skills/en/agents-hub.md +2 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/agents-hub/providers/agent-skills/es/agents-hub.md +2 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/content-editor-style/providers/agent-skills/en/content-editor-style.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/content-editor-style/providers/agent-skills/es/content-editor-style.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/en/todo-bullet-guideline.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/en/todo-bullet-guideline2.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/en/todo-bullet-skill.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/es/todo-bullet-guideline.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/es/todo-bullet-guideline2.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/edits/todo-connectors/providers/agent-skills/es/todo-bullet-skill.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/manifest.json +9 -4
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/harness/providers/agent-skills/en/__PROVIDER__/skills/publish/SKILL.md +15 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/harness/providers/agent-skills/es/__PROVIDER__/skills/publish/SKILL.md +16 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/harness/providers/codex/en/__PROVIDER__/skills/publish/SKILL.md +15 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/harness/providers/codex/es/__PROVIDER__/skills/publish/SKILL.md +16 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/master/providers/agent-skills/en/__PROVIDER__/skills/master-agent/SKILL.md +13 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/master/providers/agent-skills/es/__PROVIDER__/skills/master-agent/SKILL.md +14 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/master/providers/codex/en/.codex/agents/master-agent.toml +10 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/master/providers/codex/es/.codex/agents/master-agent.toml +10 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/en/AGENTS.md +7 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/en/__PROVIDER__/skills/content-editor/SKILL.md +20 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/es/AGENTS.md +7 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/es/__PROVIDER__/skills/content-editor/SKILL.md +20 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/shared/CLAUDE.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/codex/en/.codex/agents/content-editor.toml +19 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/codex/es/.codex/agents/content-editor.toml +19 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/prologue/providers/codex/en/.codex/agents/demo-agent.toml +13 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/prologue/providers/codex/en/__PROVIDER__/skills/demo-command/SKILL.md +11 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/prologue/providers/codex/es/.codex/agents/demo-agent.toml +13 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/prologue/providers/codex/es/__PROVIDER__/skills/demo-command/SKILL.md +12 -0
- package/dist/cli/tutorial/sm-tutorial/references/_core.md +102 -49
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.json +168 -20
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +85 -19
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +6 -7
- package/dist/cli/tutorial/sm-tutorial/references/part-authoring.md +2 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-daily.md +241 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-fundamentals.md +351 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-kickoff.md +285 -0
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-daily-loop.md +62 -99
- package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +35 -34
- package/dist/cli/tutorial/sm-tutorial/references/part-mcp.md +3 -6
- package/dist/cli/tutorial/sm-tutorial/references/part-plugins.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +198 -26
- package/dist/cli/tutorial/sm-tutorial/references/part-settings.md +19 -15
- package/dist/cli/tutorial/sm-tutorial/scripts/fixtures.js +85 -22
- package/dist/cli/tutorial/sm-tutorial/scripts/lib/paths.js +74 -4
- package/dist/cli/tutorial/sm-tutorial/scripts/state.js +22 -6
- package/dist/cli.js +409 -168
- package/dist/conformance/index.js +42 -2
- package/dist/index.js +43 -30
- package/dist/kernel/index.d.ts +28 -5
- package/dist/kernel/index.js +43 -30
- package/dist/ui/chunk-22EQLC23.js +1845 -0
- package/dist/ui/chunk-3ANNEMV4.js +499 -0
- package/dist/ui/{chunk-5BJGO7GH.js → chunk-3U4QZKU2.js} +4 -4
- package/dist/ui/chunk-3ZAHOYQ7.js +1 -0
- package/dist/ui/{chunk-56CBK7LB.js → chunk-6FGV5O5J.js} +1 -1
- package/dist/ui/chunk-7WMT2LX4.js +1 -0
- package/dist/ui/{chunk-276RLZR4.js → chunk-BSIR3ADF.js} +14 -14
- package/dist/ui/{chunk-FC22ZJQZ.js → chunk-CG25RHMO.js} +1 -1
- package/dist/ui/chunk-EFSC6SOL.js +3 -0
- package/dist/ui/chunk-EJVWTBMV.js +4 -0
- package/dist/ui/chunk-EZI3BXQN.js +1 -0
- package/dist/ui/{chunk-JZ2YF7EL.js → chunk-GUPPOK7U.js} +8 -8
- package/dist/ui/{chunk-CJURGJTN.js → chunk-HLALESGR.js} +1 -1
- package/dist/ui/chunk-I3I4KHR5.js +2 -0
- package/dist/ui/{chunk-BOVJVOLH.js → chunk-I6ED2OW7.js} +1 -1
- package/dist/ui/chunk-JKPG5PO7.js +375 -0
- package/dist/ui/chunk-K3ZRQNN5.js +2 -0
- package/dist/ui/chunk-KHDWXSGR.js +1 -0
- package/dist/ui/{chunk-HEK4PH5A.js → chunk-KMHXNOFZ.js} +1 -1
- package/dist/ui/chunk-KWT7E2RJ.js +16 -0
- package/dist/ui/{chunk-WHZVGOS3.js → chunk-MQSU6EFZ.js} +1 -1
- package/dist/ui/{chunk-43S72FTV.js → chunk-OGEE252A.js} +1 -1
- package/dist/ui/{chunk-J4J42HJ4.js → chunk-PU5OP5RN.js} +1 -1
- package/dist/ui/{chunk-UTRZTB6V.js → chunk-QVG7J2MP.js} +1 -1
- package/dist/ui/chunk-TLMV4LOQ.js +3 -0
- package/dist/ui/chunk-TQBXK5JN.js +1 -0
- package/dist/ui/chunk-Z7SOKILO.js +2 -0
- package/dist/ui/{chunk-WCABR6TI.js → chunk-ZRJ5ZCFR.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/ui/main-R7BIU4HU.js +4 -0
- package/dist/ui/styles-VEGETYWD.css +1 -0
- package/package.json +17 -18
- package/dist/cli/tutorial/sm-tutorial/references/part-connect-harness.md +0 -173
- package/dist/ui/chunk-34ZZDYNQ.js +0 -1
- package/dist/ui/chunk-444BFYGR.js +0 -3
- package/dist/ui/chunk-44VNNUSQ.js +0 -2
- package/dist/ui/chunk-4SG4352Z.js +0 -7
- package/dist/ui/chunk-5ITZXW3A.js +0 -1
- package/dist/ui/chunk-7ANZW2OI.js +0 -499
- package/dist/ui/chunk-BJ6X6WBO.js +0 -4
- package/dist/ui/chunk-CZSLV6YD.js +0 -1
- package/dist/ui/chunk-DLYJHLJX.js +0 -2
- package/dist/ui/chunk-LGFABCIA.js +0 -16
- package/dist/ui/chunk-LPDD2DHE.js +0 -369
- package/dist/ui/chunk-P3SNMV4X.js +0 -2
- package/dist/ui/chunk-S4S5ZMXJ.js +0 -3
- package/dist/ui/chunk-VHEFRMK3.js +0 -1
- package/dist/ui/chunk-X6TRIDBI.js +0 -1845
- package/dist/ui/main-V77F2KZX.js +0 -4
- package/dist/ui/styles-I4ULXD3V.css +0 -1
- /package/dist/ui/{chunk-Y2Z26SRI.js → chunk-5RNLC6V4.js} +0 -0
|
@@ -34,7 +34,8 @@ import { parseArgs } from './lib/args.js';
|
|
|
34
34
|
import { emit, succeed, die } from './lib/io.js';
|
|
35
35
|
import { loadFixturesManifest, fixturesDir, resolveFootprint } from './lib/fixtures-manifest.js';
|
|
36
36
|
import {
|
|
37
|
-
providerDir, kindsFor, resolveTargetPath, kindForPath,
|
|
37
|
+
providerDir, kindsFor, resolveTargetPath, kindForPath, nodeIdForTokenPath, overlayKey,
|
|
38
|
+
fragmentKindsFor, PROVIDER_TOKEN,
|
|
38
39
|
} from './lib/paths.js';
|
|
39
40
|
|
|
40
41
|
function opts(args) {
|
|
@@ -68,38 +69,76 @@ function writeFileEnsuring(abs, content) {
|
|
|
68
69
|
|
|
69
70
|
/**
|
|
70
71
|
* Lay one set's files for the given lang + provider. `only` (a Set of
|
|
71
|
-
* token-form relpaths) restricts to those
|
|
72
|
-
* progressive reveal where each chapter lands its
|
|
72
|
+
* token-form relpaths, claude-shaped and lens-agnostic) restricts to those
|
|
73
|
+
* nodes, for the prologue's progressive reveal where each chapter lands its
|
|
74
|
+
* own nodes; matching is by logical node id so a claude-shaped `--only`
|
|
75
|
+
* entry still selects the agent-skills skill overlay of the same node.
|
|
76
|
+
*
|
|
77
|
+
* Tiers, in lay order (later wins): lang-invariant `shared/`, the language
|
|
78
|
+
* tier, then the per-provider overlay (`providers/<provider>/{shared,<lang>}/`).
|
|
79
|
+
* The overlay carries the skill-shaped variants of nodes a lens renders
|
|
80
|
+
* differently (e.g. the `content-editor` agent becomes a skill on
|
|
81
|
+
* agent-skills); claude declares no overlay because the base IS its shape.
|
|
73
82
|
*/
|
|
74
83
|
function laySet(manifest, set, o, only = null) {
|
|
75
84
|
const { kinds } = pdirAndKinds(o);
|
|
76
85
|
if (!manifest.sets.includes(set)) die('unknown-set', `set '${set}' is not in the manifest.`);
|
|
77
86
|
const base = join(fixturesDir(), 'sets', set);
|
|
78
87
|
const langDir = existsSync(join(base, o.lang)) ? o.lang : (manifest.defaultLang ?? 'en');
|
|
88
|
+
const onlyIds = only ? new Set([...only].map(nodeIdForTokenPath)) : null;
|
|
89
|
+
const oKey = overlayKey(o.provider);
|
|
79
90
|
const laid = [];
|
|
91
|
+
const laidIds = new Set();
|
|
80
92
|
const skipped = [];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
const tiers = [
|
|
94
|
+
join(base, 'shared'),
|
|
95
|
+
join(base, langDir),
|
|
96
|
+
join(base, 'providers', oKey, 'shared'),
|
|
97
|
+
join(base, 'providers', oKey, langDir),
|
|
98
|
+
];
|
|
99
|
+
for (const tierRoot of tiers) {
|
|
84
100
|
for (const rel of walk(tierRoot)) {
|
|
85
101
|
// `rel` is the token-form target path (e.g. __PROVIDER__/agents/x.md).
|
|
86
|
-
if (
|
|
102
|
+
if (onlyIds && !onlyIds.has(nodeIdForTokenPath(rel))) continue;
|
|
87
103
|
const kind = kindForPath(rel);
|
|
88
104
|
if (!kinds.has(kind)) { skipped.push({ path: rel, kind }); continue; }
|
|
89
105
|
const target = resolveTargetPath(rel, o.provider);
|
|
90
106
|
writeFileEnsuring(join(process.cwd(), target), readFileSync(join(tierRoot, rel)));
|
|
91
107
|
laid.push(target);
|
|
108
|
+
laidIds.add(nodeIdForTokenPath(rel));
|
|
92
109
|
}
|
|
93
110
|
}
|
|
94
|
-
|
|
111
|
+
// Drop from `skipped` any node that the overlay laid under another kind
|
|
112
|
+
// (the claude-shaped agent file is skipped, but its skill overlay landed),
|
|
113
|
+
// so the report only flags nodes genuinely absent on this lens.
|
|
114
|
+
const netSkipped = skipped.filter((s) => !laidIds.has(nodeIdForTokenPath(s.path)));
|
|
115
|
+
return { laid, skipped: netSkipped };
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
|
|
118
|
+
// Count UNIQUE `.md` targets: a per-provider overlay can overwrite a base
|
|
119
|
+
// file (e.g. the open-standard `AGENTS.md` handbook), so `laid` may list the
|
|
120
|
+
// same target twice; the node count is the on-disk reality, not the write count.
|
|
121
|
+
const nodeCount = (paths) => new Set(paths.filter((p) => p.endsWith('.md'))).size;
|
|
98
122
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Resolve a fragment file path. A per-provider overlay
|
|
125
|
+
* (`edits/<id>/providers/<provider>/<lang>/`) wins when present, mirroring
|
|
126
|
+
* the set overlay, a fragment with a relative link to a provider-dir file
|
|
127
|
+
* is depth-sensitive (the content-editor lives one level deeper as a skill
|
|
128
|
+
* under agent-skills), so its link text differs per lens. Falls back to the
|
|
129
|
+
* shared fragment, then to the default language for either tier.
|
|
130
|
+
*/
|
|
131
|
+
function fragmentPath(manifest, id, o, file) {
|
|
132
|
+
const def = manifest.defaultLang ?? 'en';
|
|
133
|
+
const dir = join(fixturesDir(), 'edits', id);
|
|
134
|
+
const oKey = overlayKey(o.provider);
|
|
135
|
+
const candidates = [
|
|
136
|
+
join(dir, 'providers', oKey, o.lang, file),
|
|
137
|
+
join(dir, 'providers', oKey, def, file),
|
|
138
|
+
join(dir, o.lang, file),
|
|
139
|
+
join(dir, def, file),
|
|
140
|
+
];
|
|
141
|
+
return candidates.find((c) => existsSync(c)) ?? candidates[candidates.length - 1];
|
|
103
142
|
}
|
|
104
143
|
|
|
105
144
|
/** Apply one manifest edit (append fragments) honoring requiresKind. */
|
|
@@ -107,14 +146,30 @@ function applyEdit(manifest, id, o) {
|
|
|
107
146
|
const { kinds } = pdirAndKinds(o);
|
|
108
147
|
const def = manifest.edits?.[id];
|
|
109
148
|
if (!def) die('unknown-edit', `edit '${id}' is not in the manifest.`);
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
149
|
+
// Resolve the target to the shape this provider actually laid. When the
|
|
150
|
+
// declared (claude-shaped) target's kind is unclaimed, fall back to the
|
|
151
|
+
// skill-overlay path for the same node id, agent-skills renders the
|
|
152
|
+
// content-editor agent as a skill, so the style fragment must append to
|
|
153
|
+
// that skill body. Only genuinely-absent nodes skip the edit.
|
|
154
|
+
let targetTok = def.target;
|
|
155
|
+
if (!kinds.has(kindForPath(targetTok))) {
|
|
156
|
+
const skillTok = `${PROVIDER_TOKEN}/skills/${nodeIdForTokenPath(def.target)}/SKILL.md`;
|
|
157
|
+
const skillAbs = join(process.cwd(), resolveTargetPath(skillTok, o.provider));
|
|
158
|
+
if (kinds.has('skill') && existsSync(skillAbs)) {
|
|
159
|
+
targetTok = skillTok;
|
|
160
|
+
} else {
|
|
161
|
+
return { target: resolveTargetPath(def.target, o.provider), appended: [], skipped: true };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const target = resolveTargetPath(targetTok, o.provider);
|
|
114
165
|
const targetAbs = join(process.cwd(), target);
|
|
115
166
|
if (!existsSync(targetAbs)) die('edit-target-missing', `edit '${id}' target not found: ${target}`);
|
|
116
167
|
|
|
117
|
-
|
|
168
|
+
// Fragment gating is by TRACK, not the base-tier `kinds`: a rich provider
|
|
169
|
+
// (codex) links to agent / command roles it renders via overlay (TOML agent,
|
|
170
|
+
// command-as-skill), so those bullets apply even though its base kinds omit them.
|
|
171
|
+
const fragKinds = fragmentKindsFor(o.provider);
|
|
172
|
+
const fragments = (def.fragments ?? []).filter((f) => !f.requiresKind || fragKinds.has(f.requiresKind));
|
|
118
173
|
if (fragments.length === 0) return { target, appended: [] };
|
|
119
174
|
|
|
120
175
|
let content = readFileSync(targetAbs, 'utf8');
|
|
@@ -122,7 +177,7 @@ function applyEdit(manifest, id, o) {
|
|
|
122
177
|
if (def.prefix) content += def.prefix;
|
|
123
178
|
const appended = [];
|
|
124
179
|
for (const frag of fragments) {
|
|
125
|
-
content += readFileSync(fragmentPath(manifest, id, o
|
|
180
|
+
content += readFileSync(fragmentPath(manifest, id, o, frag.file), 'utf8');
|
|
126
181
|
appended.push(frag.file);
|
|
127
182
|
}
|
|
128
183
|
writeFileSync(targetAbs, content);
|
|
@@ -207,7 +262,15 @@ const VERBS = {
|
|
|
207
262
|
const langDir = existsSync(join(base, o.lang)) ? o.lang : (manifest.defaultLang ?? 'en');
|
|
208
263
|
// Accept a resolved path (`.claude/...`) or token form; normalise to token.
|
|
209
264
|
const tokenForm = file.startsWith(`${pdir}/`) ? PROVIDER_TOKEN + file.slice(pdir.length) : file;
|
|
210
|
-
|
|
265
|
+
// Prefer the per-provider overlay (so codex / agent-skills get their own
|
|
266
|
+
// shape, e.g. the publish skill or the TOML agent) before the base.
|
|
267
|
+
const oKey = overlayKey(o.provider);
|
|
268
|
+
const found = [
|
|
269
|
+
join(base, 'providers', oKey, langDir, tokenForm),
|
|
270
|
+
join(base, 'providers', oKey, 'shared', tokenForm),
|
|
271
|
+
join(base, langDir, tokenForm),
|
|
272
|
+
join(base, 'shared', tokenForm),
|
|
273
|
+
].find((c) => existsSync(c));
|
|
211
274
|
if (!found) {
|
|
212
275
|
emit({ ok: false, code: 'not-found', error: `file '${file}' not found in set '${set}'.` });
|
|
213
276
|
process.exit(1);
|
|
@@ -234,5 +297,5 @@ function main() {
|
|
|
234
297
|
}
|
|
235
298
|
|
|
236
299
|
main();
|
|
237
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
238
|
-
//# debugId=
|
|
300
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9e366749-efd9-5bc5-bba4-41147eabf625")}catch(e){}}();
|
|
301
|
+
//# debugId=9e366749-efd9-5bc5-bba4-41147eabf625
|
|
@@ -7,14 +7,22 @@
|
|
|
7
7
|
export const PROVIDER_TOKEN = '__PROVIDER__';
|
|
8
8
|
|
|
9
9
|
export function providerDir(provider) {
|
|
10
|
-
// agent-skills and
|
|
11
|
-
|
|
10
|
+
// agent-skills, Antigravity and Codex all keep their SKILLS under the
|
|
11
|
+
// open `.agents/skills/` layout. (Codex additionally has TOML agents under
|
|
12
|
+
// `.codex/agents/`, supplied by the codex overlay's literal paths, not this
|
|
13
|
+
// single base dir.)
|
|
14
|
+
return provider === 'agent-skills' || provider === 'antigravity' || provider === 'codex'
|
|
12
15
|
? '.agents/skills'
|
|
13
16
|
: '.claude';
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export const PROVIDER_KINDS = {
|
|
17
20
|
claude: new Set(['agent', 'command', 'skill', 'markdown']),
|
|
21
|
+
// Codex authors its agents as TOML under `.codex/agents/` (a different shape
|
|
22
|
+
// than the base `__PROVIDER__/agents/*.md`), so the base tier lays only its
|
|
23
|
+
// shared skill + markdown nodes; the codex overlay supplies the TOML agents
|
|
24
|
+
// and the command-as-skill nodes (Codex has no `command` kind).
|
|
25
|
+
codex: new Set(['skill', 'markdown']),
|
|
18
26
|
'agent-skills': new Set(['skill', 'markdown']),
|
|
19
27
|
antigravity: new Set(['skill', 'markdown']),
|
|
20
28
|
};
|
|
@@ -23,6 +31,44 @@ export function kindsFor(provider) {
|
|
|
23
31
|
return PROVIDER_KINDS[provider] ?? PROVIDER_KINDS.claude;
|
|
24
32
|
}
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Tutorial track for a provider, by the "does this lens have an `agent`
|
|
36
|
+
* kind?" axis (see `_core.md` §Provider detection):
|
|
37
|
+
* - `rich` (agent + skill + slash + `@`): `claude`, `codex`.
|
|
38
|
+
* - `basic` (skill + markdown, connected by markdown references): the
|
|
39
|
+
* open-standard family `agent-skills`, `antigravity`.
|
|
40
|
+
* The book renders the track's parts; the same lens always resolves to
|
|
41
|
+
* the same track, so a resumed session never re-derives it.
|
|
42
|
+
*/
|
|
43
|
+
export function trackFor(provider) {
|
|
44
|
+
return provider === 'claude' || provider === 'codex' ? 'rich' : 'basic';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The provider whose fixture overlays a given provider reuses. The
|
|
49
|
+
* open-standard family (`agent-skills`, `antigravity`) shares one on-disk
|
|
50
|
+
* shape (`.agents/skills/`, skill + markdown, connected by markdown
|
|
51
|
+
* references), so `antigravity` reuses the canonical `agent-skills`
|
|
52
|
+
* overlays rather than duplicating them. Every other provider keys its own.
|
|
53
|
+
*/
|
|
54
|
+
export function overlayKey(provider) {
|
|
55
|
+
return provider === 'antigravity' ? 'agent-skills' : provider;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Kinds whose edit fragments (the todo-connectors hub bullets, etc.) apply for
|
|
60
|
+
* a provider, keyed by TRACK, not by the base-tier kinds. A rich provider links
|
|
61
|
+
* to every node role even when it renders some differently, Codex's agent is a
|
|
62
|
+
* TOML overlay and its command-node is a skill, but an `@agent` mention and a
|
|
63
|
+
* `/command` invocation still resolve, so every bullet applies. A basic
|
|
64
|
+
* provider only has skill + markdown, so the agent / command bullets fold away.
|
|
65
|
+
*/
|
|
66
|
+
export function fragmentKindsFor(provider) {
|
|
67
|
+
return trackFor(provider) === 'rich'
|
|
68
|
+
? new Set(['agent', 'command', 'skill', 'markdown'])
|
|
69
|
+
: new Set(['skill', 'markdown']);
|
|
70
|
+
}
|
|
71
|
+
|
|
26
72
|
/**
|
|
27
73
|
* Per-provider kind directories. The token path is always written in
|
|
28
74
|
* the claude shape (`__PROVIDER__/skills/<name>/...`); resolving it is
|
|
@@ -31,6 +77,7 @@ export function kindsFor(provider) {
|
|
|
31
77
|
*/
|
|
32
78
|
const KIND_DIRS = {
|
|
33
79
|
claude: { agents: '.claude/agents', commands: '.claude/commands', skills: '.claude/skills' },
|
|
80
|
+
codex: { skills: '.agents/skills' },
|
|
34
81
|
'agent-skills': { skills: '.agents/skills' },
|
|
35
82
|
antigravity: { skills: '.agents/skills' },
|
|
36
83
|
};
|
|
@@ -64,5 +111,28 @@ export function kindForPath(tokenRelPath) {
|
|
|
64
111
|
if (tokenRelPath.startsWith(`${PROVIDER_TOKEN}/skills/`)) return 'skill';
|
|
65
112
|
return 'markdown';
|
|
66
113
|
}
|
|
67
|
-
|
|
68
|
-
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Logical, lens-agnostic node id for a token-form path. The SAME
|
|
117
|
+
* conceptual node renders in a different kind per lens (a `content-editor`
|
|
118
|
+
* is an `agent` on claude but a `skill` on agent-skills), so a `--only`
|
|
119
|
+
* filter or an edit target written in the claude shape must still match
|
|
120
|
+
* the agent-skills overlay. Agents / commands use the file stem; skills
|
|
121
|
+
* use the skill directory name; everything else (markdown, notes, docs)
|
|
122
|
+
* keeps its relpath verbatim. So both `__PROVIDER__/agents/content-editor.md`
|
|
123
|
+
* and `__PROVIDER__/skills/content-editor/SKILL.md` resolve to `content-editor`.
|
|
124
|
+
*/
|
|
125
|
+
export function nodeIdForTokenPath(tokenRelPath) {
|
|
126
|
+
const flat = tokenRelPath.match(/^__PROVIDER__\/(?:agents|commands)\/(.+)\.md$/);
|
|
127
|
+
if (flat) return flat[1];
|
|
128
|
+
const skill = tokenRelPath.match(/^__PROVIDER__\/skills\/([^/]+)\//);
|
|
129
|
+
if (skill) return skill[1];
|
|
130
|
+
// Codex renders an agent as a literal `.codex/agents/<name>.toml`; map it
|
|
131
|
+
// to the same id as the claude-shaped `__PROVIDER__/agents/<name>.md` so a
|
|
132
|
+
// `--only` filter (or the skipped-node dedup) matches across the two shapes.
|
|
133
|
+
const codexAgent = tokenRelPath.match(/^\.codex\/agents\/(.+)\.toml$/);
|
|
134
|
+
if (codexAgent) return codexAgent[1];
|
|
135
|
+
return tokenRelPath;
|
|
136
|
+
}
|
|
137
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9a867c5a-0c61-500e-a583-7d7dd6c5ac92")}catch(e){}}();
|
|
138
|
+
//# debugId=9a867c5a-0c61-500e-a583-7d7dd6c5ac92
|
|
@@ -31,7 +31,7 @@ import { rmSync, rmdirSync, readdirSync } from 'node:fs';
|
|
|
31
31
|
import { parseArgs } from './lib/args.js';
|
|
32
32
|
import { exists, readJson, writeJson, succeed, die } from './lib/io.js';
|
|
33
33
|
import { loadManifest, findPart } from './lib/manifest.js';
|
|
34
|
-
import { providerDir } from './lib/paths.js';
|
|
34
|
+
import { providerDir, trackFor } from './lib/paths.js';
|
|
35
35
|
import { loadFixturesManifest, resolveFootprint } from './lib/fixtures-manifest.js';
|
|
36
36
|
|
|
37
37
|
const STATE_FILE = 'tutorial-state.json';
|
|
@@ -68,13 +68,18 @@ const VERBS = {
|
|
|
68
68
|
if (exists(p) && !args.flags.force) {
|
|
69
69
|
die('exists', `${STATE_FILE} already exists; pass --force to overwrite.`);
|
|
70
70
|
}
|
|
71
|
+
const provider = args.flags.provider ?? 'claude';
|
|
71
72
|
const state = {
|
|
72
73
|
tutorial: {
|
|
73
74
|
version: STATE_VERSION,
|
|
74
75
|
started_at: now(),
|
|
75
76
|
cwd: args.flags.cwd ?? process.cwd(),
|
|
76
77
|
sm_version: args.flags['sm-version'] ?? null,
|
|
77
|
-
provider
|
|
78
|
+
provider,
|
|
79
|
+
// Derived from the provider (`_core.md` §Provider detection): the
|
|
80
|
+
// book renders this track's parts. `rich` = claude/codex,
|
|
81
|
+
// `basic` = the open-standard family (agent-skills/antigravity).
|
|
82
|
+
track: trackFor(provider),
|
|
78
83
|
lang: args.flags.lang ?? 'en',
|
|
79
84
|
},
|
|
80
85
|
tester: { level: 2 },
|
|
@@ -148,8 +153,13 @@ const VERBS = {
|
|
|
148
153
|
status() {
|
|
149
154
|
const state = loadState();
|
|
150
155
|
const manifest = loadManifest();
|
|
156
|
+
// Show only the active track's parts (plus `both`). The rich and basic
|
|
157
|
+
// campaigns share titles and order, so a session sees exactly one book,
|
|
158
|
+
// the track resolved at pre-flight (see `_core.md` §Routing + menu).
|
|
159
|
+
const track = state.tutorial?.track ?? 'rich';
|
|
151
160
|
const parts = manifest.parts
|
|
152
161
|
.filter((p) => p.status === 'active' || state.parts[p.id])
|
|
162
|
+
.filter((p) => !p.track || p.track === 'both' || p.track === track)
|
|
153
163
|
.map((p) => {
|
|
154
164
|
const tracked = state.parts[p.id];
|
|
155
165
|
return {
|
|
@@ -221,8 +231,14 @@ function computeWipePaths(state) {
|
|
|
221
231
|
const paths = new Set(['tutorial-state.json', 'findings.md', '.skillmapignore', '.skill-map']);
|
|
222
232
|
const addFootprint = (name) => resolveFootprint(manifest, name, provider).forEach((p) => paths.add(p));
|
|
223
233
|
|
|
224
|
-
|
|
225
|
-
|
|
234
|
+
// Each footprint covers both tracks: the rich and basic prologues /
|
|
235
|
+
// campaigns lay the same fixtures (the basic one under the open-standard
|
|
236
|
+
// provider), so either part's presence means that fixture is on disk.
|
|
237
|
+
if (has('fundamentals') || has('basic-fundamentals')) addFootprint('prologue');
|
|
238
|
+
if (
|
|
239
|
+
has('project-kickoff') || has('daily-loop')
|
|
240
|
+
|| has('basic-kickoff') || has('basic-daily')
|
|
241
|
+
) addFootprint('portfolio');
|
|
226
242
|
if (has('extend')) addFootprint('master');
|
|
227
243
|
// `cli` seeds the prologue demo fixture plus its external-ref demo.
|
|
228
244
|
if (has('cli')) { addFootprint('prologue'); addFootprint('cli-external'); }
|
|
@@ -258,5 +274,5 @@ function main() {
|
|
|
258
274
|
}
|
|
259
275
|
|
|
260
276
|
main();
|
|
261
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
262
|
-
//# debugId=
|
|
277
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3ef90c0e-0700-5a7b-a25f-c47aa19fd567")}catch(e){}}();
|
|
278
|
+
//# debugId=3ef90c0e-0700-5a7b-a25f-c47aa19fd567
|