haki-skills 0.2.1 → 0.2.2

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 (54) hide show
  1. package/.agent/bin/haki-tools.cjs +130 -130
  2. package/.agent/bin/lib/config.cjs +170 -170
  3. package/.agent/bin/lib/core.cjs +203 -203
  4. package/.agent/bin/lib/roadmap.cjs +266 -266
  5. package/.agent/bin/lib/state.cjs +187 -187
  6. package/.agent/references/questioning.md +95 -95
  7. package/.agent/references/ui-brand.md +50 -50
  8. package/.agent/skills/api-testing/SKILL.md +422 -422
  9. package/.agent/skills/api-testing/templates/api-client.ts +84 -84
  10. package/.agent/skills/api-testing/templates/example.api.test.ts +106 -106
  11. package/.agent/skills/api-testing/templates/seed-data.json +20 -20
  12. package/.agent/skills/api-testing/templates/vitest.api.config.ts +39 -39
  13. package/.agent/skills/context7-research/SKILL.md +141 -141
  14. package/.agent/skills/playwright-automation/SKILL.md +382 -382
  15. package/.agent/skills/playwright-automation/templates/base.fixture.ts +33 -33
  16. package/.agent/skills/playwright-automation/templates/example.page.ts +45 -45
  17. package/.agent/skills/playwright-automation/templates/example.spec.ts +43 -43
  18. package/.agent/skills/playwright-automation/templates/playwright.config.ts +71 -71
  19. package/.agent/skills/ui-ux-pro-max/SKILL.md +45 -45
  20. package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -26
  21. package/.agent/skills/ui-ux-pro-max/data/colors.csv +161 -161
  22. package/.agent/skills/ui-ux-pro-max/data/google-fonts.csv +1924 -1924
  23. package/.agent/skills/ui-ux-pro-max/data/landing.csv +35 -35
  24. package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  25. package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -68
  26. package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +162 -162
  27. package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
  28. package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -114
  29. package/.agent/skills/user-docs-generator/SKILL.md +123 -123
  30. package/.agent/templates/agents.md +46 -46
  31. package/.agent/templates/claude.md +13 -13
  32. package/.agent/templates/config.json +15 -15
  33. package/.agent/templates/cursor-haki.mdc +17 -17
  34. package/.agent/templates/project.md +27 -27
  35. package/.agent/templates/roadmap.md +22 -22
  36. package/.agent/templates/task.md +94 -94
  37. package/.agent/templates/user-docs-index.md +9 -9
  38. package/.agent/templates/user-docs-module.md +59 -59
  39. package/.agent/workflows/haki-api-test.md +175 -175
  40. package/.agent/workflows/haki-discuss.md +61 -61
  41. package/.agent/workflows/haki-docs.md +80 -80
  42. package/.agent/workflows/haki-e2e-gen.md +82 -82
  43. package/.agent/workflows/haki-e2e.md +181 -181
  44. package/.agent/workflows/haki-exec.md +77 -77
  45. package/.agent/workflows/haki-init.md +36 -36
  46. package/.agent/workflows/haki-map-codebase.md +30 -30
  47. package/.agent/workflows/haki-new-milestone.md +73 -73
  48. package/.agent/workflows/haki-new-project.md +69 -69
  49. package/.agent/workflows/haki-next.md +63 -63
  50. package/.agent/workflows/haki-plan.md +58 -58
  51. package/.agent/workflows/haki-research.md +93 -93
  52. package/README.md +169 -169
  53. package/bin/install.js +304 -239
  54. package/package.json +43 -43
@@ -1,130 +1,130 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Haki Tools — CLI utility for haki workflow operations
5
- *
6
- * Lean CLI inspired by gsd-tools.cjs but focused on 4 core concerns:
7
- * - config: .haki/config.json CRUD
8
- * - roadmap: ROADMAP.md parsing and status updates
9
- * - state: Project state detection for /haki:next routing
10
- * - core: Shared path resolution and utilities
11
- *
12
- * Usage:
13
- * node haki-tools.cjs <command> [args]
14
- *
15
- * Config Operations:
16
- * config init [choices-json] Initialize config.json
17
- * config get <key.path> Get config value
18
- * config set <key.path> <value> Set config value
19
- *
20
- * Roadmap Operations:
21
- * roadmap analyze Full roadmap parse with stats
22
- * roadmap next-task Find next actionable task
23
- * roadmap update-status <id> <status> Update task status
24
- *
25
- * State Operations:
26
- * state detect Full state detection (JSON)
27
- * state json Compact state for /haki:next
28
- */
29
-
30
- const fs = require("fs");
31
- const path = require("path");
32
- const { findProjectRoot, error, output } = require("./lib/core.cjs");
33
- const {
34
- cmdConfigInit,
35
- cmdConfigGet,
36
- cmdConfigSet,
37
- } = require("./lib/config.cjs");
38
- const {
39
- cmdRoadmapAnalyze,
40
- cmdRoadmapNextTask,
41
- cmdRoadmapUpdateStatus,
42
- } = require("./lib/roadmap.cjs");
43
- const { cmdStateDetect, cmdStateJson } = require("./lib/state.cjs");
44
-
45
- function main() {
46
- const args = process.argv.slice(2);
47
- const raw = args.includes("--raw");
48
- const filteredArgs = args.filter((a) => a !== "--raw");
49
-
50
- if (filteredArgs.length === 0) {
51
- error(
52
- "Usage: haki-tools <command> [args]\n\nCommands:\n config init|get|set\n roadmap analyze|next-task|update-status\n state detect|json",
53
- );
54
- }
55
-
56
- const cwd = findProjectRoot(process.cwd());
57
- const command = filteredArgs[0];
58
- const subCommand = filteredArgs[1];
59
- const restArgs = filteredArgs.slice(2);
60
-
61
- switch (command) {
62
- // ─── Config ────────────────────────────────────────────────────────
63
- case "config":
64
- case "config-init":
65
- case "config-get":
66
- case "config-set": {
67
- const sub = command === "config" ? subCommand : command.split("-")[1];
68
-
69
- switch (sub) {
70
- case "init":
71
- cmdConfigInit(cwd, restArgs[0] || filteredArgs[2], raw);
72
- break;
73
- case "get":
74
- cmdConfigGet(cwd, restArgs[0] || filteredArgs[2], raw);
75
- break;
76
- case "set":
77
- cmdConfigSet(
78
- cwd,
79
- restArgs[0] || filteredArgs[2],
80
- restArgs[1] || filteredArgs[3],
81
- raw,
82
- );
83
- break;
84
- default:
85
- error("Usage: config <init|get|set> [args]");
86
- }
87
- break;
88
- }
89
-
90
- // ─── Roadmap ──────────────────────────────────────────────────────
91
- case "roadmap": {
92
- switch (subCommand) {
93
- case "analyze":
94
- cmdRoadmapAnalyze(cwd, raw);
95
- break;
96
- case "next-task":
97
- cmdRoadmapNextTask(cwd, raw);
98
- break;
99
- case "update-status":
100
- cmdRoadmapUpdateStatus(cwd, restArgs[0], restArgs[1], raw);
101
- break;
102
- default:
103
- error("Usage: roadmap <analyze|next-task|update-status> [args]");
104
- }
105
- break;
106
- }
107
-
108
- // ─── State ────────────────────────────────────────────────────────
109
- case "state": {
110
- switch (subCommand) {
111
- case "detect":
112
- cmdStateDetect(cwd, raw);
113
- break;
114
- case "json":
115
- cmdStateJson(cwd, raw);
116
- break;
117
- default:
118
- error("Usage: state <detect|json>");
119
- }
120
- break;
121
- }
122
-
123
- default:
124
- error(
125
- `Unknown command: ${command}\n\nValid commands: config, roadmap, state`,
126
- );
127
- }
128
- }
129
-
130
- main();
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Haki Tools — CLI utility for haki workflow operations
5
+ *
6
+ * Lean CLI inspired by gsd-tools.cjs but focused on 4 core concerns:
7
+ * - config: .haki/config.json CRUD
8
+ * - roadmap: ROADMAP.md parsing and status updates
9
+ * - state: Project state detection for /haki:next routing
10
+ * - core: Shared path resolution and utilities
11
+ *
12
+ * Usage:
13
+ * node haki-tools.cjs <command> [args]
14
+ *
15
+ * Config Operations:
16
+ * config init [choices-json] Initialize config.json
17
+ * config get <key.path> Get config value
18
+ * config set <key.path> <value> Set config value
19
+ *
20
+ * Roadmap Operations:
21
+ * roadmap analyze Full roadmap parse with stats
22
+ * roadmap next-task Find next actionable task
23
+ * roadmap update-status <id> <status> Update task status
24
+ *
25
+ * State Operations:
26
+ * state detect Full state detection (JSON)
27
+ * state json Compact state for /haki:next
28
+ */
29
+
30
+ const fs = require("fs");
31
+ const path = require("path");
32
+ const { findProjectRoot, error, output } = require("./lib/core.cjs");
33
+ const {
34
+ cmdConfigInit,
35
+ cmdConfigGet,
36
+ cmdConfigSet,
37
+ } = require("./lib/config.cjs");
38
+ const {
39
+ cmdRoadmapAnalyze,
40
+ cmdRoadmapNextTask,
41
+ cmdRoadmapUpdateStatus,
42
+ } = require("./lib/roadmap.cjs");
43
+ const { cmdStateDetect, cmdStateJson } = require("./lib/state.cjs");
44
+
45
+ function main() {
46
+ const args = process.argv.slice(2);
47
+ const raw = args.includes("--raw");
48
+ const filteredArgs = args.filter((a) => a !== "--raw");
49
+
50
+ if (filteredArgs.length === 0) {
51
+ error(
52
+ "Usage: haki-tools <command> [args]\n\nCommands:\n config init|get|set\n roadmap analyze|next-task|update-status\n state detect|json",
53
+ );
54
+ }
55
+
56
+ const cwd = findProjectRoot(process.cwd());
57
+ const command = filteredArgs[0];
58
+ const subCommand = filteredArgs[1];
59
+ const restArgs = filteredArgs.slice(2);
60
+
61
+ switch (command) {
62
+ // ─── Config ────────────────────────────────────────────────────────
63
+ case "config":
64
+ case "config-init":
65
+ case "config-get":
66
+ case "config-set": {
67
+ const sub = command === "config" ? subCommand : command.split("-")[1];
68
+
69
+ switch (sub) {
70
+ case "init":
71
+ cmdConfigInit(cwd, restArgs[0] || filteredArgs[2], raw);
72
+ break;
73
+ case "get":
74
+ cmdConfigGet(cwd, restArgs[0] || filteredArgs[2], raw);
75
+ break;
76
+ case "set":
77
+ cmdConfigSet(
78
+ cwd,
79
+ restArgs[0] || filteredArgs[2],
80
+ restArgs[1] || filteredArgs[3],
81
+ raw,
82
+ );
83
+ break;
84
+ default:
85
+ error("Usage: config <init|get|set> [args]");
86
+ }
87
+ break;
88
+ }
89
+
90
+ // ─── Roadmap ──────────────────────────────────────────────────────
91
+ case "roadmap": {
92
+ switch (subCommand) {
93
+ case "analyze":
94
+ cmdRoadmapAnalyze(cwd, raw);
95
+ break;
96
+ case "next-task":
97
+ cmdRoadmapNextTask(cwd, raw);
98
+ break;
99
+ case "update-status":
100
+ cmdRoadmapUpdateStatus(cwd, restArgs[0], restArgs[1], raw);
101
+ break;
102
+ default:
103
+ error("Usage: roadmap <analyze|next-task|update-status> [args]");
104
+ }
105
+ break;
106
+ }
107
+
108
+ // ─── State ────────────────────────────────────────────────────────
109
+ case "state": {
110
+ switch (subCommand) {
111
+ case "detect":
112
+ cmdStateDetect(cwd, raw);
113
+ break;
114
+ case "json":
115
+ cmdStateJson(cwd, raw);
116
+ break;
117
+ default:
118
+ error("Usage: state <detect|json>");
119
+ }
120
+ break;
121
+ }
122
+
123
+ default:
124
+ error(
125
+ `Unknown command: ${command}\n\nValid commands: config, roadmap, state`,
126
+ );
127
+ }
128
+ }
129
+
130
+ main();
@@ -1,170 +1,170 @@
1
- /**
2
- * Config — .haki/config.json CRUD operations
3
- */
4
-
5
- const fs = require("fs");
6
- const path = require("path");
7
- const { output, error, hakiPaths, ensureDir } = require("./core.cjs");
8
-
9
- const DEFAULT_CONFIG = {
10
- project: {
11
- name: "",
12
- created: "",
13
- },
14
- ui_design_skill: "ui-ux-pro-max",
15
- ui_design_variant: null,
16
- workflow: {
17
- auto_research: true,
18
- auto_commit: true,
19
- tdd_first: true,
20
- plan_review_loops: 3,
21
- parallelization: true,
22
- },
23
- };
24
-
25
- /**
26
- * Build a config for a new project, merging defaults with user choices.
27
- */
28
- function buildNewProjectConfig(userChoices = {}) {
29
- return {
30
- ...DEFAULT_CONFIG,
31
- ...userChoices,
32
- project: {
33
- ...DEFAULT_CONFIG.project,
34
- ...(userChoices.project || {}),
35
- created: userChoices.project?.created || new Date().toISOString(),
36
- },
37
- workflow: {
38
- ...DEFAULT_CONFIG.workflow,
39
- ...(userChoices.workflow || {}),
40
- },
41
- };
42
- }
43
-
44
- /**
45
- * Initialize config.json for a new project.
46
- * Idempotent: returns existing if already present.
47
- */
48
- function cmdConfigInit(cwd, choicesJson, raw) {
49
- const paths = hakiPaths(cwd);
50
- const configPath = paths.config;
51
-
52
- if (fs.existsSync(configPath)) {
53
- output({ created: false, reason: "already_exists" }, raw, "exists");
54
- return;
55
- }
56
-
57
- let userChoices = {};
58
- if (choicesJson && choicesJson.trim() !== "") {
59
- try {
60
- userChoices = JSON.parse(choicesJson);
61
- } catch (err) {
62
- error("Invalid JSON for config init: " + err.message);
63
- }
64
- }
65
-
66
- ensureDir(paths.haki);
67
- const config = buildNewProjectConfig(userChoices);
68
-
69
- try {
70
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
71
- output({ created: true, path: ".haki/config.json" }, raw, "created");
72
- } catch (err) {
73
- error("Failed to write config.json: " + err.message);
74
- }
75
- }
76
-
77
- /**
78
- * Get a config value using dot-notation path.
79
- */
80
- function cmdConfigGet(cwd, keyPath, raw) {
81
- const configPath = hakiPaths(cwd).config;
82
-
83
- if (!keyPath) error("Usage: config get <key.path>");
84
-
85
- let config = {};
86
- try {
87
- if (fs.existsSync(configPath)) {
88
- config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
89
- } else {
90
- error("No config.json found");
91
- }
92
- } catch (err) {
93
- if (err.message.startsWith("No config")) throw err;
94
- error("Failed to read config.json: " + err.message);
95
- }
96
-
97
- const keys = keyPath.split(".");
98
- let current = config;
99
- for (const key of keys) {
100
- if (
101
- current === undefined ||
102
- current === null ||
103
- typeof current !== "object"
104
- ) {
105
- error("Key not found: " + keyPath);
106
- }
107
- current = current[key];
108
- }
109
-
110
- if (current === undefined) error("Key not found: " + keyPath);
111
- output(current, raw, String(current));
112
- }
113
-
114
- /**
115
- * Set a config value using dot-notation path.
116
- */
117
- function cmdConfigSet(cwd, keyPath, value, raw) {
118
- if (!keyPath) error("Usage: config set <key.path> <value>");
119
-
120
- const configPath = hakiPaths(cwd).config;
121
-
122
- let config = {};
123
- try {
124
- if (fs.existsSync(configPath)) {
125
- config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
126
- }
127
- } catch (err) {
128
- error("Failed to read config.json: " + err.message);
129
- }
130
-
131
- // Parse value
132
- let parsedValue = value;
133
- if (value === "true") parsedValue = true;
134
- else if (value === "false") parsedValue = false;
135
- else if (value === "null") parsedValue = null;
136
- else if (!isNaN(value) && value !== "") parsedValue = Number(value);
137
-
138
- // Set nested value
139
- const keys = keyPath.split(".");
140
- let current = config;
141
- for (let i = 0; i < keys.length - 1; i++) {
142
- if (
143
- current[keys[i]] === undefined ||
144
- typeof current[keys[i]] !== "object"
145
- ) {
146
- current[keys[i]] = {};
147
- }
148
- current = current[keys[i]];
149
- }
150
- current[keys[keys.length - 1]] = parsedValue;
151
-
152
- try {
153
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
154
- output(
155
- { updated: true, key: keyPath, value: parsedValue },
156
- raw,
157
- `${keyPath}=${parsedValue}`,
158
- );
159
- } catch (err) {
160
- error("Failed to write config.json: " + err.message);
161
- }
162
- }
163
-
164
- module.exports = {
165
- DEFAULT_CONFIG,
166
- buildNewProjectConfig,
167
- cmdConfigInit,
168
- cmdConfigGet,
169
- cmdConfigSet,
170
- };
1
+ /**
2
+ * Config — .haki/config.json CRUD operations
3
+ */
4
+
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const { output, error, hakiPaths, ensureDir } = require("./core.cjs");
8
+
9
+ const DEFAULT_CONFIG = {
10
+ project: {
11
+ name: "",
12
+ created: "",
13
+ },
14
+ ui_design_skill: "ui-ux-pro-max",
15
+ ui_design_variant: null,
16
+ workflow: {
17
+ auto_research: true,
18
+ auto_commit: true,
19
+ tdd_first: true,
20
+ plan_review_loops: 3,
21
+ parallelization: true,
22
+ },
23
+ };
24
+
25
+ /**
26
+ * Build a config for a new project, merging defaults with user choices.
27
+ */
28
+ function buildNewProjectConfig(userChoices = {}) {
29
+ return {
30
+ ...DEFAULT_CONFIG,
31
+ ...userChoices,
32
+ project: {
33
+ ...DEFAULT_CONFIG.project,
34
+ ...(userChoices.project || {}),
35
+ created: userChoices.project?.created || new Date().toISOString(),
36
+ },
37
+ workflow: {
38
+ ...DEFAULT_CONFIG.workflow,
39
+ ...(userChoices.workflow || {}),
40
+ },
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Initialize config.json for a new project.
46
+ * Idempotent: returns existing if already present.
47
+ */
48
+ function cmdConfigInit(cwd, choicesJson, raw) {
49
+ const paths = hakiPaths(cwd);
50
+ const configPath = paths.config;
51
+
52
+ if (fs.existsSync(configPath)) {
53
+ output({ created: false, reason: "already_exists" }, raw, "exists");
54
+ return;
55
+ }
56
+
57
+ let userChoices = {};
58
+ if (choicesJson && choicesJson.trim() !== "") {
59
+ try {
60
+ userChoices = JSON.parse(choicesJson);
61
+ } catch (err) {
62
+ error("Invalid JSON for config init: " + err.message);
63
+ }
64
+ }
65
+
66
+ ensureDir(paths.haki);
67
+ const config = buildNewProjectConfig(userChoices);
68
+
69
+ try {
70
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
71
+ output({ created: true, path: ".haki/config.json" }, raw, "created");
72
+ } catch (err) {
73
+ error("Failed to write config.json: " + err.message);
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Get a config value using dot-notation path.
79
+ */
80
+ function cmdConfigGet(cwd, keyPath, raw) {
81
+ const configPath = hakiPaths(cwd).config;
82
+
83
+ if (!keyPath) error("Usage: config get <key.path>");
84
+
85
+ let config = {};
86
+ try {
87
+ if (fs.existsSync(configPath)) {
88
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
89
+ } else {
90
+ error("No config.json found");
91
+ }
92
+ } catch (err) {
93
+ if (err.message.startsWith("No config")) throw err;
94
+ error("Failed to read config.json: " + err.message);
95
+ }
96
+
97
+ const keys = keyPath.split(".");
98
+ let current = config;
99
+ for (const key of keys) {
100
+ if (
101
+ current === undefined ||
102
+ current === null ||
103
+ typeof current !== "object"
104
+ ) {
105
+ error("Key not found: " + keyPath);
106
+ }
107
+ current = current[key];
108
+ }
109
+
110
+ if (current === undefined) error("Key not found: " + keyPath);
111
+ output(current, raw, String(current));
112
+ }
113
+
114
+ /**
115
+ * Set a config value using dot-notation path.
116
+ */
117
+ function cmdConfigSet(cwd, keyPath, value, raw) {
118
+ if (!keyPath) error("Usage: config set <key.path> <value>");
119
+
120
+ const configPath = hakiPaths(cwd).config;
121
+
122
+ let config = {};
123
+ try {
124
+ if (fs.existsSync(configPath)) {
125
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
126
+ }
127
+ } catch (err) {
128
+ error("Failed to read config.json: " + err.message);
129
+ }
130
+
131
+ // Parse value
132
+ let parsedValue = value;
133
+ if (value === "true") parsedValue = true;
134
+ else if (value === "false") parsedValue = false;
135
+ else if (value === "null") parsedValue = null;
136
+ else if (!isNaN(value) && value !== "") parsedValue = Number(value);
137
+
138
+ // Set nested value
139
+ const keys = keyPath.split(".");
140
+ let current = config;
141
+ for (let i = 0; i < keys.length - 1; i++) {
142
+ if (
143
+ current[keys[i]] === undefined ||
144
+ typeof current[keys[i]] !== "object"
145
+ ) {
146
+ current[keys[i]] = {};
147
+ }
148
+ current = current[keys[i]];
149
+ }
150
+ current[keys[keys.length - 1]] = parsedValue;
151
+
152
+ try {
153
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
154
+ output(
155
+ { updated: true, key: keyPath, value: parsedValue },
156
+ raw,
157
+ `${keyPath}=${parsedValue}`,
158
+ );
159
+ } catch (err) {
160
+ error("Failed to write config.json: " + err.message);
161
+ }
162
+ }
163
+
164
+ module.exports = {
165
+ DEFAULT_CONFIG,
166
+ buildNewProjectConfig,
167
+ cmdConfigInit,
168
+ cmdConfigGet,
169
+ cmdConfigSet,
170
+ };