first-tree 0.0.4 → 0.0.5
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 +17 -8
- package/dist/cli.js +4 -4
- package/dist/{help-Dtdj91HJ.js → help-5-WG9QFm.js} +1 -1
- package/dist/{init--VepFe6N.js → init-CAq0Uhq6.js} +19 -7
- package/dist/{installer-cH7N4RNj.js → installer-UgNasLjl.js} +19 -15
- package/dist/onboarding-3zYUeYQb.js +2 -0
- package/dist/onboarding-Dd63N-V1.js +10 -0
- package/dist/{repo-DY57bMqr.js → repo-DkR12VUv.js} +55 -4
- package/dist/{upgrade-Cgx_K2HM.js → upgrade-DYzuvv1k.js} +13 -8
- package/dist/{verify-mC9ZTd1f.js → verify-C0IUSkMZ.js} +1 -1
- package/package.json +12 -10
- package/skills/first-tree/SKILL.md +10 -6
- package/skills/first-tree/assets/framework/VERSION +1 -1
- package/skills/first-tree/assets/framework/examples/claude-code/README.md +2 -2
- package/skills/first-tree/assets/framework/examples/claude-code/settings.json +1 -1
- package/skills/first-tree/assets/framework/helpers/generate-codeowners.ts +1 -1
- package/skills/first-tree/assets/framework/helpers/inject-tree-context.sh +0 -0
- package/skills/first-tree/assets/framework/helpers/run-review.ts +1 -1
- package/skills/first-tree/assets/framework/templates/agents.md.template +2 -2
- package/skills/first-tree/assets/framework/templates/members-domain.md.template +1 -1
- package/skills/first-tree/assets/framework/templates/root-node.md.template +3 -3
- package/skills/first-tree/assets/framework/workflows/codeowners.yml +1 -1
- package/skills/first-tree/assets/framework/workflows/pr-review.yml +1 -1
- package/skills/first-tree/engine/init.ts +3 -2
- package/skills/first-tree/engine/repo.ts +36 -3
- package/skills/first-tree/engine/rules/agent-integration.ts +3 -1
- package/skills/first-tree/engine/rules/framework.ts +2 -2
- package/skills/first-tree/engine/runtime/adapters.ts +6 -2
- package/skills/first-tree/engine/runtime/asset-loader.ts +136 -4
- package/skills/first-tree/engine/runtime/installer.ts +18 -12
- package/skills/first-tree/engine/upgrade.ts +35 -8
- package/skills/first-tree/references/onboarding.md +28 -18
- package/skills/first-tree/references/upgrade-contract.md +49 -23
- package/skills/first-tree/scripts/check-skill-sync.sh +0 -0
- package/skills/first-tree/scripts/quick_validate.py +0 -0
- package/skills/first-tree/scripts/run-local-cli.sh +0 -0
- package/skills/first-tree/tests/asset-loader.test.ts +23 -1
- package/skills/first-tree/tests/helpers.ts +27 -3
- package/skills/first-tree/tests/init.test.ts +11 -3
- package/skills/first-tree/tests/repo.test.ts +26 -0
- package/skills/first-tree/tests/rules.test.ts +9 -7
- package/skills/first-tree/tests/skill-artifacts.test.ts +6 -0
- package/skills/first-tree/tests/upgrade.test.ts +20 -1
- package/skills/first-tree/tests/verify.test.ts +3 -3
- package/dist/onboarding-C9cYSE6F.js +0 -2
- package/dist/onboarding-CPP8fF4D.js +0 -10
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
gh pr view "$PR_NUMBER" --json headRefOid -q .headRefOid > /tmp/pr-head-sha.txt
|
|
46
46
|
|
|
47
47
|
- name: Run Claude review
|
|
48
|
-
run: npx tsx skills/first-tree/assets/framework/helpers/run-review.ts
|
|
48
|
+
run: npx tsx .agents/skills/first-tree/assets/framework/helpers/run-review.ts
|
|
49
49
|
|
|
50
50
|
- name: Parse and post review
|
|
51
51
|
run: |
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
FRAMEWORK_VERSION,
|
|
24
24
|
INSTALLED_PROGRESS,
|
|
25
25
|
LEGACY_AGENT_INSTRUCTIONS_FILE,
|
|
26
|
+
installedSkillRootsDisplay,
|
|
26
27
|
} from "#skill/engine/runtime/asset-loader.js";
|
|
27
28
|
|
|
28
29
|
/**
|
|
@@ -67,7 +68,7 @@ interface TaskListContext {
|
|
|
67
68
|
function installSkill(source: string, target: string): void {
|
|
68
69
|
copyCanonicalSkill(source, target);
|
|
69
70
|
console.log(
|
|
70
|
-
|
|
71
|
+
` Installed ${installedSkillRootsDisplay()} from the bundled first-tree package`,
|
|
71
72
|
);
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -198,7 +199,7 @@ export function runInit(repo?: Repo, options?: InitOptions): number {
|
|
|
198
199
|
console.log();
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
if (!r.
|
|
202
|
+
if (!r.hasCurrentInstalledSkill()) {
|
|
202
203
|
try {
|
|
203
204
|
const sourceRoot = options?.sourceRoot ?? resolveBundledPackageRoot();
|
|
204
205
|
console.log(
|
|
@@ -2,14 +2,19 @@ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
AGENT_INSTRUCTIONS_FILE,
|
|
5
|
+
CLAUDE_FRAMEWORK_VERSION,
|
|
6
|
+
CLAUDE_INSTALLED_PROGRESS,
|
|
5
7
|
FRAMEWORK_VERSION,
|
|
6
|
-
|
|
7
|
-
LEGACY_SKILL_VERSION,
|
|
8
|
+
INSTALLED_PROGRESS,
|
|
8
9
|
LEGACY_AGENT_INSTRUCTIONS_FILE,
|
|
9
10
|
LEGACY_PROGRESS,
|
|
11
|
+
LEGACY_REPO_SKILL_PROGRESS,
|
|
12
|
+
LEGACY_REPO_SKILL_VERSION,
|
|
13
|
+
LEGACY_SKILL_PROGRESS,
|
|
14
|
+
LEGACY_SKILL_VERSION,
|
|
10
15
|
LEGACY_VERSION,
|
|
11
|
-
INSTALLED_PROGRESS,
|
|
12
16
|
agentInstructionsFileCandidates,
|
|
17
|
+
installedSkillRoots,
|
|
13
18
|
type FrameworkLayout,
|
|
14
19
|
detectFrameworkLayout,
|
|
15
20
|
frameworkVersionCandidates,
|
|
@@ -164,6 +169,22 @@ export class Repo {
|
|
|
164
169
|
return knownConfigs.some((c) => this.pathExists(c));
|
|
165
170
|
}
|
|
166
171
|
|
|
172
|
+
installedSkillRoots(): string[] {
|
|
173
|
+
return installedSkillRoots();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
missingInstalledSkillRoots(): string[] {
|
|
177
|
+
return this.installedSkillRoots().filter(
|
|
178
|
+
(root) =>
|
|
179
|
+
!this.pathExists(join(root, "SKILL.md")) ||
|
|
180
|
+
!this.pathExists(join(root, "assets", "framework", "VERSION")),
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
hasCurrentInstalledSkill(): boolean {
|
|
185
|
+
return this.missingInstalledSkillRoots().length === 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
167
188
|
isGitRepo(): boolean {
|
|
168
189
|
return hasGitMetadata(this.root);
|
|
169
190
|
}
|
|
@@ -198,6 +219,12 @@ export class Repo {
|
|
|
198
219
|
if (layout === "legacy-skill") {
|
|
199
220
|
return LEGACY_SKILL_PROGRESS;
|
|
200
221
|
}
|
|
222
|
+
if (layout === "legacy-repo-skill") {
|
|
223
|
+
return LEGACY_REPO_SKILL_PROGRESS;
|
|
224
|
+
}
|
|
225
|
+
if (layout === "claude-skill") {
|
|
226
|
+
return CLAUDE_INSTALLED_PROGRESS;
|
|
227
|
+
}
|
|
201
228
|
return INSTALLED_PROGRESS;
|
|
202
229
|
}
|
|
203
230
|
|
|
@@ -209,6 +236,12 @@ export class Repo {
|
|
|
209
236
|
if (layout === "legacy-skill") {
|
|
210
237
|
return LEGACY_SKILL_VERSION;
|
|
211
238
|
}
|
|
239
|
+
if (layout === "legacy-repo-skill") {
|
|
240
|
+
return LEGACY_REPO_SKILL_VERSION;
|
|
241
|
+
}
|
|
242
|
+
if (layout === "claude-skill") {
|
|
243
|
+
return CLAUDE_FRAMEWORK_VERSION;
|
|
244
|
+
}
|
|
212
245
|
return FRAMEWORK_VERSION;
|
|
213
246
|
}
|
|
214
247
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { Repo } from "#skill/engine/repo.js";
|
|
2
2
|
import type { RuleResult } from "#skill/engine/rules/index.js";
|
|
3
|
+
import { claudeCodeExampleCandidates } from "#skill/engine/runtime/adapters.js";
|
|
3
4
|
import { FRAMEWORK_EXAMPLES_DIR } from "#skill/engine/runtime/asset-loader.js";
|
|
4
5
|
|
|
5
6
|
export function evaluate(repo: Repo): RuleResult {
|
|
6
7
|
const tasks: string[] = [];
|
|
8
|
+
const [claudeExamplePath] = claudeCodeExampleCandidates();
|
|
7
9
|
if (repo.pathExists(".claude/settings.json")) {
|
|
8
10
|
if (!repo.fileContains(".claude/settings.json", "inject-tree-context")) {
|
|
9
11
|
tasks.push(
|
|
10
|
-
`Add SessionStart hook to \`.claude/settings.json\` (see \`${
|
|
12
|
+
`Add SessionStart hook to \`.claude/settings.json\` (see \`${claudeExamplePath}/\`)`,
|
|
11
13
|
);
|
|
12
14
|
}
|
|
13
15
|
} else if (!repo.anyAgentConfig()) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Repo } from "#skill/engine/repo.js";
|
|
2
2
|
import type { RuleResult } from "#skill/engine/rules/index.js";
|
|
3
|
-
import {
|
|
3
|
+
import { installedSkillRootsDisplay } from "#skill/engine/runtime/asset-loader.js";
|
|
4
4
|
|
|
5
5
|
export function evaluate(repo: Repo): RuleResult {
|
|
6
6
|
const tasks: string[] = [];
|
|
7
7
|
if (!repo.hasFramework()) {
|
|
8
8
|
tasks.push(
|
|
9
|
-
|
|
9
|
+
`${installedSkillRootsDisplay()} not found — run \`context-tree init\` to install the framework skill bundled with the current \`first-tree\` package`,
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
12
|
return { group: "Framework", order: 1, tasks };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import {
|
|
3
|
+
CLAUDE_FRAMEWORK_EXAMPLES_DIR,
|
|
4
|
+
CLAUDE_FRAMEWORK_HELPERS_DIR,
|
|
3
5
|
FRAMEWORK_EXAMPLES_DIR,
|
|
4
|
-
|
|
6
|
+
LEGACY_REPO_SKILL_EXAMPLES_DIR,
|
|
5
7
|
LEGACY_SKILL_EXAMPLES_DIR,
|
|
6
8
|
LEGACY_EXAMPLES_DIR,
|
|
7
9
|
} from "#skill/engine/runtime/asset-loader.js";
|
|
@@ -11,12 +13,14 @@ export const CODEX_CONFIG_PATH = ".codex/config.json";
|
|
|
11
13
|
|
|
12
14
|
export function claudeCodeExampleCandidates(): string[] {
|
|
13
15
|
return [
|
|
16
|
+
join(CLAUDE_FRAMEWORK_EXAMPLES_DIR, "claude-code"),
|
|
14
17
|
join(FRAMEWORK_EXAMPLES_DIR, "claude-code"),
|
|
18
|
+
join(LEGACY_REPO_SKILL_EXAMPLES_DIR, "claude-code"),
|
|
15
19
|
join(LEGACY_SKILL_EXAMPLES_DIR, "claude-code"),
|
|
16
20
|
join(LEGACY_EXAMPLES_DIR, "claude-code"),
|
|
17
21
|
];
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
export function injectTreeContextHint(): string {
|
|
21
|
-
return join(
|
|
25
|
+
return join(CLAUDE_FRAMEWORK_HELPERS_DIR, "inject-tree-context.sh");
|
|
22
26
|
}
|
|
@@ -2,7 +2,11 @@ import { existsSync, statSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
4
|
export const SKILL_NAME = "first-tree";
|
|
5
|
-
export const
|
|
5
|
+
export const BUNDLED_SKILL_ROOT = join("skills", SKILL_NAME);
|
|
6
|
+
export const SKILL_ROOT = join(".agents", "skills", SKILL_NAME);
|
|
7
|
+
export const CLAUDE_SKILL_ROOT = join(".claude", "skills", SKILL_NAME);
|
|
8
|
+
export const INSTALLED_SKILL_ROOTS = [SKILL_ROOT, CLAUDE_SKILL_ROOT] as const;
|
|
9
|
+
|
|
6
10
|
export const SKILL_AGENTS_DIR = join(SKILL_ROOT, "agents");
|
|
7
11
|
export const SKILL_REFERENCES_DIR = join(SKILL_ROOT, "references");
|
|
8
12
|
export const FRAMEWORK_ASSET_ROOT = join(SKILL_ROOT, "assets", "framework");
|
|
@@ -18,6 +22,93 @@ export const AGENT_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
|
18
22
|
export const LEGACY_AGENT_INSTRUCTIONS_FILE = "AGENT.md";
|
|
19
23
|
export const AGENT_INSTRUCTIONS_TEMPLATE = "agents.md.template";
|
|
20
24
|
|
|
25
|
+
export const CLAUDE_SKILL_AGENTS_DIR = join(CLAUDE_SKILL_ROOT, "agents");
|
|
26
|
+
export const CLAUDE_SKILL_REFERENCES_DIR = join(CLAUDE_SKILL_ROOT, "references");
|
|
27
|
+
export const CLAUDE_FRAMEWORK_ASSET_ROOT = join(
|
|
28
|
+
CLAUDE_SKILL_ROOT,
|
|
29
|
+
"assets",
|
|
30
|
+
"framework",
|
|
31
|
+
);
|
|
32
|
+
export const CLAUDE_FRAMEWORK_MANIFEST = join(
|
|
33
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
34
|
+
"manifest.json",
|
|
35
|
+
);
|
|
36
|
+
export const CLAUDE_FRAMEWORK_VERSION = join(
|
|
37
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
38
|
+
"VERSION",
|
|
39
|
+
);
|
|
40
|
+
export const CLAUDE_FRAMEWORK_TEMPLATES_DIR = join(
|
|
41
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
42
|
+
"templates",
|
|
43
|
+
);
|
|
44
|
+
export const CLAUDE_FRAMEWORK_WORKFLOWS_DIR = join(
|
|
45
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
46
|
+
"workflows",
|
|
47
|
+
);
|
|
48
|
+
export const CLAUDE_FRAMEWORK_PROMPTS_DIR = join(
|
|
49
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
50
|
+
"prompts",
|
|
51
|
+
);
|
|
52
|
+
export const CLAUDE_FRAMEWORK_EXAMPLES_DIR = join(
|
|
53
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
54
|
+
"examples",
|
|
55
|
+
);
|
|
56
|
+
export const CLAUDE_FRAMEWORK_HELPERS_DIR = join(
|
|
57
|
+
CLAUDE_FRAMEWORK_ASSET_ROOT,
|
|
58
|
+
"helpers",
|
|
59
|
+
);
|
|
60
|
+
export const CLAUDE_INSTALLED_PROGRESS = join(
|
|
61
|
+
CLAUDE_SKILL_ROOT,
|
|
62
|
+
"progress.md",
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const LEGACY_REPO_SKILL_ROOT = join("skills", SKILL_NAME);
|
|
66
|
+
export const LEGACY_REPO_SKILL_AGENTS_DIR = join(
|
|
67
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
68
|
+
"agents",
|
|
69
|
+
);
|
|
70
|
+
export const LEGACY_REPO_SKILL_REFERENCES_DIR = join(
|
|
71
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
72
|
+
"references",
|
|
73
|
+
);
|
|
74
|
+
export const LEGACY_REPO_SKILL_ASSET_ROOT = join(
|
|
75
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
76
|
+
"assets",
|
|
77
|
+
"framework",
|
|
78
|
+
);
|
|
79
|
+
export const LEGACY_REPO_SKILL_MANIFEST = join(
|
|
80
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
81
|
+
"manifest.json",
|
|
82
|
+
);
|
|
83
|
+
export const LEGACY_REPO_SKILL_VERSION = join(
|
|
84
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
85
|
+
"VERSION",
|
|
86
|
+
);
|
|
87
|
+
export const LEGACY_REPO_SKILL_TEMPLATES_DIR = join(
|
|
88
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
89
|
+
"templates",
|
|
90
|
+
);
|
|
91
|
+
export const LEGACY_REPO_SKILL_WORKFLOWS_DIR = join(
|
|
92
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
93
|
+
"workflows",
|
|
94
|
+
);
|
|
95
|
+
export const LEGACY_REPO_SKILL_PROMPTS_DIR = join(
|
|
96
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
97
|
+
"prompts",
|
|
98
|
+
);
|
|
99
|
+
export const LEGACY_REPO_SKILL_EXAMPLES_DIR = join(
|
|
100
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
101
|
+
"examples",
|
|
102
|
+
);
|
|
103
|
+
export const LEGACY_REPO_SKILL_HELPERS_DIR = join(
|
|
104
|
+
LEGACY_REPO_SKILL_ASSET_ROOT,
|
|
105
|
+
"helpers",
|
|
106
|
+
);
|
|
107
|
+
export const LEGACY_REPO_SKILL_PROGRESS = join(
|
|
108
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
109
|
+
"progress.md",
|
|
110
|
+
);
|
|
111
|
+
|
|
21
112
|
export const LEGACY_SKILL_NAME = "first-tree-cli-framework";
|
|
22
113
|
export const LEGACY_SKILL_ROOT = join("skills", LEGACY_SKILL_NAME);
|
|
23
114
|
export const LEGACY_SKILL_ASSET_ROOT = join(
|
|
@@ -52,7 +143,12 @@ export const LEGACY_WORKFLOWS_DIR = join(LEGACY_FRAMEWORK_ROOT, "workflows");
|
|
|
52
143
|
export const LEGACY_PROMPTS_DIR = join(LEGACY_FRAMEWORK_ROOT, "prompts");
|
|
53
144
|
export const LEGACY_EXAMPLES_DIR = join(LEGACY_FRAMEWORK_ROOT, "examples");
|
|
54
145
|
|
|
55
|
-
export type FrameworkLayout =
|
|
146
|
+
export type FrameworkLayout =
|
|
147
|
+
| "skill"
|
|
148
|
+
| "claude-skill"
|
|
149
|
+
| "legacy-repo-skill"
|
|
150
|
+
| "legacy-skill"
|
|
151
|
+
| "legacy";
|
|
56
152
|
|
|
57
153
|
function pathExists(root: string, relPath: string): boolean {
|
|
58
154
|
const fullPath = join(root, relPath);
|
|
@@ -63,12 +159,34 @@ function pathExists(root: string, relPath: string): boolean {
|
|
|
63
159
|
}
|
|
64
160
|
}
|
|
65
161
|
|
|
162
|
+
export function installedSkillRoots(): string[] {
|
|
163
|
+
return [...INSTALLED_SKILL_ROOTS];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function installedSkillRootsDisplay(): string {
|
|
167
|
+
return installedSkillRoots()
|
|
168
|
+
.map((root) => `\`${root}/\``)
|
|
169
|
+
.join(" and ");
|
|
170
|
+
}
|
|
171
|
+
|
|
66
172
|
export function frameworkVersionCandidates(): string[] {
|
|
67
|
-
return [
|
|
173
|
+
return [
|
|
174
|
+
FRAMEWORK_VERSION,
|
|
175
|
+
CLAUDE_FRAMEWORK_VERSION,
|
|
176
|
+
LEGACY_REPO_SKILL_VERSION,
|
|
177
|
+
LEGACY_SKILL_VERSION,
|
|
178
|
+
LEGACY_VERSION,
|
|
179
|
+
];
|
|
68
180
|
}
|
|
69
181
|
|
|
70
182
|
export function progressFileCandidates(): string[] {
|
|
71
|
-
return [
|
|
183
|
+
return [
|
|
184
|
+
INSTALLED_PROGRESS,
|
|
185
|
+
CLAUDE_INSTALLED_PROGRESS,
|
|
186
|
+
LEGACY_REPO_SKILL_PROGRESS,
|
|
187
|
+
LEGACY_SKILL_PROGRESS,
|
|
188
|
+
LEGACY_PROGRESS,
|
|
189
|
+
];
|
|
72
190
|
}
|
|
73
191
|
|
|
74
192
|
export function agentInstructionsFileCandidates(): string[] {
|
|
@@ -78,6 +196,8 @@ export function agentInstructionsFileCandidates(): string[] {
|
|
|
78
196
|
export function frameworkTemplateDirCandidates(): string[] {
|
|
79
197
|
return [
|
|
80
198
|
FRAMEWORK_TEMPLATES_DIR,
|
|
199
|
+
CLAUDE_FRAMEWORK_TEMPLATES_DIR,
|
|
200
|
+
LEGACY_REPO_SKILL_TEMPLATES_DIR,
|
|
81
201
|
LEGACY_SKILL_TEMPLATES_DIR,
|
|
82
202
|
LEGACY_TEMPLATES_DIR,
|
|
83
203
|
];
|
|
@@ -86,6 +206,8 @@ export function frameworkTemplateDirCandidates(): string[] {
|
|
|
86
206
|
export function frameworkWorkflowDirCandidates(): string[] {
|
|
87
207
|
return [
|
|
88
208
|
FRAMEWORK_WORKFLOWS_DIR,
|
|
209
|
+
CLAUDE_FRAMEWORK_WORKFLOWS_DIR,
|
|
210
|
+
LEGACY_REPO_SKILL_WORKFLOWS_DIR,
|
|
89
211
|
LEGACY_SKILL_WORKFLOWS_DIR,
|
|
90
212
|
LEGACY_WORKFLOWS_DIR,
|
|
91
213
|
];
|
|
@@ -94,6 +216,8 @@ export function frameworkWorkflowDirCandidates(): string[] {
|
|
|
94
216
|
export function frameworkPromptDirCandidates(): string[] {
|
|
95
217
|
return [
|
|
96
218
|
FRAMEWORK_PROMPTS_DIR,
|
|
219
|
+
CLAUDE_FRAMEWORK_PROMPTS_DIR,
|
|
220
|
+
LEGACY_REPO_SKILL_PROMPTS_DIR,
|
|
97
221
|
LEGACY_SKILL_PROMPTS_DIR,
|
|
98
222
|
LEGACY_PROMPTS_DIR,
|
|
99
223
|
];
|
|
@@ -102,6 +226,8 @@ export function frameworkPromptDirCandidates(): string[] {
|
|
|
102
226
|
export function frameworkExampleDirCandidates(): string[] {
|
|
103
227
|
return [
|
|
104
228
|
FRAMEWORK_EXAMPLES_DIR,
|
|
229
|
+
CLAUDE_FRAMEWORK_EXAMPLES_DIR,
|
|
230
|
+
LEGACY_REPO_SKILL_EXAMPLES_DIR,
|
|
105
231
|
LEGACY_SKILL_EXAMPLES_DIR,
|
|
106
232
|
LEGACY_EXAMPLES_DIR,
|
|
107
233
|
];
|
|
@@ -123,6 +249,12 @@ export function detectFrameworkLayout(root: string): FrameworkLayout | null {
|
|
|
123
249
|
if (pathExists(root, FRAMEWORK_VERSION)) {
|
|
124
250
|
return "skill";
|
|
125
251
|
}
|
|
252
|
+
if (pathExists(root, CLAUDE_FRAMEWORK_VERSION)) {
|
|
253
|
+
return "claude-skill";
|
|
254
|
+
}
|
|
255
|
+
if (pathExists(root, LEGACY_REPO_SKILL_VERSION)) {
|
|
256
|
+
return "legacy-repo-skill";
|
|
257
|
+
}
|
|
126
258
|
if (pathExists(root, LEGACY_SKILL_VERSION)) {
|
|
127
259
|
return "legacy-skill";
|
|
128
260
|
}
|
|
@@ -2,9 +2,10 @@ import { copyFileSync, cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
BUNDLED_SKILL_ROOT,
|
|
6
|
+
INSTALLED_SKILL_ROOTS,
|
|
7
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
6
8
|
LEGACY_SKILL_ROOT,
|
|
7
|
-
SKILL_ROOT,
|
|
8
9
|
} from "#skill/engine/runtime/asset-loader.js";
|
|
9
10
|
|
|
10
11
|
export function resolveBundledPackageRoot(startUrl = import.meta.url): string {
|
|
@@ -12,7 +13,7 @@ export function resolveBundledPackageRoot(startUrl = import.meta.url): string {
|
|
|
12
13
|
while (true) {
|
|
13
14
|
if (
|
|
14
15
|
existsSync(join(dir, "package.json")) &&
|
|
15
|
-
existsSync(join(dir,
|
|
16
|
+
existsSync(join(dir, BUNDLED_SKILL_ROOT, "SKILL.md"))
|
|
16
17
|
) {
|
|
17
18
|
return dir;
|
|
18
19
|
}
|
|
@@ -38,7 +39,7 @@ export function resolveCanonicalSkillRoot(sourceRoot: string): string {
|
|
|
38
39
|
return directSkillRoot;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const nestedSkillRoot = join(sourceRoot,
|
|
42
|
+
const nestedSkillRoot = join(sourceRoot, BUNDLED_SKILL_ROOT);
|
|
42
43
|
if (
|
|
43
44
|
existsSync(join(nestedSkillRoot, "SKILL.md")) &&
|
|
44
45
|
existsSync(join(nestedSkillRoot, "assets", "framework", "VERSION"))
|
|
@@ -53,16 +54,21 @@ export function resolveCanonicalSkillRoot(sourceRoot: string): string {
|
|
|
53
54
|
|
|
54
55
|
export function copyCanonicalSkill(sourceRoot: string, targetRoot: string): void {
|
|
55
56
|
const src = resolveCanonicalSkillRoot(sourceRoot);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
for (const relPath of [
|
|
58
|
+
...INSTALLED_SKILL_ROOTS,
|
|
59
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
60
|
+
LEGACY_SKILL_ROOT,
|
|
61
|
+
]) {
|
|
62
|
+
const fullPath = join(targetRoot, relPath);
|
|
63
|
+
if (existsSync(fullPath)) {
|
|
64
|
+
rmSync(fullPath, { recursive: true, force: true });
|
|
65
|
+
}
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
for (const relPath of INSTALLED_SKILL_ROOTS) {
|
|
68
|
+
const dst = join(targetRoot, relPath);
|
|
69
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
70
|
+
cpSync(src, dst, { recursive: true });
|
|
63
71
|
}
|
|
64
|
-
mkdirSync(dirname(dst), { recursive: true });
|
|
65
|
-
cpSync(src, dst, { recursive: true });
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
export function renderTemplateFile(
|
|
@@ -4,14 +4,17 @@ import { Repo } from "#skill/engine/repo.js";
|
|
|
4
4
|
import {
|
|
5
5
|
AGENT_INSTRUCTIONS_FILE,
|
|
6
6
|
AGENT_INSTRUCTIONS_TEMPLATE,
|
|
7
|
+
CLAUDE_SKILL_ROOT,
|
|
7
8
|
FRAMEWORK_WORKFLOWS_DIR,
|
|
8
9
|
FRAMEWORK_TEMPLATES_DIR,
|
|
9
10
|
FRAMEWORK_VERSION,
|
|
10
11
|
INSTALLED_PROGRESS,
|
|
11
12
|
LEGACY_AGENT_INSTRUCTIONS_FILE,
|
|
12
13
|
LEGACY_FRAMEWORK_ROOT,
|
|
14
|
+
LEGACY_REPO_SKILL_ROOT,
|
|
13
15
|
LEGACY_SKILL_ROOT,
|
|
14
16
|
SKILL_ROOT,
|
|
17
|
+
installedSkillRootsDisplay,
|
|
15
18
|
type FrameworkLayout,
|
|
16
19
|
} from "#skill/engine/runtime/asset-loader.js";
|
|
17
20
|
import {
|
|
@@ -45,9 +48,10 @@ function formatUpgradeTaskList(
|
|
|
45
48
|
const lines: string[] = [
|
|
46
49
|
`# Context Tree Upgrade — v${localVersion} -> v${packagedVersion}\n`,
|
|
47
50
|
"## Installed Skill",
|
|
48
|
-
`- [ ] Review local customizations under
|
|
51
|
+
`- [ ] Review local customizations under ${installedSkillRootsDisplay()} and reapply them if needed`,
|
|
49
52
|
`- [ ] Re-copy any workflow updates you want from \`${FRAMEWORK_WORKFLOWS_DIR}/\` into \`.github/workflows/\``,
|
|
50
|
-
`- [ ] Re-check any local agent setup that references \`${
|
|
53
|
+
`- [ ] Re-check any local agent setup that references \`${CLAUDE_SKILL_ROOT}/assets/framework/examples/\` or \`${CLAUDE_SKILL_ROOT}/assets/framework/helpers/\``,
|
|
54
|
+
`- [ ] Re-check any repo scripts or workflow files that reference \`${SKILL_ROOT}/assets/framework/\``,
|
|
51
55
|
"",
|
|
52
56
|
];
|
|
53
57
|
|
|
@@ -58,6 +62,14 @@ function formatUpgradeTaskList(
|
|
|
58
62
|
);
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
if (layout === "legacy-repo-skill") {
|
|
66
|
+
lines.push(
|
|
67
|
+
"## Migration",
|
|
68
|
+
`- [ ] Remove any stale \`${LEGACY_REPO_SKILL_ROOT}/\` references from repo-specific docs, scripts, workflow files, or agent config`,
|
|
69
|
+
"",
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
if (layout === "legacy-skill") {
|
|
62
74
|
migrationTasks.push(
|
|
63
75
|
`- [ ] Remove any stale \`${LEGACY_SKILL_ROOT}/\` references from repo-specific docs, scripts, workflow files, or agent config`,
|
|
@@ -165,7 +177,12 @@ export function runUpgrade(repo?: Repo, options?: UpgradeOptions): number {
|
|
|
165
177
|
return 1;
|
|
166
178
|
}
|
|
167
179
|
|
|
168
|
-
|
|
180
|
+
const missingInstalledRoots = workingRepo.missingInstalledSkillRoots();
|
|
181
|
+
if (
|
|
182
|
+
layout === "skill" &&
|
|
183
|
+
missingInstalledRoots.length === 0 &&
|
|
184
|
+
packagedVersion === localVersion
|
|
185
|
+
) {
|
|
169
186
|
console.log(
|
|
170
187
|
`Already up to date with the bundled skill (${FRAMEWORK_VERSION} = ${localVersion}).`,
|
|
171
188
|
);
|
|
@@ -179,16 +196,26 @@ export function runUpgrade(repo?: Repo, options?: UpgradeOptions): number {
|
|
|
179
196
|
force: true,
|
|
180
197
|
});
|
|
181
198
|
console.log(
|
|
182
|
-
|
|
199
|
+
`Migrated legacy .context-tree/ layout to ${installedSkillRootsDisplay()}.`,
|
|
183
200
|
);
|
|
184
|
-
} else if (layout === "legacy-skill") {
|
|
201
|
+
} else if (layout === "legacy-repo-skill") {
|
|
185
202
|
console.log(
|
|
186
|
-
|
|
203
|
+
`Migrated legacy ${LEGACY_REPO_SKILL_ROOT}/ layout to ${installedSkillRootsDisplay()}.`,
|
|
187
204
|
);
|
|
188
|
-
} else {
|
|
205
|
+
} else if (layout === "legacy-skill") {
|
|
189
206
|
console.log(
|
|
190
|
-
|
|
207
|
+
`Migrated ${LEGACY_SKILL_ROOT}/ to ${installedSkillRootsDisplay()}.`,
|
|
191
208
|
);
|
|
209
|
+
} else {
|
|
210
|
+
if (missingInstalledRoots.length > 0) {
|
|
211
|
+
console.log(
|
|
212
|
+
`Repaired missing installed skill roots (${missingInstalledRoots.map((root) => `${root}/`).join(", ")}) and refreshed ${installedSkillRootsDisplay()} from the bundled first-tree package.`,
|
|
213
|
+
);
|
|
214
|
+
} else {
|
|
215
|
+
console.log(
|
|
216
|
+
`Refreshed ${installedSkillRootsDisplay()} from the bundled first-tree package.`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
192
219
|
}
|
|
193
220
|
|
|
194
221
|
const output = formatUpgradeTaskList(
|
|
@@ -56,8 +56,9 @@ Information an agent needs to **decide** on an approach — not to execute it.
|
|
|
56
56
|
- A source/workspace Git repository, or an already-created dedicated tree repo
|
|
57
57
|
- Node.js 18+
|
|
58
58
|
- The npm package is `first-tree`, the installed CLI command is
|
|
59
|
-
`context-tree
|
|
60
|
-
|
|
59
|
+
`context-tree`.
|
|
60
|
+
- `context-tree init` installs the framework skill into
|
|
61
|
+
`.agents/skills/first-tree/` and `.claude/skills/first-tree/`.
|
|
61
62
|
- Use `npx first-tree init` for one-off runs, or `npm install -g first-tree`
|
|
62
63
|
to add the `context-tree` command to your PATH
|
|
63
64
|
|
|
@@ -81,24 +82,30 @@ git init
|
|
|
81
82
|
context-tree init --here
|
|
82
83
|
```
|
|
83
84
|
|
|
84
|
-
Either way, the framework installs into
|
|
85
|
-
scaffolding (`NODE.md`, `AGENTS.md`,
|
|
86
|
-
|
|
85
|
+
Either way, the framework installs into `.agents/skills/first-tree/` and
|
|
86
|
+
`.claude/skills/first-tree/`, renders scaffolding (`NODE.md`, `AGENTS.md`,
|
|
87
|
+
`members/NODE.md`), and generates a task list in
|
|
88
|
+
`.agents/skills/first-tree/progress.md`.
|
|
87
89
|
|
|
88
90
|
Publishing tip: keep the tree repo in the same GitHub organization as the
|
|
89
91
|
source repo unless you have a reason not to.
|
|
90
92
|
|
|
91
93
|
### Step 2: Work Through the Task List
|
|
92
94
|
|
|
93
|
-
Read
|
|
95
|
+
Read `.agents/skills/first-tree/progress.md`. It contains a checklist tailored
|
|
96
|
+
to the current state of the repo. Complete each task:
|
|
94
97
|
|
|
95
98
|
- Fill in `NODE.md` with your organization name, owners, and domains
|
|
96
99
|
- Add project-specific instructions to `AGENTS.md` below the framework markers
|
|
97
100
|
- Create member nodes under `members/`
|
|
98
|
-
- Optionally configure agent integration (
|
|
99
|
-
|
|
101
|
+
- Optionally configure agent integration (for Claude Code, the installed hook
|
|
102
|
+
assets live under `.claude/skills/first-tree/`)
|
|
103
|
+
- Copy validation workflows from
|
|
104
|
+
`.agents/skills/first-tree/assets/framework/workflows/` to
|
|
105
|
+
`.github/workflows/`
|
|
100
106
|
|
|
101
|
-
As you complete each task, check it off in
|
|
107
|
+
As you complete each task, check it off in
|
|
108
|
+
`.agents/skills/first-tree/progress.md` by changing `- [ ]` to `- [x]`.
|
|
102
109
|
|
|
103
110
|
### Step 3: Verify
|
|
104
111
|
|
|
@@ -112,7 +119,9 @@ Or, from your source/workspace repo:
|
|
|
112
119
|
context-tree verify --tree-path ../my-org-context
|
|
113
120
|
```
|
|
114
121
|
|
|
115
|
-
This fails if any items in
|
|
122
|
+
This fails if any items in `.agents/skills/first-tree/progress.md` remain
|
|
123
|
+
unchecked, and runs deterministic checks (valid frontmatter, node structure,
|
|
124
|
+
member nodes exist).
|
|
116
125
|
|
|
117
126
|
### Step 4: Design Your Domains
|
|
118
127
|
|
|
@@ -164,13 +173,14 @@ When the framework updates:
|
|
|
164
173
|
context-tree upgrade
|
|
165
174
|
```
|
|
166
175
|
|
|
167
|
-
`context-tree upgrade` refreshes
|
|
168
|
-
skill bundled with the currently running
|
|
169
|
-
tree content, and generates follow-up
|
|
170
|
-
|
|
176
|
+
`context-tree upgrade` refreshes `.agents/skills/first-tree/` and
|
|
177
|
+
`.claude/skills/first-tree/` from the skill bundled with the currently running
|
|
178
|
+
`first-tree` npm package, preserves your tree content, and generates follow-up
|
|
179
|
+
tasks in `.agents/skills/first-tree/progress.md`.
|
|
171
180
|
|
|
172
|
-
If your repo still uses the older `skills/first-tree
|
|
173
|
-
`
|
|
181
|
+
If your repo still uses the older `skills/first-tree/`,
|
|
182
|
+
`skills/first-tree-cli-framework/`, or `.context-tree/` layouts,
|
|
183
|
+
`context-tree upgrade` will migrate it to the current installed layout first.
|
|
174
184
|
|
|
175
185
|
To pick up a newer framework release, first run a newer package version, for
|
|
176
186
|
example `npx first-tree@latest upgrade`, or update your global `first-tree`
|
|
@@ -180,6 +190,6 @@ install before running `context-tree upgrade`.
|
|
|
180
190
|
|
|
181
191
|
## Further Reading
|
|
182
192
|
|
|
183
|
-
-
|
|
184
|
-
-
|
|
193
|
+
- `.agents/skills/first-tree/references/principles.md` — Core principles with detailed examples
|
|
194
|
+
- `.agents/skills/first-tree/references/ownership-and-naming.md` — How nodes are named and owned
|
|
185
195
|
- `AGENTS.md` in your tree — The before/during/after workflow for every task
|