@first-tree-ai/context-tree 0.1.5 → 0.1.7-alpha.202609010710
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +7 -3
- package/.codex-plugin/plugin.json +16 -9
- package/README.md +150 -117
- package/dist/cli/index.mjs +955 -573
- package/dist/index.d.mts +64 -15
- package/dist/index.mjs +833 -471
- package/dist/{schemas-C4bs-FkC.d.mts → schemas-C_7izpsa.d.mts} +130 -134
- package/dist/{schemas-BWM6Q6iz.mjs → schemas-DKHE1sWt.mjs} +62 -51
- package/dist/schemas.d.mts +2 -2
- package/dist/schemas.mjs +2 -2
- package/docs/specification.md +158 -144
- package/hooks/session-start.mjs +5 -14
- package/package.json +1 -1
- package/policy/context-tree-policy.md +10 -12
- package/skills/context-tree-connect/SKILL.md +34 -0
- package/skills/context-tree-connect/agents/openai.yaml +4 -0
- package/skills/context-tree-create/SKILL.md +32 -0
- package/skills/context-tree-create/agents/openai.yaml +4 -0
- package/skills/context-tree-publish/SKILL.md +26 -0
- package/skills/context-tree-publish/agents/openai.yaml +4 -0
- package/skills/context-tree-publish/scripts/context-tree.mjs +41 -0
- package/skills/context-tree-read/SKILL.md +20 -43
- package/skills/context-tree-read/agents/openai.yaml +2 -2
- package/skills/context-tree-setup/SKILL.md +33 -0
- package/skills/context-tree-setup/agents/openai.yaml +4 -0
- package/skills/context-tree-setup/scripts/context-tree.mjs +41 -0
- package/skills/context-tree-write/SKILL.md +29 -125
- package/skills/context-tree-write/agents/openai.yaml +2 -2
- package/skills/context-tree-init/SKILL.md +0 -51
- package/skills/context-tree-init/agents/openai.yaml +0 -4
- package/skills/context-tree-link/SKILL.md +0 -45
- package/skills/context-tree-link/agents/openai.yaml +0 -4
- /package/skills/{context-tree-init → context-tree-connect}/scripts/context-tree.mjs +0 -0
- /package/skills/{context-tree-link → context-tree-create}/scripts/context-tree.mjs +0 -0
package/docs/specification.md
CHANGED
|
@@ -1,146 +1,160 @@
|
|
|
1
|
-
# Context Tree
|
|
2
|
-
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
# Context Tree lifecycle specification
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
The package exposes setup as an orchestration skill over five concrete user
|
|
6
|
+
intentions: create, connect, read, write, and publish. Supporting commands
|
|
7
|
+
(`resolve`, `sync`, `list`, `prepare-write`, `finish-write`, `verify`, and
|
|
8
|
+
`policy`) are plugin and integration plumbing. Every JSON contract is strict
|
|
9
|
+
and uses `schemaVersion: 1`.
|
|
10
|
+
|
|
11
|
+
## Shared invariants
|
|
12
|
+
|
|
13
|
+
- Every core Git and GitHub subprocess uses one injectable runner. Errors redact
|
|
14
|
+
credential-bearing URLs, authorization values, and common GitHub token forms.
|
|
15
|
+
- Repository arguments are validated `OWNER/REPO` identities. Credential-bearing
|
|
16
|
+
repository URLs are rejected and never logged.
|
|
17
|
+
- A Git project canonicalizes to the exact current checkout root. Separate
|
|
18
|
+
clones and worktrees remain separate projects.
|
|
19
|
+
- A non-Git project connection matches only its exact canonical directory.
|
|
20
|
+
- Tree validation rejects symlink components, requires an exact clean Git root,
|
|
21
|
+
parses the root node, and requires full tree verification to succeed. An
|
|
22
|
+
unclean checkout is `DIRTY_TREE` and failed verification is `INVALID_TREE`;
|
|
23
|
+
neither is reported as a stale connection.
|
|
24
|
+
- Stored `local` or `github` state remains that kind after connection; every
|
|
25
|
+
selected managed checkout is classified from a safe origin before storage.
|
|
26
|
+
- Duplicate records for one project produce `CORRUPT_CONNECTION`.
|
|
27
|
+
- Connections are persisted by an atomic replacement with mode `0600`. No
|
|
28
|
+
locking or schema migration is provided.
|
|
29
|
+
|
|
30
|
+
## Result contracts
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
type Create = {
|
|
34
|
+
created: boolean; title: string; treePath: string; branch: string;
|
|
35
|
+
commitSha: string; schemaVersion: 1;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type Tree =
|
|
39
|
+
| { kind: "local"; path: string }
|
|
40
|
+
| { kind: "github"; path: string; repository: string };
|
|
41
|
+
|
|
42
|
+
type Connection = { tree: Tree; schemaVersion: 1 };
|
|
43
|
+
type ManagedTreeListing = {
|
|
44
|
+
schemaVersion: 1;
|
|
45
|
+
trees: Array<{ name: string; tree: Tree }>;
|
|
46
|
+
};
|
|
47
|
+
type Sync = { tree: Tree; branch: string; sha: string; schemaVersion: 1 };
|
|
48
|
+
type Prepare = { worktreePath: string; schemaVersion: 1 };
|
|
49
|
+
type Finish = { branch: string; sha: string; schemaVersion: 1 };
|
|
50
|
+
type Publish = {
|
|
51
|
+
repository: string; url: string; branch: string; sha: string;
|
|
52
|
+
schemaVersion: 1;
|
|
53
|
+
};
|
|
20
54
|
```
|
|
21
55
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`
|
|
74
|
-
|
|
75
|
-
and
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
or cached. The exact clean, non-symlink Git root and its credential-free GitHub
|
|
128
|
-
`origin` remain the authorization boundary. Resolution selects a candidate and
|
|
129
|
-
does not replace full semantic verification. Reads refresh fast-forward-only,
|
|
130
|
-
validate, and report the commit SHA; authorized stale reads stay read-only.
|
|
131
|
-
|
|
132
|
-
The package root exports `linkProject`, `resolveLink`,
|
|
133
|
-
`readContextTreePolicy`, `readTree`, `scaffoldTree`, and `verifyTree`.
|
|
134
|
-
Project identification, URL normalization, and the links-file storage
|
|
135
|
-
schema are internal. Public strict CLI result schemas remain available from
|
|
136
|
-
the schemas entrypoint.
|
|
137
|
-
|
|
138
|
-
Writes fetch the discovered default branch through that checkout and edit an
|
|
139
|
-
isolated worktree. One source comes from task context, not an invocation
|
|
140
|
-
argument, and scopes one write and commit. The base and result must validate;
|
|
141
|
-
publication first uses a non-force direct push to the discovered default branch.
|
|
142
|
-
Concurrent updates are rebased, resolved from authorized evidence, and verified
|
|
143
|
-
again with bounded retries. Explicit direct-push denial or exhausted retries
|
|
144
|
-
uses a latest-base, conflict-free task-branch PR fallback that remains open.
|
|
145
|
-
Invalid bases permit only explicitly requested validator-scoped repair, and the
|
|
146
|
-
workflow never merges.
|
|
56
|
+
Errors use `{ ok: false, error: { code, message }, schemaVersion: 1 }`.
|
|
57
|
+
Lifecycle-specific codes are `NO_CONNECTION`, `CORRUPT_CONNECTION`,
|
|
58
|
+
`STALE_CONNECTION`, `DIRTY_TREE`, `INVALID_TREE`, `WRITE_OUTDATED`,
|
|
59
|
+
`GITHUB_AUTH`, `REPOSITORY_EXISTS`, and `PUBLISH_INCOMPLETE`. Other failures
|
|
60
|
+
use `CONTEXT_TREE_FAILED`.
|
|
61
|
+
|
|
62
|
+
## Creation and connection
|
|
63
|
+
|
|
64
|
+
`create` derives `<normalized-project-directory>-context-tree` from the
|
|
65
|
+
canonical project root. It scaffolds and commits the tree in the flat managed
|
|
66
|
+
namespace before atomically connecting it. Repetition is idempotent only when
|
|
67
|
+
the project is still connected to that tree. An occupied name otherwise fails
|
|
68
|
+
with guidance to use `connect <name>`, and a project already connected to a
|
|
69
|
+
different tree fails rather than being silently repointed. Files created by a
|
|
70
|
+
failed create are removed; a destination that existed before the invocation is
|
|
71
|
+
never removed.
|
|
72
|
+
|
|
73
|
+
`connect <name>` performs an exact managed-directory lookup. `connect
|
|
74
|
+
OWNER/REPO` reuses a matching checkout or clones it under the lowercased
|
|
75
|
+
repository name. Every selection is validated and safely classified as local
|
|
76
|
+
or GitHub state. Local-tree, repository, and unsafe-origin name collisions fail
|
|
77
|
+
before the project connection changes. Explicit connection switches are
|
|
78
|
+
automatic. Only a directory created by a failed clone is removed.
|
|
79
|
+
|
|
80
|
+
`connect --tree-path <path>` attaches an exact, clean, fully valid Git root
|
|
81
|
+
with no symlink components in place and never copies, moves, or deletes it.
|
|
82
|
+
Trees without an origin classify as local state; credential-free GitHub
|
|
83
|
+
origins classify as GitHub state; all other origins are rejected. Stored-
|
|
84
|
+
connection validation accepts verified external paths while name-based
|
|
85
|
+
discovery remains restricted to the managed namespace. `list` reports valid,
|
|
86
|
+
clean managed trees as `{ schemaVersion: 1, trees: [{ name, tree }] }`; a
|
|
87
|
+
missing managed directory is an empty list and is never created by listing.
|
|
88
|
+
|
|
89
|
+
## Synchronization and reading
|
|
90
|
+
|
|
91
|
+
Local synchronization makes no network call and reports the checked-out branch
|
|
92
|
+
and exact `HEAD`. GitHub synchronization performs exactly one
|
|
93
|
+
`git pull --ff-only origin <checked-out-branch>`, revalidates, then reports its
|
|
94
|
+
exact SHA. It does not discover or enforce the remote default branch and does
|
|
95
|
+
not report an `updated` flag.
|
|
96
|
+
|
|
97
|
+
`read` returns a selected node and only its immediate indexed children. Callers
|
|
98
|
+
navigate narrowly from indexes rather than scanning the semantic tree.
|
|
99
|
+
|
|
100
|
+
## Writing
|
|
101
|
+
|
|
102
|
+
`prepare-write` synchronizes and creates a random `context-tree/write/*` branch
|
|
103
|
+
in an isolated worktree at the synchronized SHA. It returns only the worktree
|
|
104
|
+
path and schema version; no token, registry, manifest, lock, or preparation
|
|
105
|
+
record exists.
|
|
106
|
+
|
|
107
|
+
`finish-write` requires that the supplied path is a real non-symlink directory,
|
|
108
|
+
belongs to the connected tree's Git common directory, uses the reserved branch
|
|
109
|
+
prefix, contains pending changes, and verifies as a complete Context Tree.
|
|
110
|
+
Calling it authorizes all pending changes. It stages everything and creates one
|
|
111
|
+
commit with `commit.gpgsign=false` while retaining the host Git identity.
|
|
112
|
+
|
|
113
|
+
For local state it attempts one fast-forward merge into the connected checkout's
|
|
114
|
+
current branch. For GitHub state it attempts one non-force push to that branch.
|
|
115
|
+
Success removes the worktree and task branch. A non-fast-forward failure emits
|
|
116
|
+
`WRITE_OUTDATED` and preserves both. There is no rebase, race loop, semantic
|
|
117
|
+
conflict result, pull-request fallback, or abandoned-worktree cleanup.
|
|
118
|
+
|
|
119
|
+
The write skill may prepare fresh and reapply the intended semantic change
|
|
120
|
+
once after `WRITE_OUTDATED`. A second outdated result is reported to the user.
|
|
121
|
+
|
|
122
|
+
## Publication
|
|
123
|
+
|
|
124
|
+
`publish` requires stored local state, a clean valid tree, and no existing
|
|
125
|
+
`origin`. By default it combines the authenticated GitHub login with the
|
|
126
|
+
managed tree name; an explicit validated `OWNER/REPO` may override it.
|
|
127
|
+
It runs one `gh repo create --private --source <tree> --remote origin --push`.
|
|
128
|
+
|
|
129
|
+
After success, the connection is atomically updated to GitHub state. Clear
|
|
130
|
+
authentication failures produce `GITHUB_AUTH`; clear name collisions produce
|
|
131
|
+
`REPOSITORY_EXISTS`; uncertain or partial outcomes produce
|
|
132
|
+
`PUBLISH_INCOMPLETE`. Publication does not inspect, adopt, repair, retry, or
|
|
133
|
+
delete partial GitHub state. The GitHub operation and local connection update are not
|
|
134
|
+
atomic.
|
|
135
|
+
|
|
136
|
+
## Setup orchestration
|
|
137
|
+
|
|
138
|
+
`context-tree-setup` is an orchestration skill over the five concrete
|
|
139
|
+
workflows. It stops when the project is already connected; otherwise it asks
|
|
140
|
+
whether to create a new tree or connect an existing one and delegates to the
|
|
141
|
+
chosen workflow. Connect targets include listed managed names when any exist,
|
|
142
|
+
plus GitHub `OWNER/REPO` and exact disk paths; without managed trees only
|
|
143
|
+
GitHub and disk-path targets are offered. It never publishes without explicit
|
|
144
|
+
user confirmation. `context-tree-read` and `context-tree-write` invoke setup
|
|
145
|
+
when they receive `NO_CONNECTION`, then retry the operation once.
|
|
146
|
+
|
|
147
|
+
## Hook and skills
|
|
148
|
+
|
|
149
|
+
The session hook resolves the host-supplied `cwd` rather than its own process
|
|
150
|
+
directory, and is silent without a valid connection, including unconnected
|
|
151
|
+
sessions and payloads with no `cwd`; setup routing happens in the read and
|
|
152
|
+
write skills, never in the hook. With a connection, it reports only
|
|
153
|
+
`Context Tree connected at <path>`.
|
|
154
|
+
|
|
155
|
+
Skills invoke the packaged CLI directly as
|
|
156
|
+
`node "<skill-directory>/scripts/context-tree.mjs"` after checking `--version`.
|
|
157
|
+
They rely on the packaged CLI and do not prescribe raw Git/GitHub operations.
|
|
158
|
+
|
|
159
|
+
The skill inventory is setup, create, connect, read, write, and publish;
|
|
160
|
+
setup orchestrates the five concrete workflows.
|
package/hooks/session-start.mjs
CHANGED
|
@@ -28,37 +28,28 @@ if (input.hook_event_name !== "SessionStart" && input.hook_event_name !== "Subag
|
|
|
28
28
|
const pluginRoot = process.env.PLUGIN_ROOT ?? process.env.CLAUDE_PLUGIN_ROOT;
|
|
29
29
|
const packagedCli = pluginRoot === undefined ? undefined : join(pluginRoot, "dist", "cli", "index.mjs");
|
|
30
30
|
if (packagedCli === undefined || !existsSync(packagedCli)) {
|
|
31
|
-
process.stdout.write(JSON.stringify({ systemMessage: "Context Tree setup warning: packaged CLI is unavailable." }));
|
|
32
31
|
process.exit(0);
|
|
33
32
|
}
|
|
34
33
|
const resolved = spawnSync(process.execPath, [packagedCli, "resolve", "--project-path", input.cwd], {
|
|
35
34
|
encoding: "utf8",
|
|
36
35
|
stdio: ["ignore", "pipe", "ignore"],
|
|
37
36
|
});
|
|
37
|
+
if (resolved.status !== 0) process.exit(0);
|
|
38
|
+
|
|
38
39
|
let payload;
|
|
39
40
|
try {
|
|
40
41
|
payload = JSON.parse(resolved.stdout);
|
|
41
42
|
} catch {
|
|
42
|
-
process.stdout.write(JSON.stringify({ systemMessage: "Context Tree setup warning: packaged CLI is unavailable." }));
|
|
43
|
-
process.exit(0);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (resolved.status !== 0) {
|
|
47
|
-
const code = payload?.error?.code;
|
|
48
|
-
if (code === "NO_LINK") process.exit(0);
|
|
49
|
-
if (["AMBIGUOUS_LINK", "CORRUPT_LINK", "STALE_LINK"].includes(code)) {
|
|
50
|
-
process.stdout.write(JSON.stringify({ systemMessage: `Context Tree setup warning: ${payload.error.message}` }));
|
|
51
|
-
}
|
|
52
43
|
process.exit(0);
|
|
53
44
|
}
|
|
54
45
|
|
|
55
|
-
const tree = payload?.
|
|
56
|
-
if (typeof tree?.path !== "string"
|
|
46
|
+
const tree = payload?.tree;
|
|
47
|
+
if (typeof tree?.path !== "string") process.exit(0);
|
|
57
48
|
process.stdout.write(
|
|
58
49
|
JSON.stringify({
|
|
59
50
|
hookSpecificOutput: {
|
|
51
|
+
additionalContext: `Context Tree connected at ${tree.path}`,
|
|
60
52
|
hookEventName: input.hook_event_name,
|
|
61
|
-
additionalContext: `Context Tree ${tree.repository} is linked at ${tree.path}. Use the Context Tree skills for task-relevant durable context.`,
|
|
62
53
|
},
|
|
63
54
|
}),
|
|
64
55
|
);
|
package/package.json
CHANGED
|
@@ -144,15 +144,13 @@ decision, not normal tree content. Keep tree prose current-state: no timeline,
|
|
|
144
144
|
provenance, PR references, or implementation detail. `context-tree verify` must
|
|
145
145
|
pass before any tree commit.
|
|
146
146
|
|
|
147
|
-
Authorization comes from the user or host
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
write and commit
|
|
157
|
-
changes; only an explicit repair request may produce a repair-only write and
|
|
158
|
-
commit limited to validator findings.
|
|
147
|
+
Authorization comes from the user or host. Every write synchronizes the connected
|
|
148
|
+
tree's checked-out branch and uses an isolated clean worktree at that exact
|
|
149
|
+
commit. Invocation of the finishing operation authorizes all pending changes in
|
|
150
|
+
that worktree. The lifecycle verifies, commits, and attempts one fast-forward
|
|
151
|
+
merge or one non-force push. If the destination advanced, preserve the outdated
|
|
152
|
+
worktree, prepare from current state, and reapply the intended semantic change
|
|
153
|
+
once. Do not rebase, loop, push manually, or open a fallback pull request. Keep
|
|
154
|
+
each source-backed write and commit scoped to one source artifact. An invalid
|
|
155
|
+
base blocks semantic changes; only an explicit repair request may produce a
|
|
156
|
+
repair-only write and commit limited to validator findings.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-tree-connect
|
|
3
|
+
description: Connect the current project to an existing Context Tree by managed name, GitHub OWNER/REPO, or exact disk path. Use when the tree already exists; context-tree-setup delegates here once the user has chosen a target.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
|
|
6
|
+
metadata:
|
|
7
|
+
author: first-tree-ai
|
|
8
|
+
version: "0.1.7-alpha.202609010710"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Context Tree Connect
|
|
12
|
+
|
|
13
|
+
Resolve `<skill-directory>` to this skill's directory and run
|
|
14
|
+
`node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
|
|
15
|
+
If the packaged CLI is unavailable, stop and ask the user to reinstall or
|
|
16
|
+
update the plugin.
|
|
17
|
+
|
|
18
|
+
Connect exactly one target supplied by the user:
|
|
19
|
+
|
|
20
|
+
- A managed tree name or GitHub `OWNER/REPO`:
|
|
21
|
+
`node "<skill-directory>/scripts/context-tree.mjs" connect "<name-or-OWNER/REPO>"`.
|
|
22
|
+
- An exact path to an existing Context Tree checkout:
|
|
23
|
+
`node "<skill-directory>/scripts/context-tree.mjs" connect --tree-path "<path>"`.
|
|
24
|
+
That checkout is attached where it already lives and is never copied, moved,
|
|
25
|
+
or deleted.
|
|
26
|
+
|
|
27
|
+
Never accept a repository URL, and never infer, guess, or search the filesystem
|
|
28
|
+
for a target yourself; pass through only what the user typed or confirmed. An
|
|
29
|
+
explicit connect switches the project's connection. Report whether the
|
|
30
|
+
connected tree is local or GitHub-backed, with its canonical path.
|
|
31
|
+
|
|
32
|
+
If connection reports `INVALID_TREE` or `DIRTY_TREE`, report the failure and
|
|
33
|
+
stop. The tree must be repaired or committed at its own location before it can
|
|
34
|
+
be connected.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-tree-create
|
|
3
|
+
description: Create and connect a new managed local Context Tree for the current project. Use when the user wants a brand-new tree; context-tree-setup delegates here after confirming the project has none.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
|
|
6
|
+
metadata:
|
|
7
|
+
author: first-tree-ai
|
|
8
|
+
version: "0.1.7-alpha.202609010710"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Context Tree Create
|
|
12
|
+
|
|
13
|
+
Resolve `<skill-directory>` to this skill's directory and run
|
|
14
|
+
`node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
|
|
15
|
+
If the packaged CLI is unavailable, stop and ask the user to reinstall or
|
|
16
|
+
update the plugin.
|
|
17
|
+
|
|
18
|
+
Run `node "<skill-directory>/scripts/context-tree.mjs" create`. Report whether
|
|
19
|
+
the managed tree was created or already existed, together with its name, path,
|
|
20
|
+
and exact commit SHA.
|
|
21
|
+
|
|
22
|
+
The managed name is derived from the project directory's name. If that name is
|
|
23
|
+
already taken, or the project is already connected to a different tree, report
|
|
24
|
+
the `connect` command the error supplies and stop. Do not replace or remove the
|
|
25
|
+
existing managed tree or connection.
|
|
26
|
+
|
|
27
|
+
After the tree is created or reused, run
|
|
28
|
+
`node "<skill-directory>/scripts/context-tree.mjs" resolve`. When the tree is
|
|
29
|
+
local, ask the user whether to publish it as a private GitHub repository. An
|
|
30
|
+
explicit prior request to publish counts as confirmation; otherwise a "no"
|
|
31
|
+
leaves the tree local, and a "yes" delegates to `$context-tree-publish`. Never
|
|
32
|
+
publish without that confirmation.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-tree-publish
|
|
3
|
+
description: Publish the current project's local Context Tree as a new private GitHub repository. Use only when the user explicitly asks to publish or share the tree.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
|
|
6
|
+
metadata:
|
|
7
|
+
author: first-tree-ai
|
|
8
|
+
version: "0.1.7-alpha.202609010710"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Context Tree Publish
|
|
12
|
+
|
|
13
|
+
Resolve `<skill-directory>` to this skill's directory and run
|
|
14
|
+
`node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
|
|
15
|
+
If the packaged CLI is unavailable, stop and ask the user to reinstall or
|
|
16
|
+
update the plugin.
|
|
17
|
+
|
|
18
|
+
Run `node "<skill-directory>/scripts/context-tree.mjs" publish`. When the user
|
|
19
|
+
explicitly supplies an alternative, append the validated `OWNER/REPO` argument.
|
|
20
|
+
Never accept a repository URL.
|
|
21
|
+
|
|
22
|
+
Publication creates one new private repository, and the local connection update
|
|
23
|
+
that follows is not part of the same atomic step. If it reports
|
|
24
|
+
`PUBLISH_INCOMPLETE`, do not inspect, adopt, repair, retry, or delete partial
|
|
25
|
+
state; report the uncertain outcome. If it reports `INVALID_TREE`, run `verify`
|
|
26
|
+
and report its findings.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { lstatSync, readFileSync, realpathSync } from "node:fs";
|
|
5
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const PACKAGE_NAME = "@first-tree-ai/context-tree";
|
|
9
|
+
const REINSTALL_MESSAGE = "Context Tree packaged CLI is unavailable. Reinstall or update the Context Tree plugin.";
|
|
10
|
+
|
|
11
|
+
function packagedCli() {
|
|
12
|
+
try {
|
|
13
|
+
const packageRoot = realpathSync(resolve(dirname(fileURLToPath(import.meta.url)), "../../.."));
|
|
14
|
+
const packageJson = resolve(packageRoot, "package.json");
|
|
15
|
+
const cli = resolve(packageRoot, "dist/cli/index.mjs");
|
|
16
|
+
if (lstatSync(packageJson).isSymbolicLink() || !lstatSync(packageJson).isFile()) return undefined;
|
|
17
|
+
if (JSON.parse(readFileSync(packageJson, "utf8")).name !== PACKAGE_NAME) return undefined;
|
|
18
|
+
if (lstatSync(cli).isSymbolicLink() || !lstatSync(cli).isFile()) return undefined;
|
|
19
|
+
const realCli = realpathSync(cli);
|
|
20
|
+
const containedPath = relative(packageRoot, realCli);
|
|
21
|
+
return containedPath !== "" && !containedPath.startsWith("..") && !isAbsolute(containedPath) ? realCli : undefined;
|
|
22
|
+
} catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function forward(result) {
|
|
28
|
+
if (result.error !== undefined) {
|
|
29
|
+
process.stderr.write(`${REINSTALL_MESSAGE}\n`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
if (result.signal !== null) process.kill(process.pid, result.signal);
|
|
33
|
+
process.exit(result.status ?? 1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const cli = packagedCli();
|
|
37
|
+
if (cli === undefined) {
|
|
38
|
+
process.stderr.write(`${REINSTALL_MESSAGE}\n`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
forward(spawnSync(process.execPath, [cli, ...process.argv.slice(2)], { stdio: "inherit" }));
|