@treeseed/cli 0.4.6 → 0.4.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.
- package/README.md +12 -4
- package/dist/cli/handlers/close.js +3 -1
- package/dist/cli/handlers/release.js +3 -1
- package/dist/cli/handlers/save.js +5 -3
- package/dist/cli/handlers/stage.js +3 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/operations-registry.js +5 -2
- package/dist/cli/runtime.d.ts +4 -4
- package/dist/cli/runtime.js +47 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -14,10 +14,18 @@ This package publishes the `treeseed` binary. `@treeseed/sdk` owns the reusable
|
|
|
14
14
|
Install the CLI with its runtime dependencies:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install @treeseed/cli @treeseed/core @treeseed/sdk
|
|
17
|
+
npm install @treeseed/cli @treeseed/core @treeseed/sdk
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
`@treeseed/cli` is a thin installable wrapper over `@treeseed/sdk` workflow and operations interfaces plus the `@treeseed/
|
|
20
|
+
`@treeseed/cli` is a thin installable wrapper over `@treeseed/sdk` workflow and operations interfaces plus the `@treeseed/core` runtime namespaces. `treeseed dev` and `treeseed agents ...` resolve and delegate to the tenant-installed or sibling-workspace `@treeseed/core` runtime. In normal consumer installs, npm resolves the runtime dependencies automatically.
|
|
21
|
+
|
|
22
|
+
Workflow guarantees:
|
|
23
|
+
|
|
24
|
+
- `treeseed init`, `treeseed config`, and `treeseed release` resolve the project from nested directories and do not rely on the currently checked-out task branch.
|
|
25
|
+
- `treeseed switch` requires a clean worktree before leaving the current branch and creates new task branches from the latest `staging`.
|
|
26
|
+
- `treeseed save` is the canonical checkpoint command: it syncs the current branch with origin, succeeds even when no new changes exist, and can create or refresh preview deployments with `--preview`.
|
|
27
|
+
- `treeseed stage` and `treeseed close` auto-save meaningful uncommitted task-branch changes before merge or cleanup, then leave the repository on `staging`.
|
|
28
|
+
- `treeseed release` completes on `staging` after promoting `staging` into `main` and pushing the release tag.
|
|
21
29
|
|
|
22
30
|
After installation, the published binary is available as:
|
|
23
31
|
|
|
@@ -34,7 +42,7 @@ The main workflow commands exposed by the current CLI are:
|
|
|
34
42
|
- `treeseed tasks [--json]`
|
|
35
43
|
- `treeseed switch <branch-name> [--preview]`
|
|
36
44
|
- `treeseed dev`
|
|
37
|
-
- `treeseed save "<commit message>"`
|
|
45
|
+
- `treeseed save [--preview] "<commit message>"`
|
|
38
46
|
- `treeseed stage "<resolution message>"`
|
|
39
47
|
- `treeseed close "<close reason>"`
|
|
40
48
|
- `treeseed release --major|--minor|--patch`
|
|
@@ -51,7 +59,7 @@ treeseed status
|
|
|
51
59
|
treeseed config
|
|
52
60
|
treeseed switch feature/search-improvements --preview
|
|
53
61
|
treeseed dev
|
|
54
|
-
treeseed save "feat: add search filters"
|
|
62
|
+
treeseed save --preview "feat: add search filters"
|
|
55
63
|
treeseed stage "feat: add search filters"
|
|
56
64
|
treeseed release --patch
|
|
57
65
|
treeseed status --json
|
|
@@ -11,8 +11,10 @@ const handleClose = async (invocation, context) => {
|
|
|
11
11
|
summary: "Treeseed close completed successfully.",
|
|
12
12
|
facts: [
|
|
13
13
|
{ label: "Closed branch", value: payload.branchName },
|
|
14
|
+
{ label: "Auto-saved", value: payload.autoSaved ? "yes" : "no" },
|
|
14
15
|
{ label: "Deprecated tag", value: payload.deprecatedTag.tagName },
|
|
15
|
-
{ label: "Preview cleanup", value: payload.previewCleanup.performed ? "performed" : "not needed" }
|
|
16
|
+
{ label: "Preview cleanup", value: payload.previewCleanup.performed ? "performed" : "not needed" },
|
|
17
|
+
{ label: "Final branch", value: payload.finalBranch }
|
|
16
18
|
],
|
|
17
19
|
nextSteps: renderWorkflowNextSteps(result),
|
|
18
20
|
report: payload
|
|
@@ -14,7 +14,9 @@ const handleRelease = async (invocation, context) => {
|
|
|
14
14
|
{ label: "Release level", value: payload.level },
|
|
15
15
|
{ label: "Root version", value: payload.rootVersion },
|
|
16
16
|
{ label: "Release tag", value: payload.releaseTag },
|
|
17
|
-
{ label: "
|
|
17
|
+
{ label: "Released commit", value: payload.releasedCommit.slice(0, 12) },
|
|
18
|
+
{ label: "Updated packages", value: payload.touchedPackages.length },
|
|
19
|
+
{ label: "Final branch", value: payload.finalBranch }
|
|
18
20
|
],
|
|
19
21
|
nextSteps: renderWorkflowNextSteps(result),
|
|
20
22
|
report: payload
|
|
@@ -4,18 +4,20 @@ const handleSave = async (invocation, context) => {
|
|
|
4
4
|
try {
|
|
5
5
|
const result = await createWorkflowSdk(context).save({
|
|
6
6
|
message: invocation.positionals.join(" ").trim(),
|
|
7
|
-
hotfix: invocation.args.hotfix === true
|
|
7
|
+
hotfix: invocation.args.hotfix === true,
|
|
8
|
+
preview: invocation.args.preview === true
|
|
8
9
|
});
|
|
9
10
|
const payload = result.payload;
|
|
10
11
|
return guidedResult({
|
|
11
12
|
command: invocation.commandName || "save",
|
|
12
|
-
summary: "Treeseed save completed successfully.",
|
|
13
|
+
summary: payload.noChanges ? "Treeseed save found no new changes and confirmed branch sync." : "Treeseed save completed successfully.",
|
|
13
14
|
facts: [
|
|
14
15
|
{ label: "Branch", value: payload.branch },
|
|
15
16
|
{ label: "Environment scope", value: payload.scope },
|
|
16
17
|
{ label: "Hotfix", value: payload.hotfix ? "yes" : "no" },
|
|
17
18
|
{ label: "Commit", value: payload.commitSha.slice(0, 12) },
|
|
18
|
-
{ label: "
|
|
19
|
+
{ label: "Commit created", value: payload.commitCreated ? "yes" : "no" },
|
|
20
|
+
{ label: "Preview action", value: payload.previewAction?.status ?? "skipped" }
|
|
19
21
|
],
|
|
20
22
|
nextSteps: renderWorkflowNextSteps(result),
|
|
21
23
|
report: payload
|
|
@@ -12,9 +12,11 @@ const handleStage = async (invocation, context) => {
|
|
|
12
12
|
facts: [
|
|
13
13
|
{ label: "Merged branch", value: payload.branchName },
|
|
14
14
|
{ label: "Merge target", value: payload.mergeTarget },
|
|
15
|
+
{ label: "Auto-saved", value: payload.autoSaved ? "yes" : "no" },
|
|
15
16
|
{ label: "Deprecated tag", value: payload.deprecatedTag.tagName },
|
|
16
17
|
{ label: "Staging wait", value: payload.stagingWait.status },
|
|
17
|
-
{ label: "Preview cleanup", value: payload.previewCleanup.performed ? "performed" : "not needed" }
|
|
18
|
+
{ label: "Preview cleanup", value: payload.previewCleanup.performed ? "performed" : "not needed" },
|
|
19
|
+
{ label: "Final branch", value: payload.finalBranch }
|
|
18
20
|
],
|
|
19
21
|
nextSteps: renderWorkflowNextSteps(result),
|
|
20
22
|
report: payload
|
package/dist/cli/help.js
CHANGED
|
@@ -108,7 +108,7 @@ function renderTreeseedHelp(commandName) {
|
|
|
108
108
|
" treeseed agents --help",
|
|
109
109
|
"",
|
|
110
110
|
"Notes",
|
|
111
|
-
" - Delegates to the `@treeseed/
|
|
111
|
+
" - Delegates to the integrated `@treeseed/core` agent runtime.",
|
|
112
112
|
" - Use `treeseed agents --help` to list supported agent subcommands."
|
|
113
113
|
].join("\n");
|
|
114
114
|
}
|
|
@@ -34,13 +34,14 @@ const CLI_COMMAND_OVERLAYS = /* @__PURE__ */ new Map([
|
|
|
34
34
|
handlerName: "switch"
|
|
35
35
|
})],
|
|
36
36
|
["save", command({
|
|
37
|
-
usage: "treeseed save [--hotfix] <message> [--json]",
|
|
37
|
+
usage: "treeseed save [--hotfix] [--preview] <message> [--json]",
|
|
38
38
|
arguments: [{ name: "message", description: "Git commit message for the save operation.", required: true, kind: "message_tail" }],
|
|
39
39
|
options: [
|
|
40
40
|
{ name: "hotfix", flags: "--hotfix", description: "Allow save on main for an explicit hotfix.", kind: "boolean" },
|
|
41
|
+
{ name: "preview", flags: "--preview", description: "Create or refresh the branch preview during save.", kind: "boolean" },
|
|
41
42
|
{ name: "json", flags: "--json", description: "Emit machine-readable JSON instead of human-readable text.", kind: "boolean" }
|
|
42
43
|
],
|
|
43
|
-
examples: ['treeseed save "feat: add search filters"', 'treeseed save --hotfix "fix: unblock production form submit"'],
|
|
44
|
+
examples: ['treeseed save "feat: add search filters"', 'treeseed save --preview "feat: add search filters"', 'treeseed save --hotfix "fix: unblock production form submit"'],
|
|
44
45
|
executionMode: "handler",
|
|
45
46
|
handlerName: "save"
|
|
46
47
|
})],
|
|
@@ -49,6 +50,7 @@ const CLI_COMMAND_OVERLAYS = /* @__PURE__ */ new Map([
|
|
|
49
50
|
arguments: [{ name: "message", description: "Reason for closing the task without staging it.", required: true, kind: "message_tail" }],
|
|
50
51
|
options: [{ name: "json", flags: "--json", description: "Emit machine-readable JSON instead of human-readable text.", kind: "boolean" }],
|
|
51
52
|
examples: ['treeseed close "superseded by feature/search-v2"'],
|
|
53
|
+
notes: ["Auto-saves meaningful uncommitted task-branch changes before cleanup unless disabled in the workflow API."],
|
|
52
54
|
executionMode: "handler",
|
|
53
55
|
handlerName: "close"
|
|
54
56
|
})],
|
|
@@ -57,6 +59,7 @@ const CLI_COMMAND_OVERLAYS = /* @__PURE__ */ new Map([
|
|
|
57
59
|
arguments: [{ name: "message", description: "Resolution message for the staged task.", required: true, kind: "message_tail" }],
|
|
58
60
|
options: [{ name: "json", flags: "--json", description: "Emit machine-readable JSON instead of human-readable text.", kind: "boolean" }],
|
|
59
61
|
examples: ['treeseed stage "feat: add search filters"'],
|
|
62
|
+
notes: ["Auto-saves meaningful uncommitted task-branch changes before merging into staging."],
|
|
60
63
|
executionMode: "handler",
|
|
61
64
|
handlerName: "stage"
|
|
62
65
|
})],
|
package/dist/cli/runtime.d.ts
CHANGED
|
@@ -19,13 +19,13 @@ export declare class TreeseedOperationsSdk {
|
|
|
19
19
|
private executeHandler;
|
|
20
20
|
private executeAdapter;
|
|
21
21
|
private executeAgents;
|
|
22
|
-
executeOperation(request: TreeseedOperationRequest, overrides?: Partial<TreeseedCommandContext>): Promise<
|
|
23
|
-
run(argv: string[], overrides?: Partial<TreeseedCommandContext>): Promise<
|
|
22
|
+
executeOperation(request: TreeseedOperationRequest, overrides?: Partial<TreeseedCommandContext>): Promise<any>;
|
|
23
|
+
run(argv: string[], overrides?: Partial<TreeseedCommandContext>): Promise<any>;
|
|
24
24
|
}
|
|
25
25
|
export declare function resolveTreeseedCommandCwd(spec: TreeseedOperationSpec, cwd: string): {
|
|
26
26
|
cwd: string;
|
|
27
27
|
resolvedProjectRoot: string | null;
|
|
28
28
|
resolvedWorkspaceRoot: any;
|
|
29
29
|
};
|
|
30
|
-
export declare function executeTreeseedCommand(commandName: string, argv: string[], context: TreeseedCommandContext): Promise<
|
|
31
|
-
export declare function runTreeseedCli(argv: string[], overrides?: Partial<TreeseedCommandContext>): Promise<
|
|
30
|
+
export declare function executeTreeseedCommand(commandName: string, argv: string[], context: TreeseedCommandContext): Promise<any>;
|
|
31
|
+
export declare function runTreeseedCli(argv: string[], overrides?: Partial<TreeseedCommandContext>): Promise<any>;
|
package/dist/cli/runtime.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
2
6
|
import { findNearestTreeseedRoot, findNearestTreeseedWorkspaceRoot } from "@treeseed/sdk/workflow-support";
|
|
3
7
|
import { TreeseedOperationsSdk as SdkOperationsRuntime } from "@treeseed/sdk/operations";
|
|
4
8
|
import { COMMAND_HANDLERS } from "./registry.js";
|
|
5
9
|
import { renderTreeseedHelp, renderUsage, suggestTreeseedCommands } from "./operations-help.js";
|
|
6
10
|
import { parseTreeseedInvocation, validateTreeseedInvocation } from "./operations-parser.js";
|
|
7
11
|
import { findTreeseedOperation, TRESEED_OPERATION_SPECS } from "./operations-registry.js";
|
|
12
|
+
const require2 = createRequire(import.meta.url);
|
|
8
13
|
function isHelpFlag(value) {
|
|
9
14
|
return value === "--help" || value === "-h";
|
|
10
15
|
}
|
|
@@ -16,6 +21,43 @@ function defaultWrite(output, stream = "stdout") {
|
|
|
16
21
|
function defaultSpawn(command, args, options) {
|
|
17
22
|
return spawnSync(command, args, options);
|
|
18
23
|
}
|
|
24
|
+
function resolveCoreAgentCliEntrypoint(cwd) {
|
|
25
|
+
const workspaceRoot = findNearestTreeseedWorkspaceRoot(cwd) ?? cwd;
|
|
26
|
+
const workspacePackageJsonPath = resolve(workspaceRoot, "packages", "core", "package.json");
|
|
27
|
+
const siblingPackageJsonPath = resolve(cwd, "..", "core", "package.json");
|
|
28
|
+
const installedPackageJsonPath = resolve(cwd, "node_modules", "@treeseed", "core", "package.json");
|
|
29
|
+
let packageJsonPath = workspacePackageJsonPath;
|
|
30
|
+
if (!existsSync(packageJsonPath)) {
|
|
31
|
+
packageJsonPath = existsSync(siblingPackageJsonPath) ? siblingPackageJsonPath : installedPackageJsonPath;
|
|
32
|
+
}
|
|
33
|
+
if (!existsSync(packageJsonPath)) {
|
|
34
|
+
try {
|
|
35
|
+
const resolvedPath = require2.resolve("@treeseed/core", { paths: [cwd] });
|
|
36
|
+
let currentDir = dirname(resolvedPath);
|
|
37
|
+
while (!existsSync(resolve(currentDir, "package.json"))) {
|
|
38
|
+
const parentDir = dirname(currentDir);
|
|
39
|
+
if (parentDir === currentDir) {
|
|
40
|
+
throw new Error("Unable to resolve the installed @treeseed/core package root.");
|
|
41
|
+
}
|
|
42
|
+
currentDir = parentDir;
|
|
43
|
+
}
|
|
44
|
+
packageJsonPath = resolve(currentDir, "package.json");
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"Treeseed agent commands require the integrated `@treeseed/core` runtime. Install `@treeseed/core` in the current project or run the CLI inside a Treeseed workspace."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const packageRoot = dirname(packageJsonPath);
|
|
52
|
+
const sourceEntrypoint = resolve(packageRoot, "src", "agents", "cli.ts");
|
|
53
|
+
if (existsSync(sourceEntrypoint)) {
|
|
54
|
+
return pathToFileURL(sourceEntrypoint).href;
|
|
55
|
+
}
|
|
56
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
57
|
+
const exportedEntrypoint = packageJson.exports?.["./agent/cli"];
|
|
58
|
+
const distRelativePath = typeof exportedEntrypoint === "string" ? exportedEntrypoint : exportedEntrypoint?.default ?? "./dist/agents/cli.js";
|
|
59
|
+
return pathToFileURL(resolve(packageRoot, distRelativePath)).href;
|
|
60
|
+
}
|
|
19
61
|
const sdkOperationsRuntime = new SdkOperationsRuntime();
|
|
20
62
|
function formatValidationError(spec, errors) {
|
|
21
63
|
return [
|
|
@@ -148,7 +190,7 @@ class TreeseedOperationsSdk {
|
|
|
148
190
|
}
|
|
149
191
|
async executeAgents(argv, context) {
|
|
150
192
|
try {
|
|
151
|
-
const { runTreeseedAgentCli } = await import(
|
|
193
|
+
const { runTreeseedAgentCli } = await import(resolveCoreAgentCliEntrypoint(context.cwd));
|
|
152
194
|
return await runTreeseedAgentCli(argv, {
|
|
153
195
|
cwd: context.cwd,
|
|
154
196
|
env: context.env,
|
|
@@ -172,6 +214,10 @@ class TreeseedOperationsSdk {
|
|
|
172
214
|
const argv = request.argv ?? [];
|
|
173
215
|
const commandName = request.commandName;
|
|
174
216
|
if (commandName === "agents") {
|
|
217
|
+
if (argv.some(isHelpFlag)) {
|
|
218
|
+
context.write(renderTreeseedHelp("agents"), "stdout");
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
175
221
|
return this.executeAgents(argv, context);
|
|
176
222
|
}
|
|
177
223
|
const spec = findTreeseedOperation(commandName);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "Operator-facing Treeseed CLI package.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
"release:publish": "node ./scripts/run-ts.mjs ./scripts/publish-package.ts"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@treeseed/
|
|
47
|
-
"@treeseed/sdk": "^0.4.5"
|
|
46
|
+
"@treeseed/sdk": "^0.4.7"
|
|
48
47
|
},
|
|
49
48
|
"devDependencies": {
|
|
50
49
|
"@types/node": "^24.6.0",
|