@uluops/setup 0.2.0 → 0.4.0
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 +56 -53
- package/assets/agents/anxiety-reader-agent.md +464 -0
- package/assets/commands/agents/anxiety-reader.md +160 -0
- package/assets/commands/agents/api-contract.md +1 -0
- package/assets/commands/agents/architect.md +1 -0
- package/assets/commands/agents/aristotle-analyst.md +1 -0
- package/assets/commands/agents/aristotle-explorer.md +1 -0
- package/assets/commands/agents/aristotle-forecaster.md +1 -0
- package/assets/commands/agents/aristotle-validator.md +1 -0
- package/assets/commands/agents/assumption-excavator.md +1 -0
- package/assets/commands/agents/audit.md +1 -0
- package/assets/commands/agents/{validate.md → code-validate.md} +6 -5
- package/assets/commands/agents/docs-validate.md +1 -0
- package/assets/commands/agents/frontend.md +1 -0
- package/assets/commands/agents/mcp-validate.md +1 -0
- package/assets/commands/agents/optimize.md +1 -0
- package/assets/commands/agents/pattern-analyzer.md +1 -0
- package/assets/commands/agents/prompt-quality.md +1 -0
- package/assets/commands/agents/prompt-validate.md +1 -0
- package/assets/commands/agents/public-interface.md +1 -0
- package/assets/commands/agents/release.md +1 -0
- package/assets/commands/agents/security.md +1 -0
- package/assets/commands/agents/test-review.md +1 -0
- package/assets/commands/agents/type-safety.md +1 -0
- package/assets/commands/agents/workflow-synthesis.md +1 -0
- package/assets/commands/pipelines/aristotle.md +143 -0
- package/assets/commands/pipelines/ship.md +188 -0
- package/assets/commands/workflows/prompt-audit.md +37 -747
- package/dist/cli.js +251 -207
- package/dist/harnesses/claude-code.d.ts +8 -0
- package/dist/harnesses/claude-code.js +72 -0
- package/dist/harnesses/codex.d.ts +15 -0
- package/dist/harnesses/codex.js +53 -0
- package/dist/harnesses/gemini-cli.d.ts +16 -0
- package/dist/harnesses/gemini-cli.js +54 -0
- package/dist/harnesses/index.d.ts +18 -0
- package/dist/harnesses/index.js +45 -0
- package/dist/harnesses/opencode.d.ts +14 -0
- package/dist/harnesses/opencode.js +130 -0
- package/dist/harnesses/types.d.ts +87 -0
- package/dist/harnesses/types.js +24 -0
- package/dist/lib/agent-transform.d.ts +12 -0
- package/dist/lib/agent-transform.js +129 -0
- package/dist/lib/asset-catalog.d.ts +9 -0
- package/dist/lib/asset-catalog.js +56 -0
- package/dist/lib/atomic-write.d.ts +11 -0
- package/dist/lib/atomic-write.js +28 -0
- package/dist/lib/config-merger.d.ts +7 -1
- package/dist/lib/config-merger.js +34 -5
- package/dist/lib/display.d.ts +14 -0
- package/dist/lib/display.js +66 -0
- package/dist/lib/file-ops.d.ts +6 -0
- package/dist/lib/file-ops.js +22 -1
- package/dist/lib/hash.d.ts +1 -0
- package/dist/lib/hash.js +1 -0
- package/dist/lib/health.d.ts +2 -0
- package/dist/lib/health.js +10 -0
- package/dist/lib/manifest.d.ts +22 -5
- package/dist/lib/manifest.js +148 -13
- package/dist/lib/paths.d.ts +15 -3
- package/dist/lib/paths.js +71 -13
- package/dist/lib/settings-merger.d.ts +9 -1
- package/dist/lib/settings-merger.js +45 -17
- package/dist/steps/agents.d.ts +5 -1
- package/dist/steps/agents.js +59 -9
- package/dist/steps/auth.js +26 -10
- package/dist/steps/commands.d.ts +6 -1
- package/dist/steps/commands.js +87 -9
- package/dist/steps/detect.d.ts +3 -0
- package/dist/steps/detect.js +7 -0
- package/dist/steps/mcp.d.ts +6 -2
- package/dist/steps/mcp.js +46 -21
- package/dist/steps/metrics.d.ts +14 -10
- package/dist/steps/metrics.js +59 -89
- package/dist/steps/shell.d.ts +2 -0
- package/dist/steps/shell.js +16 -9
- package/dist/steps/signup.d.ts +6 -3
- package/dist/steps/signup.js +26 -14
- package/dist/steps/verify.d.ts +2 -2
- package/dist/steps/verify.js +84 -117
- package/package.json +32 -7
- package/assets/commands/workflows/aristotle.md +0 -543
- package/assets/commands/workflows/ship.md +0 -721
- package/dist/test/auth.test.d.ts +0 -1
- package/dist/test/auth.test.js +0 -43
- package/dist/test/config-io.test.d.ts +0 -1
- package/dist/test/config-io.test.js +0 -56
- package/dist/test/config-merger.test.d.ts +0 -1
- package/dist/test/config-merger.test.js +0 -94
- package/dist/test/detect.test.d.ts +0 -1
- package/dist/test/detect.test.js +0 -25
- package/dist/test/file-ops.test.d.ts +0 -1
- package/dist/test/file-ops.test.js +0 -100
- package/dist/test/hash.test.d.ts +0 -1
- package/dist/test/hash.test.js +0 -14
- package/dist/test/manifest.test.d.ts +0 -1
- package/dist/test/manifest.test.js +0 -78
- package/dist/test/paths.test.d.ts +0 -1
- package/dist/test/paths.test.js +0 -30
- package/dist/test/settings-merger.test.d.ts +0 -1
- package/dist/test/settings-merger.test.js +0 -167
- package/dist/test/shell-profile.test.d.ts +0 -1
- package/dist/test/shell-profile.test.js +0 -40
- package/dist/test/shell.test.d.ts +0 -1
- package/dist/test/shell.test.js +0 -71
- package/dist/test/signup.test.d.ts +0 -1
- package/dist/test/signup.test.js +0 -83
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
-
import { getShellProfile } from "../lib/paths.js";
|
|
3
|
-
afterEach(() => {
|
|
4
|
-
vi.unstubAllEnvs();
|
|
5
|
-
});
|
|
6
|
-
describe("getShellProfile", () => {
|
|
7
|
-
it("returns .zshrc for zsh shell", () => {
|
|
8
|
-
vi.stubEnv("SHELL", "/bin/zsh");
|
|
9
|
-
const result = getShellProfile();
|
|
10
|
-
expect(result).not.toBeNull();
|
|
11
|
-
expect(result.shell).toBe("zsh");
|
|
12
|
-
expect(result.path).toMatch(/\.zshrc$/);
|
|
13
|
-
});
|
|
14
|
-
it("returns .bashrc for bash on linux", () => {
|
|
15
|
-
vi.stubEnv("SHELL", "/bin/bash");
|
|
16
|
-
// getShellProfile checks platform() — on linux it returns .bashrc
|
|
17
|
-
const result = getShellProfile();
|
|
18
|
-
expect(result).not.toBeNull();
|
|
19
|
-
expect(result.shell).toBe("bash");
|
|
20
|
-
// On linux: .bashrc, on darwin: .bash_profile
|
|
21
|
-
expect(result.path).toMatch(/\.bash(rc|_profile)$/);
|
|
22
|
-
});
|
|
23
|
-
it("returns config.fish for fish shell", () => {
|
|
24
|
-
vi.stubEnv("SHELL", "/usr/bin/fish");
|
|
25
|
-
const result = getShellProfile();
|
|
26
|
-
expect(result).not.toBeNull();
|
|
27
|
-
expect(result.shell).toBe("fish");
|
|
28
|
-
expect(result.path).toMatch(/config\.fish$/);
|
|
29
|
-
});
|
|
30
|
-
it("returns null for unknown shell", () => {
|
|
31
|
-
vi.stubEnv("SHELL", "/bin/csh");
|
|
32
|
-
const result = getShellProfile();
|
|
33
|
-
expect(result).toBeNull();
|
|
34
|
-
});
|
|
35
|
-
it("returns null when SHELL is empty", () => {
|
|
36
|
-
vi.stubEnv("SHELL", "");
|
|
37
|
-
const result = getShellProfile();
|
|
38
|
-
expect(result).toBeNull();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test/shell.test.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { writeFile, readFile, unlink, mkdtemp } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import { writeShellExport, removeShellExport } from "../steps/shell.js";
|
|
6
|
-
let tmpDir;
|
|
7
|
-
let profilePath;
|
|
8
|
-
beforeEach(async () => {
|
|
9
|
-
tmpDir = await mkdtemp(join(tmpdir(), "uluops-test-"));
|
|
10
|
-
profilePath = join(tmpDir, ".bashrc");
|
|
11
|
-
});
|
|
12
|
-
afterEach(async () => {
|
|
13
|
-
try {
|
|
14
|
-
await unlink(profilePath);
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
// may not exist
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
describe("writeShellExport", () => {
|
|
21
|
-
it("creates profile with fenced block if file does not exist", async () => {
|
|
22
|
-
await writeShellExport(profilePath, "ulr_abc123", false);
|
|
23
|
-
const content = await readFile(profilePath, "utf-8");
|
|
24
|
-
expect(content).toContain("# --- UluOps (managed by @uluops/setup) ---");
|
|
25
|
-
expect(content).toContain('export ULUOPS_API_KEY="ulr_abc123"');
|
|
26
|
-
expect(content).toContain("# --- /UluOps ---");
|
|
27
|
-
});
|
|
28
|
-
it("appends fenced block to existing file", async () => {
|
|
29
|
-
await writeFile(profilePath, "# existing content\n");
|
|
30
|
-
await writeShellExport(profilePath, "ulr_abc123", false);
|
|
31
|
-
const content = await readFile(profilePath, "utf-8");
|
|
32
|
-
expect(content).toContain("# existing content");
|
|
33
|
-
expect(content).toContain('export ULUOPS_API_KEY="ulr_abc123"');
|
|
34
|
-
});
|
|
35
|
-
it("replaces existing fenced block on re-run", async () => {
|
|
36
|
-
await writeShellExport(profilePath, "ulr_old", false);
|
|
37
|
-
await writeShellExport(profilePath, "ulr_new", false);
|
|
38
|
-
const content = await readFile(profilePath, "utf-8");
|
|
39
|
-
expect(content).toContain('export ULUOPS_API_KEY="ulr_new"');
|
|
40
|
-
expect(content).not.toContain("ulr_old");
|
|
41
|
-
// Only one fenced block should exist
|
|
42
|
-
expect(content.split("# --- UluOps").length).toBe(2);
|
|
43
|
-
});
|
|
44
|
-
it("does not modify files in dry-run mode", async () => {
|
|
45
|
-
await writeFile(profilePath, "# existing\n");
|
|
46
|
-
await writeShellExport(profilePath, "ulr_abc123", true);
|
|
47
|
-
const content = await readFile(profilePath, "utf-8");
|
|
48
|
-
expect(content).toBe("# existing\n");
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
describe("removeShellExport", () => {
|
|
52
|
-
it("removes the fenced block from the file", async () => {
|
|
53
|
-
const initial = "# before\n\n# --- UluOps (managed by @uluops/setup) ---\nexport ULUOPS_API_KEY=\"ulr_abc\"\n# --- /UluOps ---\n\n# after\n";
|
|
54
|
-
await writeFile(profilePath, initial);
|
|
55
|
-
await removeShellExport(profilePath);
|
|
56
|
-
const content = await readFile(profilePath, "utf-8");
|
|
57
|
-
expect(content).toContain("# before");
|
|
58
|
-
expect(content).toContain("# after");
|
|
59
|
-
expect(content).not.toContain("ULUOPS_API_KEY");
|
|
60
|
-
expect(content).not.toContain("UluOps");
|
|
61
|
-
});
|
|
62
|
-
it("does nothing if no fenced block exists", async () => {
|
|
63
|
-
await writeFile(profilePath, "# no uluops here\n");
|
|
64
|
-
await removeShellExport(profilePath);
|
|
65
|
-
const content = await readFile(profilePath, "utf-8");
|
|
66
|
-
expect(content).toBe("# no uluops here\n");
|
|
67
|
-
});
|
|
68
|
-
it("does nothing if file does not exist", async () => {
|
|
69
|
-
await expect(removeShellExport(join(tmpDir, "nonexistent"))).resolves.toBeUndefined();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test/signup.test.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
-
import { validatePassword, validateEmail } from "../steps/signup.js";
|
|
3
|
-
describe("validatePassword", () => {
|
|
4
|
-
it("accepts a valid password", () => {
|
|
5
|
-
expect(validatePassword("GoodPass1")).toBe(true);
|
|
6
|
-
});
|
|
7
|
-
it("rejects passwords shorter than 8 chars", () => {
|
|
8
|
-
expect(validatePassword("Short1A")).toContain("at least 8");
|
|
9
|
-
});
|
|
10
|
-
it("rejects passwords longer than 128 chars", () => {
|
|
11
|
-
const long = "Aa1" + "x".repeat(126);
|
|
12
|
-
expect(validatePassword(long)).toContain("at most 128");
|
|
13
|
-
});
|
|
14
|
-
it("rejects passwords without lowercase", () => {
|
|
15
|
-
expect(validatePassword("ALLCAPS123")).toContain("lowercase");
|
|
16
|
-
});
|
|
17
|
-
it("rejects passwords without uppercase", () => {
|
|
18
|
-
expect(validatePassword("alllower123")).toContain("uppercase");
|
|
19
|
-
});
|
|
20
|
-
it("rejects passwords without number", () => {
|
|
21
|
-
expect(validatePassword("NoNumbersHere")).toContain("number");
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
describe("validateEmail", () => {
|
|
25
|
-
it("accepts a valid email", () => {
|
|
26
|
-
expect(validateEmail("user@example.com")).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
it("rejects empty string", () => {
|
|
29
|
-
expect(validateEmail("")).toContain("required");
|
|
30
|
-
});
|
|
31
|
-
it("rejects missing @", () => {
|
|
32
|
-
expect(validateEmail("notanemail")).toContain("Invalid");
|
|
33
|
-
});
|
|
34
|
-
it("rejects missing domain", () => {
|
|
35
|
-
expect(validateEmail("user@")).toContain("Invalid");
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe("signup (network)", () => {
|
|
39
|
-
afterEach(() => {
|
|
40
|
-
vi.restoreAllMocks();
|
|
41
|
-
});
|
|
42
|
-
it("handles 409 conflict (duplicate email)", async () => {
|
|
43
|
-
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
|
|
44
|
-
ok: false,
|
|
45
|
-
status: 409,
|
|
46
|
-
json: async () => ({ error: { message: "Email already exists" } }),
|
|
47
|
-
headers: new Headers(),
|
|
48
|
-
}));
|
|
49
|
-
const { signup } = await import("../steps/signup.js");
|
|
50
|
-
// Mock inquirer prompts
|
|
51
|
-
vi.mock("@inquirer/prompts", () => ({
|
|
52
|
-
input: vi.fn().mockResolvedValue("existing@example.com"),
|
|
53
|
-
password: vi.fn().mockResolvedValue("ValidPass1"),
|
|
54
|
-
}));
|
|
55
|
-
await expect(signup()).rejects.toThrow("already registered");
|
|
56
|
-
vi.unstubAllGlobals();
|
|
57
|
-
});
|
|
58
|
-
it("handles 429 rate limit", async () => {
|
|
59
|
-
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
|
|
60
|
-
ok: false,
|
|
61
|
-
status: 429,
|
|
62
|
-
json: async () => ({ error: { message: "Too many requests" } }),
|
|
63
|
-
headers: new Headers({ "Retry-After": "30" }),
|
|
64
|
-
}));
|
|
65
|
-
const { signup } = await import("../steps/signup.js");
|
|
66
|
-
vi.mock("@inquirer/prompts", () => ({
|
|
67
|
-
input: vi.fn().mockResolvedValue("user@example.com"),
|
|
68
|
-
password: vi.fn().mockResolvedValue("ValidPass1"),
|
|
69
|
-
}));
|
|
70
|
-
await expect(signup()).rejects.toThrow("Rate limited");
|
|
71
|
-
vi.unstubAllGlobals();
|
|
72
|
-
});
|
|
73
|
-
it("handles network failure", async () => {
|
|
74
|
-
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new TypeError("fetch failed")));
|
|
75
|
-
const { signup } = await import("../steps/signup.js");
|
|
76
|
-
vi.mock("@inquirer/prompts", () => ({
|
|
77
|
-
input: vi.fn().mockResolvedValue("user@example.com"),
|
|
78
|
-
password: vi.fn().mockResolvedValue("ValidPass1"),
|
|
79
|
-
}));
|
|
80
|
-
await expect(signup()).rejects.toThrow("Can't reach");
|
|
81
|
-
vi.unstubAllGlobals();
|
|
82
|
-
});
|
|
83
|
-
});
|