first-tree 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +16 -5
  2. package/dist/bootstrap-YRjfHJp7.js +28 -0
  3. package/dist/cli.js +14 -5
  4. package/dist/{help-DV9-AaFp.js → help-CDfaFrzl.js} +1 -1
  5. package/dist/{init-BgGH2_yC.js → init-DjSVkUeR.js} +19 -8
  6. package/dist/onboarding-BiHx2jy5.js +10 -0
  7. package/dist/onboarding-Ce033qaW.js +2 -0
  8. package/dist/publish-D0crNDjz.js +504 -0
  9. package/dist/{repo-Cc5U4DWT.js → repo-BeVpMoHi.js} +2 -15
  10. package/dist/{source-integration-CuKjoheT.js → source-integration-DMxnl8Dw.js} +2 -6
  11. package/dist/{upgrade-BvA9oKmi.js → upgrade-B_NTlNrx.js} +2 -4
  12. package/dist/{verify-G8gNXzDX.js → verify-Chhm1vOF.js} +3 -3
  13. package/package.json +1 -1
  14. package/skills/first-tree/SKILL.md +25 -6
  15. package/skills/first-tree/agents/openai.yaml +1 -1
  16. package/skills/first-tree/assets/framework/VERSION +1 -1
  17. package/skills/first-tree/engine/commands/publish.ts +5 -0
  18. package/skills/first-tree/engine/init.ts +24 -6
  19. package/skills/first-tree/engine/publish.ts +807 -0
  20. package/skills/first-tree/engine/repo.ts +0 -8
  21. package/skills/first-tree/engine/runtime/adapters.ts +0 -2
  22. package/skills/first-tree/engine/runtime/asset-loader.ts +1 -36
  23. package/skills/first-tree/engine/runtime/bootstrap.ts +40 -0
  24. package/skills/first-tree/engine/runtime/installer.ts +0 -2
  25. package/skills/first-tree/engine/upgrade.ts +0 -11
  26. package/skills/first-tree/engine/validators/nodes.ts +2 -11
  27. package/skills/first-tree/references/maintainer-build-and-distribution.md +3 -0
  28. package/skills/first-tree/references/maintainer-thin-cli.md +1 -1
  29. package/skills/first-tree/references/onboarding.md +18 -12
  30. package/skills/first-tree/references/source-map.md +3 -1
  31. package/skills/first-tree/references/source-workspace-installation.md +25 -13
  32. package/skills/first-tree/references/upgrade-contract.md +15 -8
  33. package/skills/first-tree/scripts/check-skill-sync.sh +0 -1
  34. package/skills/first-tree/tests/asset-loader.test.ts +0 -24
  35. package/skills/first-tree/tests/helpers.ts +0 -14
  36. package/skills/first-tree/tests/init.test.ts +25 -0
  37. package/skills/first-tree/tests/publish.test.ts +248 -0
  38. package/skills/first-tree/tests/repo.test.ts +0 -25
  39. package/skills/first-tree/tests/skill-artifacts.test.ts +16 -1
  40. package/skills/first-tree/tests/thin-cli.test.ts +6 -0
  41. package/skills/first-tree/tests/upgrade.test.ts +0 -21
  42. package/dist/onboarding-D7fGGOMN.js +0 -10
  43. package/dist/onboarding-lASHHmgO.js +0 -2
@@ -0,0 +1,248 @@
1
+ import { join, relative } from "node:path";
2
+ import { writeFileSync } from "node:fs";
3
+ import { describe, expect, it } from "vitest";
4
+ import { Repo } from "#skill/engine/repo.js";
5
+ import {
6
+ PUBLISH_USAGE,
7
+ parsePublishArgs,
8
+ runPublish,
9
+ type CommandRunner,
10
+ } from "#skill/engine/publish.js";
11
+ import { writeBootstrapState } from "#skill/engine/runtime/bootstrap.js";
12
+ import {
13
+ AGENT_INSTRUCTIONS_FILE,
14
+ CLAUDE_INSTRUCTIONS_FILE,
15
+ SOURCE_INTEGRATION_MARKER,
16
+ } from "#skill/engine/runtime/asset-loader.js";
17
+ import {
18
+ makeAgentsMd,
19
+ makeFramework,
20
+ makeGitRepo,
21
+ makeMembers,
22
+ makeNode,
23
+ makeSourceRepo,
24
+ useTmpDir,
25
+ } from "./helpers.js";
26
+
27
+ interface RecordedCommand {
28
+ args: string[];
29
+ command: string;
30
+ cwd: string;
31
+ }
32
+
33
+ function makeTreeRepo(root: string): void {
34
+ makeGitRepo(root);
35
+ makeFramework(root, "0.2.0");
36
+ makeNode(root);
37
+ makeAgentsMd(root, { markers: true });
38
+ makeMembers(root);
39
+ }
40
+
41
+ function makeSourceIntegration(root: string): void {
42
+ writeFileSync(
43
+ join(root, AGENT_INSTRUCTIONS_FILE),
44
+ `${SOURCE_INTEGRATION_MARKER} installed\n`,
45
+ );
46
+ writeFileSync(
47
+ join(root, CLAUDE_INSTRUCTIONS_FILE),
48
+ `${SOURCE_INTEGRATION_MARKER} installed\n`,
49
+ );
50
+ }
51
+
52
+ function createRunner(
53
+ sourceRoot: string,
54
+ treeRoot: string,
55
+ ): { calls: RecordedCommand[]; runner: CommandRunner } {
56
+ const calls: RecordedCommand[] = [];
57
+ let treeOriginExists = false;
58
+ const runner: CommandRunner = (command, args, options) => {
59
+ calls.push({ command, args, cwd: options.cwd });
60
+
61
+ if (command === "git" && args[0] === "remote" && args[1] === "get-url") {
62
+ if (options.cwd === sourceRoot) {
63
+ return "git@github.com:acme/ADHD.git";
64
+ }
65
+ if (!treeOriginExists) {
66
+ throw new Error("missing origin");
67
+ }
68
+ return "git@github.com:acme/ADHD-context.git";
69
+ }
70
+
71
+ if (command === "gh" && args[0] === "repo" && args[1] === "view") {
72
+ if (args[2] === "acme/ADHD") {
73
+ return JSON.stringify({
74
+ defaultBranchRef: { name: "main" },
75
+ nameWithOwner: "acme/ADHD",
76
+ visibility: "PRIVATE",
77
+ });
78
+ }
79
+ throw new Error("not found");
80
+ }
81
+
82
+ if (
83
+ command === "git"
84
+ && args[0] === "rev-parse"
85
+ && args[1] === "--verify"
86
+ && args[2] === "HEAD"
87
+ && options.cwd === treeRoot
88
+ ) {
89
+ throw new Error("missing HEAD");
90
+ }
91
+
92
+ if (
93
+ command === "git"
94
+ && args[0] === "diff"
95
+ && args[1] === "--cached"
96
+ && args[2] === "--quiet"
97
+ ) {
98
+ throw new Error("changes present");
99
+ }
100
+
101
+ if (command === "git" && args[0] === "branch" && args[1] === "--show-current") {
102
+ return "main";
103
+ }
104
+
105
+ if (
106
+ command === "git"
107
+ && args[0] === "rev-parse"
108
+ && args[1] === "--verify"
109
+ && args[2] === "refs/remotes/origin/main"
110
+ ) {
111
+ return "origin/main";
112
+ }
113
+
114
+ if (
115
+ command === "git"
116
+ && args[0] === "rev-parse"
117
+ && args[1] === "--verify"
118
+ && args[2].startsWith("refs/heads/")
119
+ ) {
120
+ throw new Error("missing local branch");
121
+ }
122
+
123
+ if (command === "git" && args[0] === "ls-files") {
124
+ return "";
125
+ }
126
+
127
+ if (command === "gh" && args[0] === "pr" && args[1] === "create") {
128
+ return "https://github.com/acme/ADHD/pull/123";
129
+ }
130
+
131
+ if (command === "gh" && args[0] === "repo" && args[1] === "create") {
132
+ treeOriginExists = true;
133
+ return "";
134
+ }
135
+
136
+ if (command === "git" && args[0] === "remote" && args[1] === "add") {
137
+ treeOriginExists = true;
138
+ return "";
139
+ }
140
+
141
+ return "";
142
+ };
143
+
144
+ return { calls, runner };
145
+ }
146
+
147
+ describe("parsePublishArgs", () => {
148
+ it("documents the publish command", () => {
149
+ expect(PUBLISH_USAGE).toContain("context-tree publish");
150
+ expect(PUBLISH_USAGE).toContain("--open-pr");
151
+ expect(PUBLISH_USAGE).toContain("--source-repo PATH");
152
+ });
153
+
154
+ it("parses supported publish flags", () => {
155
+ expect(
156
+ parsePublishArgs([
157
+ "--open-pr",
158
+ "--tree-path",
159
+ "../ADHD-context",
160
+ "--source-repo",
161
+ "../ADHD",
162
+ "--submodule-path",
163
+ "ADHD-context",
164
+ "--source-remote",
165
+ "origin",
166
+ ]),
167
+ ).toEqual({
168
+ openPr: true,
169
+ sourceRemote: "origin",
170
+ sourceRepoPath: "../ADHD",
171
+ submodulePath: "ADHD-context",
172
+ treePath: "../ADHD-context",
173
+ });
174
+ });
175
+ });
176
+
177
+ describe("runPublish", () => {
178
+ it("publishes the tree repo, adds the submodule, and opens the source PR", () => {
179
+ const rootDir = useTmpDir();
180
+ const sourceRoot = join(rootDir.path, "ADHD");
181
+ const treeRoot = join(rootDir.path, "ADHD-context");
182
+
183
+ makeSourceRepo(sourceRoot);
184
+ makeFramework(sourceRoot, "0.2.0");
185
+ makeSourceIntegration(sourceRoot);
186
+ makeTreeRepo(treeRoot);
187
+ writeBootstrapState(treeRoot, {
188
+ sourceRepoName: "ADHD",
189
+ sourceRepoPath: relative(treeRoot, sourceRoot),
190
+ treeRepoName: "ADHD-context",
191
+ });
192
+
193
+ const { calls, runner } = createRunner(sourceRoot, treeRoot);
194
+ const result = runPublish(new Repo(treeRoot), {
195
+ commandRunner: runner,
196
+ openPr: true,
197
+ });
198
+
199
+ expect(result).toBe(0);
200
+ expect(
201
+ calls.some(
202
+ (call) =>
203
+ call.command === "gh"
204
+ && call.args[0] === "repo"
205
+ && call.args[1] === "create"
206
+ && call.args[2] === "acme/ADHD-context",
207
+ ),
208
+ ).toBe(true);
209
+ expect(
210
+ calls.some(
211
+ (call) =>
212
+ call.command === "git"
213
+ && call.args[0] === "submodule"
214
+ && call.args[1] === "add"
215
+ && call.args[2] === "git@github.com:acme/ADHD-context.git"
216
+ && call.args[3] === "ADHD-context",
217
+ ),
218
+ ).toBe(true);
219
+ expect(
220
+ calls.some(
221
+ (call) =>
222
+ call.command === "git"
223
+ && call.args[0] === "switch"
224
+ && call.args[1] === "-c"
225
+ && call.args[2] === "chore/connect-adhd-context",
226
+ ),
227
+ ).toBe(true);
228
+ expect(
229
+ calls.some(
230
+ (call) =>
231
+ call.command === "gh"
232
+ && call.args[0] === "pr"
233
+ && call.args[1] === "create"
234
+ && call.args.includes("--repo")
235
+ && call.args.includes("acme/ADHD"),
236
+ ),
237
+ ).toBe(true);
238
+ });
239
+
240
+ it("errors when the source repo cannot be inferred", () => {
241
+ const treeRoot = useTmpDir();
242
+ makeTreeRepo(treeRoot.path);
243
+
244
+ const result = runPublish(new Repo(treeRoot.path));
245
+
246
+ expect(result).toBe(1);
247
+ });
248
+ });
@@ -11,8 +11,6 @@ import {
11
11
  LEGACY_AGENT_INSTRUCTIONS_FILE,
12
12
  LEGACY_REPO_SKILL_PROGRESS,
13
13
  LEGACY_REPO_SKILL_VERSION,
14
- LEGACY_SKILL_PROGRESS,
15
- LEGACY_SKILL_VERSION,
16
14
  LEGACY_PROGRESS,
17
15
  LEGACY_VERSION,
18
16
  SOURCE_INTEGRATION_MARKER,
@@ -23,7 +21,6 @@ import {
23
21
  makeGitRepo,
24
22
  makeLegacyFramework,
25
23
  makeLegacyRepoFramework,
26
- makeLegacyNamedFramework,
27
24
  makeSourceRepo,
28
25
  makeSourceSkill,
29
26
  } from "./helpers.js";
@@ -181,13 +178,6 @@ describe("hasFramework", () => {
181
178
  expect(repo.hasFramework()).toBe(true);
182
179
  });
183
180
 
184
- it("returns true with the previous installed skill name", () => {
185
- const tmp = useTmpDir();
186
- makeLegacyNamedFramework(tmp.path);
187
- const repo = new Repo(tmp.path);
188
- expect(repo.hasFramework()).toBe(true);
189
- });
190
-
191
181
  it("returns true with the previous workspace skill path", () => {
192
182
  const tmp = useTmpDir();
193
183
  makeLegacyRepoFramework(tmp.path);
@@ -219,13 +209,6 @@ describe("readVersion", () => {
219
209
  expect(repo.readVersion()).toBe("0.3.0");
220
210
  });
221
211
 
222
- it("reads the previous installed skill version", () => {
223
- const tmp = useTmpDir();
224
- makeLegacyNamedFramework(tmp.path, "0.2.5");
225
- const repo = new Repo(tmp.path);
226
- expect(repo.readVersion()).toBe("0.2.5");
227
- });
228
-
229
212
  it("reads the previous workspace skill version", () => {
230
213
  const tmp = useTmpDir();
231
214
  makeLegacyRepoFramework(tmp.path, "0.2.4");
@@ -258,14 +241,6 @@ describe("path preferences", () => {
258
241
  expect(repo.frameworkVersionPath()).toBe(LEGACY_VERSION);
259
242
  });
260
243
 
261
- it("switches path preferences for repos using the previous skill name", () => {
262
- const tmp = useTmpDir();
263
- makeLegacyNamedFramework(tmp.path);
264
- const repo = new Repo(tmp.path);
265
- expect(repo.preferredProgressPath()).toBe(LEGACY_SKILL_PROGRESS);
266
- expect(repo.frameworkVersionPath()).toBe(LEGACY_SKILL_VERSION);
267
- });
268
-
269
244
  it("switches path preferences for repos using the previous workspace skill path", () => {
270
245
  const tmp = useTmpDir();
271
246
  makeLegacyRepoFramework(tmp.path);
@@ -139,7 +139,6 @@ describe("skill artifacts", () => {
139
139
  expect(isTrackedInGit(".claude")).toBe(false);
140
140
  expect(isTrackedInGit(".context-tree")).toBe(false);
141
141
  expect(existsSync(join(ROOT, "AGENT.md"))).toBe(false);
142
- expect(isTrackedInGit("skills/first-tree-cli-framework")).toBe(false);
143
142
  expect(isTrackedInGit("docs")).toBe(false);
144
143
  expect(isTrackedInGit("tests")).toBe(false);
145
144
  expect(existsSync(join(ROOT, "evals"))).toBe(true);
@@ -231,6 +230,9 @@ describe("skill artifacts", () => {
231
230
  expect(read("README.md")).toContain("dedicated tree repo");
232
231
  expect(read("README.md")).toContain("FIRST-TREE-SOURCE-INTEGRATION:");
233
232
  expect(read("README.md")).toContain("`first-tree` skill");
233
+ expect(read("README.md")).toContain("context-tree publish --open-pr");
234
+ expect(read("README.md")).toContain("canonical local working copy");
235
+ expect(read("README.md")).toContain("Only use `--here` after you have already switched into the dedicated tree repo.");
234
236
  expect(read("AGENTS.md")).toContain("references/source-map.md");
235
237
  expect(read("AGENTS.md")).toContain("source-workspace-installation.md");
236
238
  expect(read("AGENTS.md")).toContain("bundled skill path");
@@ -249,8 +251,10 @@ describe("skill artifacts", () => {
249
251
  expect(onboarding).toContain(".agents/skills/first-tree/");
250
252
  expect(onboarding).toContain(".claude/skills/first-tree/");
251
253
  expect(onboarding).toContain("FIRST-TREE-SOURCE-INTEGRATION:");
254
+ expect(onboarding).toContain("context-tree publish --open-pr");
252
255
  expect(onboarding).toContain("source/workspace repo");
253
256
  expect(onboarding).toContain("git submodule");
257
+ expect(onboarding).toContain("Only use `--here` after you have already switched into the dedicated tree repo.");
254
258
  expect(onboarding).not.toContain("This clones the framework into `.context-tree/`");
255
259
  expect(onboarding).not.toContain("from upstream");
256
260
 
@@ -265,6 +269,8 @@ describe("skill artifacts", () => {
265
269
  expect(skillMd).toContain(".claude/skills/first-tree/");
266
270
  expect(skillMd).toContain("source-workspace-installation.md");
267
271
  expect(skillMd).toContain("FIRST-TREE-SOURCE-INTEGRATION:");
272
+ expect(skillMd).toContain("context-tree publish --open-pr");
273
+ expect(skillMd).toContain("Never run `context-tree init --here` in a source/workspace repo");
268
274
  expect(skillMd).not.toContain("canonical eval harness");
269
275
 
270
276
  const sourceMap = read("skills/first-tree/references/source-map.md");
@@ -275,6 +281,8 @@ describe("skill artifacts", () => {
275
281
  expect(sourceMap).toContain("maintainer-thin-cli.md");
276
282
  expect(sourceMap).toContain("maintainer-build-and-distribution.md");
277
283
  expect(sourceMap).toContain("maintainer-testing.md");
284
+ expect(sourceMap).toContain("engine/publish.ts");
285
+ expect(sourceMap).toContain("tests/publish.test.ts");
278
286
  expect(sourceMap).toContain("engine/commands/");
279
287
  expect(sourceMap).toContain("engine/runtime/asset-loader.ts");
280
288
  expect(sourceMap).toContain("tests/init.test.ts");
@@ -289,7 +297,9 @@ describe("skill artifacts", () => {
289
297
  );
290
298
  expect(sourceWorkspaceInstall).toContain("FIRST-TREE-SOURCE-INTEGRATION:");
291
299
  expect(sourceWorkspaceInstall).toContain("git submodule");
300
+ expect(sourceWorkspaceInstall).toContain("context-tree publish --open-pr");
292
301
  expect(sourceWorkspaceInstall).toContain("Do not run `context-tree verify`");
302
+ expect(sourceWorkspaceInstall).toContain("Do not run `context-tree init --here` in the source/workspace repo");
293
303
 
294
304
  const maintainerArchitecture = read(
295
305
  "skills/first-tree/references/maintainer-architecture.md",
@@ -297,6 +307,11 @@ describe("skill artifacts", () => {
297
307
  expect(maintainerArchitecture).toContain("maintainer-only developer tooling");
298
308
  expect(maintainerArchitecture).toContain("`evals/`");
299
309
  expect(maintainerArchitecture).not.toContain("tests, and evals");
310
+
311
+ const buildAndDistribution = read(
312
+ "skills/first-tree/references/maintainer-build-and-distribution.md",
313
+ );
314
+ expect(buildAndDistribution).toContain("context-tree publish");
300
315
  });
301
316
 
302
317
  it("keeps public OSS entrypoints and package metadata in place", () => {
@@ -39,6 +39,12 @@ afterEach(() => {
39
39
  });
40
40
 
41
41
  describe("thin CLI shell", () => {
42
+ it("documents the dedicated-repo meaning of --here", () => {
43
+ expect(USAGE).toContain("git init && context-tree init --here");
44
+ expect(USAGE).toContain("context-tree publish --open-pr");
45
+ expect(USAGE).toContain("`--here` is for when the current repo is already the dedicated tree repo.");
46
+ });
47
+
42
48
  it("treats a symlinked npm bin path as direct execution", () => {
43
49
  const dir = makeTempDir();
44
50
  const target = join(dir, "cli.js");
@@ -18,7 +18,6 @@ import {
18
18
  makeSourceRepo,
19
19
  makeLegacyFramework,
20
20
  makeLegacyRepoFramework,
21
- makeLegacyNamedFramework,
22
21
  makeSourceSkill,
23
22
  useTmpDir,
24
23
  } from "./helpers.js";
@@ -63,26 +62,6 @@ describe("runUpgrade", () => {
63
62
  expect(existsSync(join(repoDir.path, INSTALLED_PROGRESS))).toBe(false);
64
63
  });
65
64
 
66
- it("migrates repos that still use the previous installed skill name", () => {
67
- const repoDir = useTmpDir();
68
- const sourceDir = useTmpDir();
69
- makeLegacyNamedFramework(repoDir.path, "0.2.0");
70
- makeSourceSkill(sourceDir.path, "0.2.0");
71
-
72
- const result = runUpgrade(new Repo(repoDir.path), {
73
- sourceRoot: sourceDir.path,
74
- });
75
-
76
- expect(result).toBe(0);
77
- expect(existsSync(join(repoDir.path, "skills", "first-tree-cli-framework"))).toBe(
78
- false,
79
- );
80
- expect(readFileSync(join(repoDir.path, FRAMEWORK_VERSION), "utf-8").trim()).toBe("0.2.0");
81
- expect(readFileSync(join(repoDir.path, INSTALLED_PROGRESS), "utf-8")).toContain(
82
- "skills/first-tree-cli-framework/",
83
- );
84
- });
85
-
86
65
  it("migrates repos that still use the previous workspace skill path", () => {
87
66
  const repoDir = useTmpDir();
88
67
  const sourceDir = useTmpDir();
@@ -1,10 +0,0 @@
1
- //#region skills/first-tree/references/onboarding.md
2
- var onboarding_default = "# Context Tree Onboarding\n\nYou are setting up a **Context Tree** — the living source of truth for an organization. This document tells you what it is and how to bootstrap one.\n\n---\n\n## What Is a Context Tree\n\nA Context Tree is a Git repository where every directory is a **domain** and every file is a **node**. Each node captures decisions, designs, and cross-domain relationships — the knowledge that would otherwise scatter across PRs, documents, and people's heads.\n\nKey properties:\n\n- **Nodes are markdown files.** Each directory has a `NODE.md` that describes the domain. Leaf `.md` files capture specific decisions or designs.\n- **Every node has an owner.** Declared in YAML frontmatter. Owners approve changes to their nodes.\n- **Organized by concern, not by repo or team.** An agent working on \"add SSO\" finds all auth context in one place — not split across 4 repos.\n- **The tree is never a snapshot — it's the current state.** When decisions change, the tree updates. Stale nodes are bugs.\n\n### Frontmatter Format\n\nEvery node has frontmatter:\n\n```yaml\n---\ntitle: \"Auth Architecture\"\nowners: [alice, bob]\nsoft_links: [/infrastructure/deployments]\n---\n```\n\n- `owners` — who can approve changes. `owners: []` inherits from parent. `owners: [*]` means anyone.\n- `soft_links` — cross-references to related nodes in other domains.\n\n### What Belongs in the Tree\n\nInformation an agent needs to **decide** on an approach — not to execute it.\n\n**Yes:** \"Auth spans 4 repos: backend issues JWTs, frontend uses Better Auth, extension uses OAuth popup, desktop uses localhost callback.\"\n\n**No:** The function signature of `auth_service.verify()` — that's in the code.\n\n---\n\n## Four Principles\n\n1. **Source of truth for decisions, not execution.** The tree captures the *what* and *why*. Execution details stay in source systems.\n2. **Agents are first-class participants.** The tree is designed for agents to navigate and update.\n3. **Transparency by default.** Reading is open to all. Writing requires owner approval.\n4. **Git-native.** Nodes are files, domains are directories. History, ownership, and review follow Git conventions.\n\n---\n\n## How to Set Up a Context Tree\n\n### Prerequisites\n\n- A source/workspace Git repository, or an already-created dedicated tree repo\n- Node.js 18+\n- The npm package is `first-tree`, the installed CLI command is\n `context-tree`.\n- `context-tree init` installs the framework skill into\n `.agents/skills/first-tree/` and `.claude/skills/first-tree/`.\n- Use `npx first-tree init` for one-off runs, or `npm install -g first-tree`\n to add the `context-tree` command to your PATH\n\n### Step 1: Initialize\n\nRecommended workflow: run `context-tree init` from your source or workspace repo.\nThe CLI will install the bundled skill in the current repo, update root\n`AGENTS.md` and `CLAUDE.md` with a `FIRST-TREE-SOURCE-INTEGRATION:` line, and\ncreate a sibling dedicated tree repo named `<repo>-context` by default. Tree\nfiles are scaffolded only in the dedicated tree repo.\n\n```bash\ncd my-org\ncontext-tree init\ncd ../my-org-context\n```\n\nIf you already created a dedicated tree repo manually, initialize it in place:\n\n```bash\nmkdir my-org-context && cd my-org-context\ngit init\ncontext-tree init --here\n```\n\nEither way, the framework installs into `.agents/skills/first-tree/` and\n`.claude/skills/first-tree/`, renders scaffolding (`NODE.md`, `AGENTS.md`,\n`members/NODE.md`), and generates a task list in\n`.agents/skills/first-tree/progress.md`.\n\nPublishing tip: keep the tree repo in the same GitHub organization as the\nsource repo unless you have a reason not to.\n\nHard boundary: do **not** create `NODE.md`, `members/`, or tree-scoped\n`AGENTS.md` in the source/workspace repo. Those files belong only in the\ndedicated `*-context` repo.\n\nDefault agent workflow after initialization:\n\n1. Create and push the dedicated `*-context` repo in the same GitHub\n organization as the source repo.\n2. Add the dedicated tree repo back to the source/workspace repo as a `git submodule`.\n3. Open a PR against the source/workspace repo's default branch for the local\n skill integration plus the new submodule pointer. Do not merge it\n automatically.\n\n### Step 2: Work Through the Task List\n\nRead `.agents/skills/first-tree/progress.md`. It contains a checklist tailored\nto the current state of the repo. Complete each task:\n\n- Fill in `NODE.md` with your organization name, owners, and domains\n- Add project-specific instructions to `AGENTS.md` below the framework markers\n- Create member nodes under `members/`\n- Optionally configure agent integration (for Claude Code, the installed hook\n assets live under `.claude/skills/first-tree/`)\n- Copy validation workflows from\n `.agents/skills/first-tree/assets/framework/workflows/` to\n `.github/workflows/`\n\nAs you complete each task, check it off in\n`.agents/skills/first-tree/progress.md` by changing `- [ ]` to `- [x]`.\n\n### Step 3: Verify\n\n```bash\ncontext-tree verify\n```\n\nOr, from your source/workspace repo:\n\n```bash\ncontext-tree verify --tree-path ../my-org-context\n```\n\nThis fails if any items in `.agents/skills/first-tree/progress.md` remain\nunchecked, and runs deterministic checks (valid frontmatter, node structure,\nmember nodes exist).\n\nDo not run `context-tree verify` in the source/workspace repo itself. That repo\nonly carries the installed skill plus the\n`FIRST-TREE-SOURCE-INTEGRATION:` line.\n\n### Step 4: Design Your Domains\n\nCreate top-level directories for your organization's primary concerns. Each needs a `NODE.md`:\n\n```\nmy-org-tree/\n NODE.md # root — lists all domains\n engineering/\n NODE.md # decisions about architecture, infra, tooling\n product/\n NODE.md # strategy, roadmap, user research\n marketing/\n NODE.md # positioning, campaigns\n members/\n NODE.md # team members and agents\n alice/\n NODE.md # individual member node\n```\n\n### Step 5: Populate from Existing Work\n\nFor each domain, extract knowledge from existing repos, docs, and systems:\n\n- Decisions and their rationale\n- Cross-domain relationships and dependencies\n- Constraints that aren't obvious from the code\n\nThe tree doesn't duplicate source code — it captures what connects things and why they were built that way.\n\n---\n\n## CLI Reference\n\n| Command | Description |\n|---------|-------------|\n| `context-tree init` | Install local source/workspace integration and create or refresh a dedicated tree repo. By default, running in a source/workspace repo creates a sibling `<repo>-context`; use `--here` to initialize the current repo in place. |\n| `context-tree verify` | Check the installed progress file for unchecked items + run deterministic validation. Use `--tree-path` when invoking from another working directory. |\n| `context-tree upgrade` | Refresh the installed framework skill from the currently running `first-tree` npm package and generate follow-up tasks. Use `--tree-path` when invoking from another working directory. |\n| `context-tree help onboarding` | Print this onboarding guide. |\n\n---\n\n## Upgrading the Framework\n\nWhen the framework updates:\n\n```bash\ncontext-tree upgrade\n```\n\n`context-tree upgrade` refreshes `.agents/skills/first-tree/` and\n`.claude/skills/first-tree/` from the skill bundled with the currently running\n`first-tree` npm package, preserves your tree content, and generates follow-up\ntasks in `.agents/skills/first-tree/progress.md`.\n\nIf you run `context-tree upgrade` in the source/workspace repo, it refreshes\nonly the local installed skill plus the `FIRST-TREE-SOURCE-INTEGRATION:` lines.\nRun `context-tree upgrade --tree-path ../my-org-context` to upgrade the\ndedicated tree repo itself.\n\nIf your repo still uses the older `skills/first-tree/`,\n`skills/first-tree-cli-framework/`, or `.context-tree/` layouts,\n`context-tree upgrade` will migrate it to the current installed layout first.\n\nTo pick up a newer framework release, first run a newer package version, for\nexample `npx first-tree@latest upgrade`, or update your global `first-tree`\ninstall before running `context-tree upgrade`.\n\n---\n\n## Further Reading\n\n- `.agents/skills/first-tree/references/principles.md` — Core principles with detailed examples\n- `.agents/skills/first-tree/references/source-workspace-installation.md` — Source/workspace install contract\n- `.agents/skills/first-tree/references/ownership-and-naming.md` — How nodes are named and owned\n- `AGENTS.md` in your tree — The before/during/after workflow for every task\n";
3
- //#endregion
4
- //#region skills/first-tree/engine/onboarding.ts
5
- function runOnboarding(output = console.log) {
6
- output(onboarding_default);
7
- return 0;
8
- }
9
- //#endregion
10
- export { onboarding_default as n, runOnboarding as t };
@@ -1,2 +0,0 @@
1
- import { t as runOnboarding } from "./onboarding-D7fGGOMN.js";
2
- export { runOnboarding };