first-tree 0.0.1 → 0.0.3

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 (80) hide show
  1. package/README.md +73 -39
  2. package/dist/cli.js +27 -13
  3. package/dist/help-xEI-s9iN.js +25 -0
  4. package/dist/init-DtOjj0wc.js +253 -0
  5. package/dist/installer-rcZpGLnM.js +47 -0
  6. package/dist/onboarding-6Fr5Gkrk.js +2 -0
  7. package/dist/onboarding-B9zPGvvG.js +10 -0
  8. package/dist/repo-BTJG8BU1.js +187 -0
  9. package/dist/upgrade-COGgI7Rj.js +96 -0
  10. package/dist/{verify-DIz6qmBX.js → verify-CxN6JiV9.js} +135 -8
  11. package/package.json +33 -10
  12. package/skills/first-tree/SKILL.md +109 -0
  13. package/skills/first-tree/agents/openai.yaml +4 -0
  14. package/skills/first-tree/assets/framework/VERSION +1 -0
  15. package/skills/first-tree/assets/framework/examples/claude-code/README.md +14 -0
  16. package/skills/first-tree/assets/framework/examples/claude-code/settings.json +14 -0
  17. package/skills/first-tree/assets/framework/helpers/generate-codeowners.ts +224 -0
  18. package/skills/first-tree/assets/framework/helpers/inject-tree-context.sh +15 -0
  19. package/skills/first-tree/assets/framework/helpers/run-review.ts +179 -0
  20. package/skills/first-tree/assets/framework/manifest.json +11 -0
  21. package/skills/first-tree/assets/framework/prompts/pr-review.md +38 -0
  22. package/skills/first-tree/assets/framework/templates/agent.md.template +48 -0
  23. package/skills/first-tree/assets/framework/templates/member-node.md.template +18 -0
  24. package/skills/first-tree/assets/framework/templates/members-domain.md.template +45 -0
  25. package/skills/first-tree/assets/framework/templates/root-node.md.template +38 -0
  26. package/skills/first-tree/assets/framework/workflows/codeowners.yml +31 -0
  27. package/skills/first-tree/assets/framework/workflows/pr-review.yml +146 -0
  28. package/skills/first-tree/assets/framework/workflows/validate.yml +19 -0
  29. package/skills/first-tree/engine/commands/help.ts +32 -0
  30. package/skills/first-tree/engine/commands/init.ts +1 -0
  31. package/skills/first-tree/engine/commands/upgrade.ts +1 -0
  32. package/skills/first-tree/engine/commands/verify.ts +1 -0
  33. package/skills/first-tree/engine/init.ts +145 -0
  34. package/skills/first-tree/engine/onboarding.ts +10 -0
  35. package/skills/first-tree/engine/repo.ts +184 -0
  36. package/skills/first-tree/engine/rules/agent-instructions.ts +37 -0
  37. package/skills/first-tree/engine/rules/agent-integration.ts +19 -0
  38. package/skills/first-tree/engine/rules/ci-validation.ts +72 -0
  39. package/skills/first-tree/engine/rules/framework.ts +13 -0
  40. package/skills/first-tree/engine/rules/index.ts +41 -0
  41. package/skills/first-tree/engine/rules/members.ts +21 -0
  42. package/skills/first-tree/engine/rules/populate-tree.ts +36 -0
  43. package/skills/first-tree/engine/rules/root-node.ts +41 -0
  44. package/skills/first-tree/engine/runtime/adapters.ts +22 -0
  45. package/skills/first-tree/engine/runtime/asset-loader.ts +134 -0
  46. package/skills/first-tree/engine/runtime/installer.ts +82 -0
  47. package/skills/first-tree/engine/runtime/upgrader.ts +23 -0
  48. package/skills/first-tree/engine/upgrade.ts +176 -0
  49. package/skills/first-tree/engine/validators/members.ts +215 -0
  50. package/skills/first-tree/engine/validators/nodes.ts +514 -0
  51. package/skills/first-tree/engine/verify.ts +97 -0
  52. package/skills/first-tree/references/about.md +36 -0
  53. package/skills/first-tree/references/maintainer-architecture.md +59 -0
  54. package/skills/first-tree/references/maintainer-build-and-distribution.md +56 -0
  55. package/skills/first-tree/references/maintainer-testing.md +58 -0
  56. package/skills/first-tree/references/maintainer-thin-cli.md +38 -0
  57. package/skills/first-tree/references/onboarding.md +162 -0
  58. package/skills/first-tree/references/ownership-and-naming.md +94 -0
  59. package/skills/first-tree/references/principles.md +113 -0
  60. package/skills/first-tree/references/source-map.md +94 -0
  61. package/skills/first-tree/references/upgrade-contract.md +85 -0
  62. package/skills/first-tree/scripts/check-skill-sync.sh +133 -0
  63. package/skills/first-tree/scripts/quick_validate.py +95 -0
  64. package/skills/first-tree/scripts/run-local-cli.sh +35 -0
  65. package/skills/first-tree/tests/asset-loader.test.ts +75 -0
  66. package/skills/first-tree/tests/generate-codeowners.test.ts +94 -0
  67. package/skills/first-tree/tests/helpers.ts +149 -0
  68. package/skills/first-tree/tests/init.test.ts +153 -0
  69. package/skills/first-tree/tests/repo.test.ts +362 -0
  70. package/skills/first-tree/tests/rules.test.ts +394 -0
  71. package/skills/first-tree/tests/run-review.test.ts +155 -0
  72. package/skills/first-tree/tests/skill-artifacts.test.ts +307 -0
  73. package/skills/first-tree/tests/thin-cli.test.ts +59 -0
  74. package/skills/first-tree/tests/upgrade.test.ts +89 -0
  75. package/skills/first-tree/tests/validate-members.test.ts +224 -0
  76. package/skills/first-tree/tests/validate-nodes.test.ts +198 -0
  77. package/skills/first-tree/tests/verify.test.ts +142 -0
  78. package/dist/init-CE_944sb.js +0 -283
  79. package/dist/repo-BByc3VvM.js +0 -111
  80. package/dist/upgrade-Chr7z0CY.js +0 -82
package/README.md CHANGED
@@ -1,68 +1,102 @@
1
- # seed-tree
1
+ # first-tree
2
2
 
3
- Template source and CLI for [Context Tree](https://context-tree.ai) the living source of truth for your organization.
3
+ Thin distribution package for the `context-tree` CLI and the bundled canonical
4
+ `first-tree` skill.
4
5
 
5
- ## What is Context Tree?
6
+ ## Package Name vs Command
6
7
 
7
- A tree-structured knowledge base that agents and humans build and maintain together. Every node represents a domain, decision, or design. Every node has an owner. When things change, the tree updates. See [docs/about.md](docs/about.md) for the full story.
8
+ - The npm package is `first-tree`.
9
+ - The installed CLI command is `context-tree`.
10
+ - The installed skill directory inside a user tree is `skills/first-tree/`.
11
+ - When maintainer docs say "the `first-tree` skill", they mean that bundled
12
+ skill directory, not the npm package name.
13
+ - `npx first-tree init` is the quickest one-off entrypoint.
14
+ - `npm install -g first-tree` adds `context-tree` to your PATH for repeated
15
+ use.
16
+
17
+ ## What This Repo Ships
18
+
19
+ - `src/` keeps the thin CLI shell that parses commands and dispatches to the
20
+ bundled skill.
21
+ - `skills/first-tree/` is the canonical source for framework behavior, shipped
22
+ templates, maintainer references, and validation logic.
23
+ - `evals/` is maintainer-only developer tooling for the source repo. It is
24
+ intentionally not part of the published package.
8
25
 
9
26
  ## Quick Start
10
27
 
28
+ If you are starting a brand-new tree, create a git repo first:
29
+
11
30
  ```bash
12
- npx context-tree init
31
+ mkdir my-org-tree && cd my-org-tree
32
+ git init
33
+ npx first-tree init
13
34
  ```
14
35
 
15
- Run this inside a git repo. It clones the framework, renders scaffolding, and generates a task list for your agent to work through.
36
+ If you already have the command on your PATH:
37
+
38
+ ```bash
39
+ context-tree init
40
+ ```
41
+
42
+ The `first-tree` npm package carries the bundled canonical skill, and
43
+ `context-tree init` / `context-tree upgrade` install from that bundled copy
44
+ instead of cloning this source repo at runtime.
16
45
 
17
46
  ## Commands
18
47
 
19
48
  | Command | What it does |
20
- |---------|-------------|
49
+ | --- | --- |
21
50
  | `context-tree init` | Bootstrap a new context tree in the current git repo |
22
- | `context-tree verify` | Run checks against the tree, report pass/fail |
23
- | `context-tree upgrade` | Compare local framework version to upstream, generate upgrade tasks |
51
+ | `context-tree verify` | Run verification checks against the current tree |
52
+ | `context-tree upgrade` | Refresh the installed skill from the current `first-tree` npm package and write follow-up tasks |
53
+ | `context-tree help onboarding` | Print the onboarding guide |
24
54
 
25
- ## What `init` creates
55
+ ## Runtime And Maintainer Prerequisites
26
56
 
27
- ```
28
- your-tree/
29
- .context-tree/ # framework (upgradable from seed-tree)
30
- VERSION
31
- principles.md
32
- ownership-and-naming.md
33
- templates/
34
- workflows/
35
- examples/
36
- NODE.md # root node — your domains (from template)
37
- AGENT.md # agent instructions with framework markers (from template)
38
- members/
39
- NODE.md # members domain (from template)
40
- ```
57
+ - User trees: the onboarding guide targets Node.js 18+.
58
+ - This source repo: use Node.js 22 and pnpm 10 to match CI and the checked-in
59
+ package manager version.
41
60
 
42
- ## Upgrades
61
+ ## Developing This Repo
43
62
 
44
- After init, seed-tree is added as a git remote (`context-tree-upstream`). To upgrade the framework:
63
+ Run these commands from the repo root:
45
64
 
46
65
  ```bash
47
- context-tree upgrade # shows what changed and what to do
66
+ pnpm install --frozen-lockfile
67
+ pnpm validate:skill
68
+ pnpm typecheck
69
+ pnpm test
70
+ pnpm build
48
71
  ```
49
72
 
50
- ## Documentation
51
-
52
- - [docs/onboarding.md](docs/onboarding.md) — Onboarding guide for setting up a context tree (for agents)
53
- - [docs/about.md](docs/about.md) — What is Context Tree and who it's for
54
- - [.context-tree/principles.md](.context-tree/principles.md) — Core principles with examples
55
- - [.context-tree/ownership-and-naming.md](.context-tree/ownership-and-naming.md) — Node naming and ownership model
56
-
57
- ## Development
73
+ When package contents or install/upgrade behavior changes, also run:
58
74
 
59
75
  ```bash
60
- pnpm install
61
- pnpm test # run tests
62
- pnpm typecheck # type check
63
- pnpm build # build CLI
76
+ pnpm pack
64
77
  ```
65
78
 
79
+ ## Canonical Documentation
80
+
81
+ All framework documentation, maintainer guidance, and shipped runtime assets
82
+ live in `skills/first-tree/`.
83
+
84
+ - User-facing overview: `skills/first-tree/references/about.md`
85
+ - User onboarding: `skills/first-tree/references/onboarding.md`
86
+ - Maintainer entrypoint: `skills/first-tree/references/source-map.md`
87
+
88
+ If you are maintaining this repo, start with the source map instead of relying
89
+ on root-level prose.
90
+
91
+ ## Contributing And Security
92
+
93
+ - Use the GitHub issue forms for bug reports and feature requests so maintainers
94
+ get reproducible context up front.
95
+ - See `CONTRIBUTING.md` for local setup, validation expectations, and where
96
+ changes should live.
97
+ - See `CODE_OF_CONDUCT.md` for community expectations.
98
+ - See `SECURITY.md` for vulnerability reporting guidance.
99
+
66
100
  ## License
67
101
 
68
102
  Apache 2.0
package/dist/cli.js CHANGED
@@ -1,41 +1,55 @@
1
1
  #!/usr/bin/env node
2
+ import { pathToFileURL } from "node:url";
2
3
  //#region src/cli.ts
3
4
  const USAGE = `usage: context-tree <command>
4
5
 
6
+ New to context-tree? Run \`context-tree help onboarding\` first.
7
+
5
8
  Commands:
6
- init Bootstrap a new context tree (clones seed-tree, copies framework files)
9
+ init Bootstrap a new context tree (installs the framework skill)
7
10
  verify Run verification checks against the current tree
8
- upgrade Generate an upgrade task list from upstream changes
11
+ upgrade Refresh the installed skill from the current first-tree npm package and generate follow-up tasks
12
+ help Show help for a topic (e.g. \`help onboarding\`)
9
13
 
10
14
  Options:
11
- --help Show this help message
15
+ --help Show this help message
16
+ --version Show version number
12
17
  `;
13
- async function main() {
14
- const args = process.argv.slice(2);
18
+ async function runCli(args, output = console.log) {
19
+ const write = (text) => output(text);
15
20
  if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
16
- console.log(USAGE);
21
+ write(USAGE);
22
+ return 0;
23
+ }
24
+ if (args[0] === "--version" || args[0] === "-v") {
25
+ const { createRequire } = await import("node:module");
26
+ write(createRequire(import.meta.url)("../package.json").version);
17
27
  return 0;
18
28
  }
19
29
  const command = args[0];
20
30
  switch (command) {
21
31
  case "init": {
22
- const { runInit } = await import("./init-CE_944sb.js");
32
+ const { runInit } = await import("./init-DtOjj0wc.js");
23
33
  return runInit();
24
34
  }
25
35
  case "verify": {
26
- const { runVerify } = await import("./verify-DIz6qmBX.js");
36
+ const { runVerify } = await import("./verify-CxN6JiV9.js");
27
37
  return runVerify();
28
38
  }
29
39
  case "upgrade": {
30
- const { runUpgrade } = await import("./upgrade-Chr7z0CY.js");
40
+ const { runUpgrade } = await import("./upgrade-COGgI7Rj.js");
31
41
  return runUpgrade();
32
42
  }
43
+ case "help": return (await import("./help-xEI-s9iN.js")).runHelp(args.slice(1), write);
33
44
  default:
34
- console.log(`Unknown command: ${command}`);
35
- console.log(USAGE);
45
+ write(`Unknown command: ${command}`);
46
+ write(USAGE);
36
47
  return 1;
37
48
  }
38
49
  }
39
- main().then((code) => process.exit(code));
50
+ async function main() {
51
+ return runCli(process.argv.slice(2));
52
+ }
53
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL(process.argv[1]).href) main().then((code) => process.exit(code));
40
54
  //#endregion
41
- export {};
55
+ export { USAGE, runCli };
@@ -0,0 +1,25 @@
1
+ //#region skills/first-tree/engine/commands/help.ts
2
+ const HELP_USAGE = `usage: context-tree help <topic>
3
+
4
+ Topics:
5
+ onboarding How to set up a context tree from scratch
6
+ `;
7
+ async function runHelp(args, output = console.log) {
8
+ const topic = args[0];
9
+ if (!topic || topic === "--help" || topic === "-h") {
10
+ output(HELP_USAGE);
11
+ return 0;
12
+ }
13
+ switch (topic) {
14
+ case "onboarding": {
15
+ const { runOnboarding } = await import("./onboarding-6Fr5Gkrk.js");
16
+ return runOnboarding(output);
17
+ }
18
+ default:
19
+ output(`Unknown help topic: ${topic}`);
20
+ output(HELP_USAGE);
21
+ return 1;
22
+ }
23
+ }
24
+ //#endregion
25
+ export { runHelp };
@@ -0,0 +1,253 @@
1
+ import { a as FRAMEWORK_TEMPLATES_DIR, c as INSTALLED_PROGRESS, d as SKILL_ROOT, i as FRAMEWORK_EXAMPLES_DIR, n as Repo, o as FRAMEWORK_VERSION, r as FRAMEWORK_ASSET_ROOT, s as FRAMEWORK_WORKFLOWS_DIR, t as FRAMEWORK_END_MARKER } from "./repo-BTJG8BU1.js";
2
+ import { n as onboarding_default } from "./onboarding-B9zPGvvG.js";
3
+ import { n as renderTemplateFile, r as resolveBundledPackageRoot, t as copyCanonicalSkill } from "./installer-rcZpGLnM.js";
4
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+ //#region \0rolldown/runtime.js
7
+ var __defProp = Object.defineProperty;
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
+ return target;
16
+ };
17
+ //#endregion
18
+ //#region skills/first-tree/engine/rules/agent-instructions.ts
19
+ var agent_instructions_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$6 });
20
+ function evaluate$6(repo) {
21
+ const tasks = [];
22
+ if (!repo.pathExists("AGENT.md")) tasks.push(`AGENT.md is missing — create from \`${FRAMEWORK_TEMPLATES_DIR}/agent.md.template\``);
23
+ else if (!repo.hasAgentMdMarkers()) tasks.push("AGENT.md exists but is missing framework markers — add `<!-- BEGIN CONTEXT-TREE FRAMEWORK -->` and `<!-- END CONTEXT-TREE FRAMEWORK -->` sections");
24
+ else {
25
+ const afterMarker = (repo.readFile("AGENT.md") ?? "").split(FRAMEWORK_END_MARKER);
26
+ if (afterMarker.length > 1) {
27
+ if (afterMarker[1].trim().split("\n").filter((l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("<!--")).length === 0) tasks.push("Add your project-specific instructions below the framework markers in AGENT.md");
28
+ }
29
+ }
30
+ return {
31
+ group: "Agent Instructions",
32
+ order: 3,
33
+ tasks
34
+ };
35
+ }
36
+ //#endregion
37
+ //#region skills/first-tree/engine/rules/agent-integration.ts
38
+ var agent_integration_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$5 });
39
+ function evaluate$5(repo) {
40
+ const tasks = [];
41
+ if (repo.pathExists(".claude/settings.json")) {
42
+ if (!repo.fileContains(".claude/settings.json", "inject-tree-context")) tasks.push(`Add SessionStart hook to \`.claude/settings.json\` (see \`${FRAMEWORK_EXAMPLES_DIR}/claude-code/\`)`);
43
+ } else if (!repo.anyAgentConfig()) tasks.push(`No agent configuration detected. Configure your agent to load tree context at session start. See \`${FRAMEWORK_EXAMPLES_DIR}/\` for supported agents. You can skip this and set it up later.`);
44
+ return {
45
+ group: "Agent Integration",
46
+ order: 5,
47
+ tasks
48
+ };
49
+ }
50
+ //#endregion
51
+ //#region skills/first-tree/engine/rules/ci-validation.ts
52
+ var ci_validation_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$4 });
53
+ function evaluate$4(repo) {
54
+ const tasks = [];
55
+ let hasValidation = false;
56
+ let hasPrReview = false;
57
+ let hasCodeowners = false;
58
+ const workflowsDir = join(repo.root, ".github", "workflows");
59
+ try {
60
+ if (statSync(workflowsDir).isDirectory()) for (const name of readdirSync(workflowsDir)) {
61
+ if (!name.endsWith(".yml") && !name.endsWith(".yaml")) continue;
62
+ const fullPath = join(workflowsDir, name);
63
+ try {
64
+ if (!statSync(fullPath).isFile()) continue;
65
+ const content = readFileSync(fullPath, "utf-8");
66
+ if (content.includes("validate_nodes") || content.includes("validate_members")) hasValidation = true;
67
+ if (content.includes("run-review")) hasPrReview = true;
68
+ if (content.includes("generate-codeowners")) hasCodeowners = true;
69
+ } catch {
70
+ continue;
71
+ }
72
+ }
73
+ } catch {}
74
+ if (!hasValidation) tasks.push(`No validation workflow found — copy \`${FRAMEWORK_WORKFLOWS_DIR}/validate.yml\` to \`.github/workflows/validate.yml\``);
75
+ if (!hasPrReview) {
76
+ tasks.push(`Use ${INTERACTIVE_TOOL} to ask whether the user wants AI-powered PR reviews. Options:\n 1. **OpenRouter** — use an OpenRouter API key
77
+ 2. **Claude API** — use a Claude API key directly
78
+ 3. **Skip** — do not set up PR reviews
79
+ If (1): copy \`${FRAMEWORK_WORKFLOWS_DIR}/pr-review.yml\` to \`.github/workflows/pr-review.yml\` as-is; the repo secret name is \`OPENROUTER_API_KEY\`. If (2): copy the workflow and replace the \`env\` block with \`ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}\`, remove the \`ANTHROPIC_BASE_URL\`, \`ANTHROPIC_AUTH_TOKEN\`, and \`ANTHROPIC_DEFAULT_SONNET_MODEL\` lines; the repo secret name is \`ANTHROPIC_API_KEY\`. If (3): skip this and the next task.`);
80
+ tasks.push(`Use ${INTERACTIVE_TOOL} to ask how the user wants to configure the API secret. Options:\n 1. **Set it now** — provide the key and the agent will run \`gh secret set <SECRET_NAME> --body <KEY>\`
81
+ 2. **I'll do it myself** — the agent will show manual instructions
82
+ If (1): ask the user to provide the key, then run \`gh secret set\` with the secret name from the previous step. If (2): tell the user to go to their repo → Settings → Secrets and variables → Actions → New repository secret, and create the secret with the name from the previous step. Skip this task if the user chose Skip in the previous step.`);
83
+ }
84
+ if (!hasCodeowners) tasks.push(`No CODEOWNERS workflow found — copy \`${FRAMEWORK_WORKFLOWS_DIR}/codeowners.yml\` to \`.github/workflows/codeowners.yml\` to auto-generate CODEOWNERS from tree ownership on every PR.`);
85
+ return {
86
+ group: "CI / Validation",
87
+ order: 6,
88
+ tasks
89
+ };
90
+ }
91
+ //#endregion
92
+ //#region skills/first-tree/engine/rules/framework.ts
93
+ var framework_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$3 });
94
+ function evaluate$3(repo) {
95
+ const tasks = [];
96
+ if (!repo.hasFramework()) tasks.push(`\`${SKILL_ROOT}/\` not found — run \`context-tree init\` to install the framework skill bundled with the current \`first-tree\` package`);
97
+ return {
98
+ group: "Framework",
99
+ order: 1,
100
+ tasks
101
+ };
102
+ }
103
+ //#endregion
104
+ //#region skills/first-tree/engine/rules/members.ts
105
+ var members_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$2 });
106
+ function evaluate$2(repo) {
107
+ const tasks = [];
108
+ if (!repo.pathExists("members")) tasks.push("`members/` directory is missing — create it with a NODE.md");
109
+ else if (!repo.pathExists("members/NODE.md")) tasks.push("`members/NODE.md` is missing — create it from the template");
110
+ if (repo.hasMembers() && repo.memberCount() === 0) tasks.push("Add at least one member node under `members/`. Analyze the user's code repositories (git history, CODEOWNERS, README contributors) to suggest members, then confirm with the user");
111
+ else if (!repo.hasMembers()) tasks.push("Add at least one member node under `members/`. Analyze the user's code repositories (git history, CODEOWNERS, README contributors) to suggest members, then confirm with the user");
112
+ return {
113
+ group: "Members",
114
+ order: 4,
115
+ tasks
116
+ };
117
+ }
118
+ //#endregion
119
+ //#region skills/first-tree/engine/rules/populate-tree.ts
120
+ var populate_tree_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate$1 });
121
+ function evaluate$1(repo) {
122
+ const tasks = [];
123
+ tasks.push(`Ask the user whether they want to populate the full context tree now using the **${INTERACTIVE_TOOL}** tool. Present two options: (1) **Yes — populate the full tree**: the agent will analyze source repositories, create sub-domains, and populate NODE.md files for each domain and sub-domain; (2) **No — I'll do it later**: skip deep population and finish init with just the top-level structure. If the user selects No, check off all remaining items in this section and move on.`);
124
+ tasks.push("If the user selected Yes: analyze the codebase (and any additional repositories the user provides) to identify logical sub-domains within each top-level domain. For each sub-domain, create a directory with a NODE.md containing proper frontmatter (title, owners) and a description of the sub-domain's purpose, boundaries, and key decisions. Create deeper sub-domains when a domain is large enough to warrant further decomposition.");
125
+ tasks.push("Use **sub-tasks** (TaskCreate) to parallelize the population work — create one sub-task per top-level domain so each domain can be populated concurrently. Each sub-task should: read the relevant source code, identify sub-domains, create NODE.md files, and establish soft_links between related domains.");
126
+ tasks.push("After all domains are populated, update the root NODE.md to list every top-level domain with a one-line description. Ensure all NODE.md files pass `context-tree verify` — valid frontmatter, no placeholders, and soft_links that resolve correctly.");
127
+ return {
128
+ group: "Populate Tree",
129
+ order: 7,
130
+ tasks
131
+ };
132
+ }
133
+ //#endregion
134
+ //#region skills/first-tree/engine/rules/root-node.ts
135
+ var root_node_exports = /* @__PURE__ */ __exportAll({ evaluate: () => evaluate });
136
+ function evaluate(repo) {
137
+ const tasks = [];
138
+ if (!repo.pathExists("NODE.md")) tasks.push(`NODE.md is missing — create from \`${FRAMEWORK_TEMPLATES_DIR}/root-node.md.template\`. Ask the user for their code repositories or project directories, then analyze the source to determine the project description and domain structure`);
139
+ else {
140
+ const fm = repo.frontmatter("NODE.md");
141
+ if (fm === null) tasks.push("NODE.md exists but has no frontmatter — add frontmatter with title and owners fields");
142
+ else {
143
+ if (!fm.title || fm.title.startsWith("<")) tasks.push("NODE.md has a placeholder title — replace with your organization name");
144
+ if (!fm.owners || fm.owners.length === 0 || fm.owners.length === 1 && fm.owners[0].startsWith("<")) tasks.push("NODE.md has placeholder owners — set owners to your GitHub username(s)");
145
+ }
146
+ if (repo.hasPlaceholderNode()) tasks.push("NODE.md has placeholder content — ask the user for their code repositories or project directories, then analyze the source to fill in the project description and domain structure");
147
+ }
148
+ return {
149
+ group: "Root Node",
150
+ order: 2,
151
+ tasks
152
+ };
153
+ }
154
+ //#endregion
155
+ //#region skills/first-tree/engine/rules/index.ts
156
+ const ALL_RULES = [
157
+ framework_exports,
158
+ root_node_exports,
159
+ agent_instructions_exports,
160
+ members_exports,
161
+ agent_integration_exports,
162
+ ci_validation_exports,
163
+ populate_tree_exports
164
+ ];
165
+ function evaluateAll(repo) {
166
+ const results = [];
167
+ for (const rule of ALL_RULES) {
168
+ const result = rule.evaluate(repo);
169
+ if (result.tasks.length > 0) results.push(result);
170
+ }
171
+ return results.sort((a, b) => a.order - b.order);
172
+ }
173
+ //#endregion
174
+ //#region skills/first-tree/engine/init.ts
175
+ /**
176
+ * The interactive prompt tool the agent should use to present choices.
177
+ * Different agents may name this differently — change it here to update
178
+ * all generated task text at once.
179
+ */
180
+ const INTERACTIVE_TOOL = "AskUserQuestion";
181
+ const TEMPLATE_MAP = [
182
+ ["root-node.md.template", "NODE.md"],
183
+ ["agent.md.template", "AGENT.md"],
184
+ ["members-domain.md.template", "members/NODE.md"]
185
+ ];
186
+ function installSkill(source, target) {
187
+ copyCanonicalSkill(source, target);
188
+ console.log(" Installed skills/first-tree/ from the bundled first-tree package");
189
+ }
190
+ function renderTemplates(target) {
191
+ const frameworkDir = join(target, FRAMEWORK_ASSET_ROOT);
192
+ for (const [templateName, targetPath] of TEMPLATE_MAP) if (existsSync(join(target, targetPath))) console.log(` Skipped ${targetPath} (already exists)`);
193
+ else if (renderTemplateFile(frameworkDir, templateName, target, targetPath)) console.log(` Created ${targetPath}`);
194
+ }
195
+ function formatTaskList(groups) {
196
+ const lines = ["# Context Tree Init\n", `**Agent instructions:** Before starting work, analyze the full task list below and identify all information you need from the user. Ask the user for their code repositories or project directories so you can analyze the source yourself — derive project descriptions, domains, and members from the code instead of asking the user to describe them. Collect everything upfront using the **${INTERACTIVE_TOOL}** tool with structured options — present selectable choices (with label and description) so the user can pick instead of typing free-form answers. You may batch up to 4 questions per ${INTERACTIVE_TOOL} call.\n`];
197
+ for (const group of groups) {
198
+ lines.push(`## ${group.group}`);
199
+ for (const task of group.tasks) lines.push(`- [ ] ${task}`);
200
+ lines.push("");
201
+ }
202
+ lines.push("## Verification");
203
+ lines.push("After completing the tasks above, run `context-tree verify` to confirm:");
204
+ lines.push(`- [ ] \`${FRAMEWORK_VERSION}\` exists`);
205
+ lines.push("- [ ] Root NODE.md has valid frontmatter (title, owners)");
206
+ lines.push("- [ ] AGENT.md exists with framework markers");
207
+ lines.push("- [ ] `context-tree verify` passes with no errors");
208
+ lines.push("- [ ] At least one member node exists");
209
+ lines.push("");
210
+ lines.push("---");
211
+ lines.push("");
212
+ lines.push(`**Important:** As you complete each task, check it off in \`${INSTALLED_PROGRESS}\` by changing \`- [ ]\` to \`- [x]\`. Run \`context-tree verify\` when done — it will fail if any items remain unchecked.`);
213
+ lines.push("");
214
+ return lines.join("\n");
215
+ }
216
+ function writeProgress(repo, content) {
217
+ const progressPath = join(repo.root, repo.preferredProgressPath());
218
+ mkdirSync(dirname(progressPath), { recursive: true });
219
+ writeFileSync(progressPath, content);
220
+ }
221
+ function runInit(repo, options) {
222
+ const r = repo ?? new Repo();
223
+ if (!r.isGitRepo()) {
224
+ console.error("Error: not a git repository. Initialize one first:\n git init");
225
+ return 1;
226
+ }
227
+ if (!r.hasFramework()) try {
228
+ const sourceRoot = options?.sourceRoot ?? resolveBundledPackageRoot();
229
+ console.log("Installing the framework skill bundled with this first-tree package...");
230
+ console.log("Installing skill and scaffolding...");
231
+ installSkill(sourceRoot, r.root);
232
+ renderTemplates(r.root);
233
+ console.log();
234
+ } catch (err) {
235
+ const message = err instanceof Error ? err.message : "unknown error";
236
+ console.error(`Error: ${message}`);
237
+ return 1;
238
+ }
239
+ console.log(onboarding_default);
240
+ console.log("---\n");
241
+ const groups = evaluateAll(r);
242
+ if (groups.length === 0) {
243
+ console.log("All checks passed. Your context tree is set up.");
244
+ return 0;
245
+ }
246
+ const output = formatTaskList(groups);
247
+ console.log(output);
248
+ writeProgress(r, output);
249
+ console.log(`Progress file written to ${r.preferredProgressPath()}`);
250
+ return 0;
251
+ }
252
+ //#endregion
253
+ export { runInit };
@@ -0,0 +1,47 @@
1
+ import { d as SKILL_ROOT, u as LEGACY_SKILL_ROOT } from "./repo-BTJG8BU1.js";
2
+ import { fileURLToPath } from "node:url";
3
+ import { copyFileSync, cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ //#region skills/first-tree/engine/runtime/installer.ts
6
+ function resolveBundledPackageRoot(startUrl = import.meta.url) {
7
+ let dir = dirname(fileURLToPath(startUrl));
8
+ while (true) {
9
+ if (existsSync(join(dir, "package.json")) && existsSync(join(dir, SKILL_ROOT, "SKILL.md"))) return dir;
10
+ const parent = dirname(dir);
11
+ if (parent === dir) break;
12
+ dir = parent;
13
+ }
14
+ throw new Error("Could not locate the bundled `first-tree` package root. Reinstall the package and try again.");
15
+ }
16
+ function resolveCanonicalSkillRoot(sourceRoot) {
17
+ const directSkillRoot = sourceRoot;
18
+ if (existsSync(join(directSkillRoot, "SKILL.md")) && existsSync(join(directSkillRoot, "assets", "framework", "VERSION"))) return directSkillRoot;
19
+ const nestedSkillRoot = join(sourceRoot, SKILL_ROOT);
20
+ if (existsSync(join(nestedSkillRoot, "SKILL.md")) && existsSync(join(nestedSkillRoot, "assets", "framework", "VERSION"))) return nestedSkillRoot;
21
+ throw new Error(`Canonical skill not found under ${sourceRoot}. Reinstall the \`first-tree\` package and try again.`);
22
+ }
23
+ function copyCanonicalSkill(sourceRoot, targetRoot) {
24
+ const src = resolveCanonicalSkillRoot(sourceRoot);
25
+ const dst = join(targetRoot, SKILL_ROOT);
26
+ const legacyDst = join(targetRoot, LEGACY_SKILL_ROOT);
27
+ if (existsSync(dst)) rmSync(dst, {
28
+ recursive: true,
29
+ force: true
30
+ });
31
+ if (legacyDst !== dst && existsSync(legacyDst)) rmSync(legacyDst, {
32
+ recursive: true,
33
+ force: true
34
+ });
35
+ mkdirSync(dirname(dst), { recursive: true });
36
+ cpSync(src, dst, { recursive: true });
37
+ }
38
+ function renderTemplateFile(frameworkRoot, templateName, targetRoot, targetPath) {
39
+ const src = join(frameworkRoot, "templates", templateName);
40
+ const dst = join(targetRoot, targetPath);
41
+ if (existsSync(dst) || !existsSync(src)) return false;
42
+ mkdirSync(dirname(dst), { recursive: true });
43
+ copyFileSync(src, dst);
44
+ return true;
45
+ }
46
+ //#endregion
47
+ export { resolveCanonicalSkillRoot as i, renderTemplateFile as n, resolveBundledPackageRoot as r, copyCanonicalSkill as t };
@@ -0,0 +1,2 @@
1
+ import { t as runOnboarding } from "./onboarding-B9zPGvvG.js";
2
+ export { runOnboarding };
@@ -0,0 +1,10 @@
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 Git repository for your tree (separate from your code repos)\n- Node.js 18+\n- The npm package is `first-tree`, the installed CLI command is\n `context-tree`, and the installed skill directory in the tree is\n `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\n```bash\nmkdir my-org-tree && cd my-org-tree\ngit init\ncontext-tree init\n```\n\nThis installs the framework skill into `skills/first-tree/`, renders scaffolding (`NODE.md`, `AGENT.md`, `members/NODE.md`), and generates a task list in `skills/first-tree/progress.md`.\n\n### Step 2: Work Through the Task List\n\nRead `skills/first-tree/progress.md`. It contains a checklist tailored to 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 `AGENT.md` below the framework markers\n- Create member nodes under `members/`\n- Optionally configure agent integration (e.g., Claude Code session hooks)\n- Copy validation workflows from `skills/first-tree/assets/framework/workflows/` to `.github/workflows/`\n\nAs you complete each task, check it off in `skills/first-tree/progress.md` by changing `- [ ]` to `- [x]`.\n\n### Step 3: Verify\n\n```bash\ncontext-tree verify\n```\n\nThis fails if any items in `skills/first-tree/progress.md` remain unchecked, and runs deterministic checks (valid frontmatter, node structure, member nodes exist).\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` | Bootstrap a new tree. Installs the framework skill, renders templates, generates a task list. |\n| `context-tree verify` | Check the installed progress file for unchecked items + run deterministic validation. |\n| `context-tree upgrade` | Refresh the installed framework skill from the currently running `first-tree` npm package and generate follow-up tasks. |\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 `skills/first-tree/` from the\nskill bundled with the currently running `first-tree` npm package, preserves your\ntree content, and generates follow-up tasks in\n`skills/first-tree/progress.md`.\n\nIf your repo still uses the older `skills/first-tree-cli-framework/` path,\n`context-tree upgrade` will migrate it to `skills/first-tree/` 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- `skills/first-tree/references/principles.md` — Core principles with detailed examples\n- `skills/first-tree/references/ownership-and-naming.md` — How nodes are named and owned\n- `AGENT.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 };