sequant 1.0.0 → 1.1.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.
Files changed (50) hide show
  1. package/README.md +12 -8
  2. package/dist/src/commands/doctor.d.ts.map +1 -1
  3. package/dist/src/commands/doctor.js +70 -0
  4. package/dist/src/commands/doctor.js.map +1 -1
  5. package/dist/src/commands/doctor.test.d.ts +2 -0
  6. package/dist/src/commands/doctor.test.d.ts.map +1 -0
  7. package/dist/src/commands/doctor.test.js +209 -0
  8. package/dist/src/commands/doctor.test.js.map +1 -0
  9. package/dist/src/commands/init.d.ts.map +1 -1
  10. package/dist/src/commands/init.js +69 -2
  11. package/dist/src/commands/init.js.map +1 -1
  12. package/dist/src/commands/init.test.d.ts +2 -0
  13. package/dist/src/commands/init.test.d.ts.map +1 -0
  14. package/dist/src/commands/init.test.js +195 -0
  15. package/dist/src/commands/init.test.js.map +1 -0
  16. package/dist/src/lib/stacks.d.ts.map +1 -1
  17. package/dist/src/lib/stacks.js +39 -0
  18. package/dist/src/lib/stacks.js.map +1 -1
  19. package/dist/src/lib/stacks.test.d.ts +2 -0
  20. package/dist/src/lib/stacks.test.d.ts.map +1 -0
  21. package/dist/src/lib/stacks.test.js +145 -0
  22. package/dist/src/lib/stacks.test.js.map +1 -0
  23. package/package.json +4 -3
  24. package/stacks/astro.yaml +35 -0
  25. package/templates/hooks/post-tool.sh +0 -11
  26. package/templates/hooks/pre-tool.sh +2 -2
  27. package/templates/memory/constitution.md +8 -0
  28. package/templates/scripts/cleanup-worktree.sh +1 -1
  29. package/templates/scripts/new-feature.sh +7 -5
  30. package/templates/skills/assess/SKILL.md +16 -16
  31. package/templates/skills/clean/SKILL.md +2 -2
  32. package/templates/skills/docs/SKILL.md +32 -34
  33. package/templates/skills/exec/SKILL.md +17 -25
  34. package/templates/skills/fullsolve/SKILL.md +18 -16
  35. package/templates/skills/loop/SKILL.md +8 -5
  36. package/templates/skills/qa/SKILL.md +22 -4
  37. package/templates/skills/qa/references/code-quality-exemplars.md +23 -28
  38. package/templates/skills/qa/references/code-review-checklist.md +6 -17
  39. package/templates/skills/qa/scripts/quality-checks.sh +4 -17
  40. package/templates/skills/reflect/SKILL.md +4 -2
  41. package/templates/skills/reflect/references/documentation-tiers.md +3 -3
  42. package/templates/skills/security-review/references/security-checklists.md +10 -8
  43. package/templates/skills/solve/SKILL.md +109 -155
  44. package/templates/skills/spec/SKILL.md +2 -3
  45. package/templates/skills/spec/references/parallel-groups.md +1 -1
  46. package/templates/skills/spec/references/verification-criteria.md +1 -1
  47. package/templates/skills/test/SKILL.md +6 -5
  48. package/templates/skills/testgen/SKILL.md +0 -1
  49. package/templates/skills/verify/SKILL.md +5 -5
  50. package/templates/skills/reflect/scripts/workflow-queries.ts +0 -165
@@ -0,0 +1,195 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { execSync } from "child_process";
3
+ // Mock child_process
4
+ vi.mock("child_process", () => ({
5
+ execSync: vi.fn(),
6
+ }));
7
+ // Mock fs functions
8
+ vi.mock("../lib/fs.js", () => ({
9
+ fileExists: vi.fn(),
10
+ ensureDir: vi.fn(),
11
+ }));
12
+ // Mock stacks
13
+ vi.mock("../lib/stacks.js", () => ({
14
+ detectStack: vi.fn(),
15
+ }));
16
+ // Mock templates
17
+ vi.mock("../lib/templates.js", () => ({
18
+ copyTemplates: vi.fn(),
19
+ }));
20
+ // Mock manifest
21
+ vi.mock("../lib/manifest.js", () => ({
22
+ createManifest: vi.fn(),
23
+ }));
24
+ // Mock inquirer
25
+ vi.mock("inquirer", () => ({
26
+ default: {
27
+ prompt: vi.fn(),
28
+ },
29
+ }));
30
+ import { initCommand } from "./init.js";
31
+ import { fileExists, ensureDir } from "../lib/fs.js";
32
+ import { detectStack } from "../lib/stacks.js";
33
+ import { copyTemplates } from "../lib/templates.js";
34
+ import { createManifest } from "../lib/manifest.js";
35
+ const mockExecSync = vi.mocked(execSync);
36
+ const mockFileExists = vi.mocked(fileExists);
37
+ const mockEnsureDir = vi.mocked(ensureDir);
38
+ const mockDetectStack = vi.mocked(detectStack);
39
+ const mockCopyTemplates = vi.mocked(copyTemplates);
40
+ const mockCreateManifest = vi.mocked(createManifest);
41
+ describe("init command", () => {
42
+ let consoleLogSpy;
43
+ beforeEach(() => {
44
+ vi.resetAllMocks();
45
+ consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => { });
46
+ // Default: not initialized, all commands work
47
+ mockFileExists.mockResolvedValue(false);
48
+ mockEnsureDir.mockResolvedValue(undefined);
49
+ mockDetectStack.mockResolvedValue(null);
50
+ mockCopyTemplates.mockResolvedValue(undefined);
51
+ mockCreateManifest.mockResolvedValue(undefined);
52
+ mockExecSync.mockImplementation(() => Buffer.from(""));
53
+ });
54
+ afterEach(() => {
55
+ consoleLogSpy.mockRestore();
56
+ });
57
+ describe("prerequisite checks", () => {
58
+ it("shows no warnings when all prerequisites are met", async () => {
59
+ mockExecSync.mockImplementation((cmd) => {
60
+ if (cmd === "command -v gh")
61
+ return Buffer.from("/usr/local/bin/gh");
62
+ if (cmd === "gh auth status")
63
+ return Buffer.from("");
64
+ if (cmd === "command -v jq")
65
+ return Buffer.from("/usr/local/bin/jq");
66
+ return Buffer.from("");
67
+ });
68
+ await initCommand({ yes: true, stack: "generic" });
69
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
70
+ expect(output).not.toContain("Prerequisites:");
71
+ expect(output).not.toContain("GitHub CLI (gh) is not installed");
72
+ expect(output).not.toContain("GitHub CLI is not authenticated");
73
+ expect(output).toContain("Sequant initialized successfully");
74
+ });
75
+ it("warns when gh CLI is not installed", async () => {
76
+ mockExecSync.mockImplementation((cmd) => {
77
+ if (cmd === "command -v gh") {
78
+ throw new Error("command not found");
79
+ }
80
+ if (cmd === "command -v jq")
81
+ return Buffer.from("/usr/local/bin/jq");
82
+ return Buffer.from("");
83
+ });
84
+ await initCommand({ yes: true, stack: "generic" });
85
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
86
+ expect(output).toContain("Prerequisites:");
87
+ expect(output).toContain("GitHub CLI (gh) is not installed");
88
+ expect(output).toContain("https://cli.github.com");
89
+ expect(output).toContain("Remember to address prerequisites");
90
+ });
91
+ it("warns when gh CLI is not authenticated", async () => {
92
+ mockExecSync.mockImplementation((cmd) => {
93
+ if (cmd === "command -v gh")
94
+ return Buffer.from("/usr/local/bin/gh");
95
+ if (cmd === "gh auth status") {
96
+ throw new Error("not authenticated");
97
+ }
98
+ if (cmd === "command -v jq")
99
+ return Buffer.from("/usr/local/bin/jq");
100
+ return Buffer.from("");
101
+ });
102
+ await initCommand({ yes: true, stack: "generic" });
103
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
104
+ expect(output).toContain("Prerequisites:");
105
+ expect(output).toContain("GitHub CLI is not authenticated");
106
+ expect(output).toContain("gh auth login");
107
+ expect(output).toContain("Remember to address prerequisites");
108
+ });
109
+ it("shows optional jq suggestion when jq is not installed", async () => {
110
+ mockExecSync.mockImplementation((cmd) => {
111
+ if (cmd === "command -v gh")
112
+ return Buffer.from("/usr/local/bin/gh");
113
+ if (cmd === "gh auth status")
114
+ return Buffer.from("");
115
+ if (cmd === "command -v jq") {
116
+ throw new Error("command not found");
117
+ }
118
+ return Buffer.from("");
119
+ });
120
+ await initCommand({ yes: true, stack: "generic" });
121
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
122
+ expect(output).toContain("Optional improvements:");
123
+ expect(output).toContain("Install jq for faster JSON parsing");
124
+ // Should NOT show prerequisites warning since jq is optional
125
+ expect(output).not.toContain("Prerequisites:");
126
+ });
127
+ it("shows both gh warning and jq suggestion when both are missing", async () => {
128
+ mockExecSync.mockImplementation((cmd) => {
129
+ if (cmd === "command -v gh") {
130
+ throw new Error("command not found");
131
+ }
132
+ if (cmd === "command -v jq") {
133
+ throw new Error("command not found");
134
+ }
135
+ return Buffer.from("");
136
+ });
137
+ await initCommand({ yes: true, stack: "generic" });
138
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
139
+ expect(output).toContain("Prerequisites:");
140
+ expect(output).toContain("GitHub CLI (gh) is not installed");
141
+ expect(output).toContain("Optional improvements:");
142
+ expect(output).toContain("Install jq for faster JSON parsing");
143
+ });
144
+ it("skips auth check when gh is not installed", async () => {
145
+ mockExecSync.mockImplementation((cmd) => {
146
+ if (cmd === "command -v gh") {
147
+ throw new Error("command not found");
148
+ }
149
+ if (cmd === "gh auth status") {
150
+ throw new Error("should not be called");
151
+ }
152
+ if (cmd === "command -v jq")
153
+ return Buffer.from("/usr/local/bin/jq");
154
+ return Buffer.from("");
155
+ });
156
+ await initCommand({ yes: true, stack: "generic" });
157
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
158
+ // Should only show "not installed", not "not authenticated"
159
+ expect(output).toContain("GitHub CLI (gh) is not installed");
160
+ expect(output).not.toContain("GitHub CLI is not authenticated");
161
+ });
162
+ });
163
+ describe("initialization flow", () => {
164
+ it("completes successfully with --yes and --stack flags", async () => {
165
+ mockExecSync.mockImplementation((cmd) => {
166
+ if (cmd === "command -v gh")
167
+ return Buffer.from("/usr/local/bin/gh");
168
+ if (cmd === "gh auth status")
169
+ return Buffer.from("");
170
+ if (cmd === "command -v jq")
171
+ return Buffer.from("/usr/local/bin/jq");
172
+ return Buffer.from("");
173
+ });
174
+ await initCommand({ yes: true, stack: "nextjs" });
175
+ expect(mockEnsureDir).toHaveBeenCalledWith(".claude/skills");
176
+ expect(mockEnsureDir).toHaveBeenCalledWith(".claude/hooks");
177
+ expect(mockEnsureDir).toHaveBeenCalledWith(".claude/memory");
178
+ expect(mockEnsureDir).toHaveBeenCalledWith("scripts/dev");
179
+ expect(mockCopyTemplates).toHaveBeenCalledWith("nextjs");
180
+ expect(mockCreateManifest).toHaveBeenCalledWith("nextjs");
181
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
182
+ expect(output).toContain("Sequant initialized successfully");
183
+ });
184
+ it("warns but continues when already initialized without --force", async () => {
185
+ mockFileExists.mockImplementation(async (path) => {
186
+ return path === ".claude/settings.json";
187
+ });
188
+ mockExecSync.mockImplementation(() => Buffer.from(""));
189
+ await initCommand({ yes: true, stack: "generic" });
190
+ const output = consoleLogSpy.mock.calls.map((c) => c[0]).join("\n");
191
+ expect(output).toContain("already initialized");
192
+ });
193
+ });
194
+ });
195
+ //# sourceMappingURL=init.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../../src/commands/init.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stacks.d.ts","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAsF9C,CAAC;AAEF,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuC1D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAEzD"}
1
+ {"version":3,"file":"stacks.d.ts","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CA0G9C,CAAC;AAEF,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2D1D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAEzD"}
@@ -73,6 +73,26 @@ export const STACKS = {
73
73
  LINT_COMMAND: "golangci-lint run",
74
74
  },
75
75
  },
76
+ astro: {
77
+ name: "astro",
78
+ displayName: "Astro",
79
+ detection: {
80
+ files: ["astro.config.mjs", "astro.config.js", "astro.config.ts"],
81
+ packageDeps: ["astro"],
82
+ },
83
+ commands: {
84
+ // Note: Astro projects may not have test/lint configured by default
85
+ test: "npm test",
86
+ build: "npm run build",
87
+ lint: "npm run lint",
88
+ dev: "npm run dev",
89
+ },
90
+ variables: {
91
+ TEST_COMMAND: "npm test",
92
+ BUILD_COMMAND: "npm run build",
93
+ LINT_COMMAND: "npm run lint",
94
+ },
95
+ },
76
96
  generic: {
77
97
  name: "generic",
78
98
  displayName: "Generic",
@@ -109,6 +129,25 @@ export async function detectStack() {
109
129
  // Ignore parse errors
110
130
  }
111
131
  }
132
+ // Check for Astro
133
+ for (const file of STACKS.astro.detection.files || []) {
134
+ if (await fileExists(file)) {
135
+ return "astro";
136
+ }
137
+ }
138
+ // Check package.json for Astro dependency
139
+ if (await fileExists("package.json")) {
140
+ try {
141
+ const pkg = JSON.parse(await readFile("package.json"));
142
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
143
+ if (deps.astro) {
144
+ return "astro";
145
+ }
146
+ }
147
+ catch {
148
+ // Ignore parse errors
149
+ }
150
+ }
112
151
  // Check for Rust
113
152
  if (await fileExists("Cargo.toml")) {
114
153
  return "rust";
@@ -1 +1 @@
1
- {"version":3,"file":"stacks.js","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stacks.js","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stacks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stacks.test.d.ts","sourceRoot":"","sources":["../../../src/lib/stacks.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,145 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { detectStack, getStackConfig, STACKS } from "./stacks.js";
3
+ // Mock the fs module
4
+ vi.mock("./fs.js", () => ({
5
+ fileExists: vi.fn(),
6
+ readFile: vi.fn(),
7
+ }));
8
+ import { fileExists, readFile } from "./fs.js";
9
+ const mockFileExists = vi.mocked(fileExists);
10
+ const mockReadFile = vi.mocked(readFile);
11
+ describe("STACKS", () => {
12
+ describe("astro config", () => {
13
+ it("has correct detection files", () => {
14
+ expect(STACKS.astro.detection.files).toEqual([
15
+ "astro.config.mjs",
16
+ "astro.config.js",
17
+ "astro.config.ts",
18
+ ]);
19
+ });
20
+ it("has astro in packageDeps", () => {
21
+ expect(STACKS.astro.detection.packageDeps).toContain("astro");
22
+ });
23
+ it("has correct commands", () => {
24
+ expect(STACKS.astro.commands.build).toBe("npm run build");
25
+ expect(STACKS.astro.commands.dev).toBe("npm run dev");
26
+ expect(STACKS.astro.commands.test).toBe("npm test");
27
+ expect(STACKS.astro.commands.lint).toBe("npm run lint");
28
+ });
29
+ });
30
+ });
31
+ describe("detectStack", () => {
32
+ beforeEach(() => {
33
+ vi.resetAllMocks();
34
+ mockFileExists.mockResolvedValue(false);
35
+ mockReadFile.mockResolvedValue("{}");
36
+ });
37
+ describe("Astro detection", () => {
38
+ it("detects astro.config.mjs", async () => {
39
+ mockFileExists.mockImplementation(async (path) => {
40
+ return path === "astro.config.mjs";
41
+ });
42
+ const result = await detectStack();
43
+ expect(result).toBe("astro");
44
+ });
45
+ it("detects astro.config.js", async () => {
46
+ mockFileExists.mockImplementation(async (path) => {
47
+ return path === "astro.config.js";
48
+ });
49
+ const result = await detectStack();
50
+ expect(result).toBe("astro");
51
+ });
52
+ it("detects astro.config.ts", async () => {
53
+ mockFileExists.mockImplementation(async (path) => {
54
+ return path === "astro.config.ts";
55
+ });
56
+ const result = await detectStack();
57
+ expect(result).toBe("astro");
58
+ });
59
+ it("detects astro in dependencies via package.json", async () => {
60
+ mockFileExists.mockImplementation(async (path) => {
61
+ return path === "package.json";
62
+ });
63
+ mockReadFile.mockResolvedValue(JSON.stringify({
64
+ dependencies: { astro: "^4.0.0" },
65
+ }));
66
+ const result = await detectStack();
67
+ expect(result).toBe("astro");
68
+ });
69
+ it("detects astro in devDependencies via package.json", async () => {
70
+ mockFileExists.mockImplementation(async (path) => {
71
+ return path === "package.json";
72
+ });
73
+ mockReadFile.mockResolvedValue(JSON.stringify({
74
+ devDependencies: { astro: "^4.0.0" },
75
+ }));
76
+ const result = await detectStack();
77
+ expect(result).toBe("astro");
78
+ });
79
+ });
80
+ describe("priority", () => {
81
+ it("Next.js takes priority over Astro when both present", async () => {
82
+ mockFileExists.mockImplementation(async (path) => {
83
+ return path === "next.config.js" || path === "astro.config.mjs";
84
+ });
85
+ const result = await detectStack();
86
+ expect(result).toBe("nextjs");
87
+ });
88
+ it("Next.js dep takes priority over Astro dep", async () => {
89
+ mockFileExists.mockImplementation(async (path) => {
90
+ return path === "package.json";
91
+ });
92
+ mockReadFile.mockResolvedValue(JSON.stringify({
93
+ dependencies: { next: "^14.0.0", astro: "^4.0.0" },
94
+ }));
95
+ const result = await detectStack();
96
+ expect(result).toBe("nextjs");
97
+ });
98
+ it("Astro config file takes priority over Rust", async () => {
99
+ mockFileExists.mockImplementation(async (path) => {
100
+ return path === "astro.config.mjs" || path === "Cargo.toml";
101
+ });
102
+ const result = await detectStack();
103
+ expect(result).toBe("astro");
104
+ });
105
+ });
106
+ describe("edge cases", () => {
107
+ it("returns null when no stack detected", async () => {
108
+ mockFileExists.mockResolvedValue(false);
109
+ const result = await detectStack();
110
+ expect(result).toBeNull();
111
+ });
112
+ it("handles malformed package.json gracefully", async () => {
113
+ mockFileExists.mockImplementation(async (path) => {
114
+ return path === "package.json";
115
+ });
116
+ mockReadFile.mockResolvedValue("{ invalid json }");
117
+ const result = await detectStack();
118
+ expect(result).toBeNull();
119
+ });
120
+ it("handles empty package.json", async () => {
121
+ mockFileExists.mockImplementation(async (path) => {
122
+ return path === "package.json";
123
+ });
124
+ mockReadFile.mockResolvedValue("{}");
125
+ const result = await detectStack();
126
+ expect(result).toBeNull();
127
+ });
128
+ });
129
+ });
130
+ describe("getStackConfig", () => {
131
+ it("returns astro config for astro stack", () => {
132
+ const config = getStackConfig("astro");
133
+ expect(config.name).toBe("astro");
134
+ expect(config.displayName).toBe("Astro");
135
+ });
136
+ it("returns generic config for unknown stack", () => {
137
+ const config = getStackConfig("unknown-stack");
138
+ expect(config.name).toBe("generic");
139
+ });
140
+ it("returns generic config for empty string", () => {
141
+ const config = getStackConfig("");
142
+ expect(config.name).toBe("generic");
143
+ });
144
+ });
145
+ //# sourceMappingURL=stacks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stacks.test.js","sourceRoot":"","sources":["../../../src/lib/stacks.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sequant",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Quantize your development workflow - Sequential AI phases with quality gates",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "build": "tsc",
24
24
  "dev": "tsx bin/cli.ts",
25
- "test": "echo \"No tests yet\" && exit 0",
25
+ "test": "vitest run",
26
26
  "lint": "echo \"No linter configured yet\" && exit 0",
27
27
  "validate:skills": "for skill in templates/skills/*/; do npx skills-ref validate \"$skill\"; done",
28
28
  "prepublishOnly": "npm run build"
@@ -64,6 +64,7 @@
64
64
  "@types/inquirer": "^9.0.7",
65
65
  "@types/node": "^22.10.5",
66
66
  "tsx": "^4.19.2",
67
- "typescript": "^5.7.2"
67
+ "typescript": "^5.7.2",
68
+ "vitest": "^3.2.4"
68
69
  }
69
70
  }
@@ -0,0 +1,35 @@
1
+ name: astro
2
+ displayName: Astro
3
+ description: The web framework for content-driven websites
4
+
5
+ detection:
6
+ files:
7
+ - astro.config.mjs
8
+ - astro.config.js
9
+ - astro.config.ts
10
+ packageDeps:
11
+ - astro
12
+
13
+ commands:
14
+ test: npm test
15
+ build: npm run build
16
+ lint: npm run lint
17
+ dev: npm run dev
18
+
19
+ variables:
20
+ TEST_COMMAND: npm test
21
+ BUILD_COMMAND: npm run build
22
+ LINT_COMMAND: npm run lint
23
+
24
+ patterns:
25
+ pages: src/pages/**/*.astro
26
+ components: src/components/**/*.astro
27
+ layouts: src/layouts/**/*.astro
28
+ content: src/content/**/*.{md,mdx}
29
+
30
+ notes: |
31
+ Astro projects may not have test or lint scripts by default.
32
+ Recommended setup:
33
+ - Testing: npm install -D vitest
34
+ - Linting: npm install -D eslint eslint-plugin-astro
35
+ Build output defaults to dist/
@@ -180,17 +180,6 @@ elif [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
180
180
  fi
181
181
  fi
182
182
 
183
- # === LOG SUPABASE QUERIES ===
184
- if [[ "$TOOL_NAME" == "mcp__supabase__execute_sql" ]]; then
185
- # Extract SQL query with jq or fallback
186
- if command -v jq &>/dev/null; then
187
- QUERY=$(echo "$TOOL_INPUT" | jq -r '.query // empty' 2>/dev/null | head -c 200)
188
- else
189
- QUERY=$(echo "$TOOL_INPUT" | head -c 200)
190
- fi
191
- echo "$(date +%H:%M:%S) SQL: $QUERY" >> "$QUALITY_LOG"
192
- fi
193
-
194
183
  # === TRACK GIT OPERATIONS ===
195
184
  if [[ "$TOOL_NAME" == "Bash" ]]; then
196
185
  if echo "$TOOL_INPUT" | grep -qE 'git (commit|push|pr create)'; then
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
  # Pre-tool hook for Claude Code
3
- # - Security guardrails for execute-issues.ts (blocks catastrophic commands)
3
+ # - Security guardrails (blocks catastrophic commands)
4
4
  # - Timing instrumentation for performance analysis
5
5
  # Exit 0 = allow, Exit 2 = block (Exit 1 = non-blocking error, logged but not blocked)
6
6
 
@@ -346,5 +346,5 @@ if [[ "${CLAUDE_HOOKS_FILE_LOCKING:-true}" == "true" ]]; then
346
346
  fi
347
347
 
348
348
  # === ALLOW EVERYTHING ELSE ===
349
- # Slash commands need: git, npm, file edits, gh pr/issue, supabase queries
349
+ # Slash commands need: git, npm, file edits, gh pr/issue, MCP tools
350
350
  exit 0
@@ -54,6 +54,14 @@ This document defines the core principles and patterns for AI-assisted developme
54
54
  | `/loop` | Fix iteration when tests fail |
55
55
  | `/docs` | Generate feature documentation |
56
56
 
57
+ ## Stack-Specific Notes
58
+
59
+ ### Astro Projects
60
+ - Astro projects may not have `test` or `lint` scripts configured by default
61
+ - If tests are needed, consider adding Vitest (`npm install -D vitest`)
62
+ - For linting, consider ESLint with the Astro plugin (`npm install -D eslint eslint-plugin-astro`)
63
+ - Build output goes to `dist/` by default
64
+
57
65
  ## Project-Specific Notes
58
66
 
59
67
  <!-- Add your project-specific guidelines below -->
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Clean up a worktree after PR is merged
4
4
  # Usage: ./scripts/cleanup-worktree.sh <branch-name>
5
- # Example: ./scripts/cleanup-worktree.sh feature/4-build-shop-detail-pages
5
+ # Example: ./scripts/cleanup-worktree.sh feature/123-add-user-dashboard
6
6
 
7
7
  set -e
8
8
 
@@ -121,11 +121,13 @@ git worktree add "$WORKTREE_DIR" -b "$BRANCH_NAME"
121
121
  # Navigate to worktree
122
122
  cd "$WORKTREE_DIR"
123
123
 
124
- # Copy .env.local if it exists (use absolute path from main repo)
125
- if [ -f "${MAIN_REPO_DIR}/.env.local" ]; then
126
- echo -e "${BLUE}📋 Copying .env.local...${NC}"
127
- cp "${MAIN_REPO_DIR}/.env.local" .env.local
128
- fi
124
+ # Copy environment files if they exist (use absolute path from main repo)
125
+ for ENV_FILE in .env .env.local .env.development; do
126
+ if [ -f "${MAIN_REPO_DIR}/${ENV_FILE}" ]; then
127
+ echo -e "${BLUE}📋 Copying ${ENV_FILE}...${NC}"
128
+ cp "${MAIN_REPO_DIR}/${ENV_FILE}" "${ENV_FILE}"
129
+ fi
130
+ done
129
131
 
130
132
  # Copy .claude/settings.local.json for auto-approved permissions
131
133
  if [ -f "${MAIN_REPO_DIR}/.claude/settings.local.json" ]; then