@sallmarta/eye-hate-agent 1.0.2 → 1.0.3

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 (89) hide show
  1. package/README.md +38 -310
  2. package/bin/eha.js +203 -118
  3. package/docs/templates/project-docs-template/foundation/architecture.md +79 -0
  4. package/docs/templates/project-docs-template/foundation/changelog.md +53 -0
  5. package/docs/templates/project-docs-template/foundation/feature-inventory.md +46 -0
  6. package/docs/templates/project-docs-template/foundation/phases.md +60 -0
  7. package/docs/templates/project-docs-template/foundation/prd.md +69 -0
  8. package/docs/templates/project-docs-template/foundation/status.md +57 -0
  9. package/docs/templates/project-docs-template/foundation/workflow.md +59 -0
  10. package/docs/templates/project-docs-template/getting-started.md +52 -0
  11. package/docs/{vibes → templates}/project-docs-template/index.md +12 -12
  12. package/docs/templates/project-docs-template/operations/ci-cd.md +56 -0
  13. package/docs/templates/project-docs-template/operations/compliance.md +46 -0
  14. package/docs/templates/project-docs-template/operations/governance.md +46 -0
  15. package/docs/templates/project-docs-template/operations/observability.md +53 -0
  16. package/docs/templates/project-docs-template/operations/production-runbook.md +62 -0
  17. package/docs/templates/project-docs-template/operations/security.md +49 -0
  18. package/docs/templates/project-docs-template/technical/api-contract.md +49 -0
  19. package/docs/templates/project-docs-template/technical/database.md +59 -0
  20. package/docs/templates/project-docs-template/technical/error-handling.md +54 -0
  21. package/docs/templates/project-docs-template/technical/internationalization.md +46 -0
  22. package/docs/templates/project-docs-template/technical/testing.md +57 -0
  23. package/docs/templates/project-docs-template/technical/ui-ux.md +68 -0
  24. package/docs/{vibes → templates}/project-docs-template/technical-guidelines/index.md +3 -3
  25. package/docs/{vibes → templates}/reusable-prompts/00-project-docs-bootstrap.md +2 -4
  26. package/docs/{vibes → templates}/reusable-prompts/00-project-docs-parity.md +3 -5
  27. package/docs/{vibes → templates}/reusable-prompts/00-project-docs-refresh.md +2 -4
  28. package/docs/{vibes → templates}/reusable-prompts/02-sdd-discuss.md +2 -2
  29. package/{.agents/rules/agent.md → docs/templates/rules/agent-rules.md} +6 -11
  30. package/docs/templates/skills/architecture/db-schema-design/SKILL.md +14 -0
  31. package/docs/{vibes/skills → templates/skills/auditing}/full-verification/SKILL.md +1 -1
  32. package/docs/{vibes/skills → templates/skills/auditing}/parity/SKILL.md +2 -2
  33. package/docs/templates/skills/engineering/refactor-specialist/SKILL.md +13 -0
  34. package/docs/{vibes/skills → templates/skills/engineering}/test-authoring/SKILL.md +177 -1
  35. package/docs/templates/skills/engineering/ui-ux-implementation/SKILL.md +13 -0
  36. package/docs/templates/skills/operations/ci-cd-authoring/SKILL.md +13 -0
  37. package/docs/templates/skills/operations/observability-setup/SKILL.md +13 -0
  38. package/package.json +4 -6
  39. package/src/engine/index.js +7 -12
  40. package/src/engine/install.js +67 -163
  41. package/src/engine/runtime-adapters.js +263 -50
  42. package/src/engine/skill-registry.js +67 -0
  43. package/src/engine/state.js +29 -7
  44. package/src/engine/workflow-registry.js +14 -23
  45. package/.claude/commands/eha/README.md +0 -3
  46. package/.claude/commands/eha/eha-bootstrap.md +0 -9
  47. package/.claude/commands/eha/eha-discuss.md +0 -9
  48. package/.claude/commands/eha/eha-execute.md +0 -9
  49. package/.claude/commands/eha/eha-parity.md +0 -9
  50. package/.claude/commands/eha/eha-refresh.md +0 -9
  51. package/.claude/commands/eha/eha-verify.md +0 -9
  52. package/.claude/rules/agent-rules.md +0 -64
  53. package/.github/instructions/agent-rules.instructions.md +0 -63
  54. package/.github/instructions/eha-workflows.instructions.md +0 -21
  55. package/docs/eyehateagent-contract.md +0 -475
  56. package/docs/eyehateagent-maintenance.md +0 -103
  57. package/docs/project-docs/changelog.md +0 -299
  58. package/docs/project-docs/foundation/architecture.md +0 -117
  59. package/docs/project-docs/foundation/status.md +0 -32
  60. package/docs/project-docs/foundation/workflow.md +0 -63
  61. package/docs/project-docs/index.md +0 -20
  62. package/docs/project-docs/testing.md +0 -73
  63. package/docs/vibes/project-docs-template/foundation/architecture.md +0 -79
  64. package/docs/vibes/project-docs-template/foundation/changelog.md +0 -53
  65. package/docs/vibes/project-docs-template/foundation/feature-inventory.md +0 -46
  66. package/docs/vibes/project-docs-template/foundation/phases.md +0 -60
  67. package/docs/vibes/project-docs-template/foundation/prd.md +0 -69
  68. package/docs/vibes/project-docs-template/foundation/status.md +0 -57
  69. package/docs/vibes/project-docs-template/foundation/workflow.md +0 -59
  70. package/docs/vibes/project-docs-template/getting-started.md +0 -52
  71. package/docs/vibes/project-docs-template/operations/ci-cd.md +0 -56
  72. package/docs/vibes/project-docs-template/operations/compliance.md +0 -46
  73. package/docs/vibes/project-docs-template/operations/governance.md +0 -46
  74. package/docs/vibes/project-docs-template/operations/observability.md +0 -53
  75. package/docs/vibes/project-docs-template/operations/production-runbook.md +0 -62
  76. package/docs/vibes/project-docs-template/operations/security.md +0 -49
  77. package/docs/vibes/project-docs-template/technical/api-contract.md +0 -49
  78. package/docs/vibes/project-docs-template/technical/database.md +0 -59
  79. package/docs/vibes/project-docs-template/technical/error-handling.md +0 -54
  80. package/docs/vibes/project-docs-template/technical/internationalization.md +0 -46
  81. package/docs/vibes/project-docs-template/technical/testing.md +0 -57
  82. package/docs/vibes/project-docs-template/technical/ui-ux.md +0 -68
  83. package/docs/vibes/skills/project-elevation/SKILL.md +0 -157
  84. package/docs/vibes/skills/test-authoring/references/patterns.md +0 -116
  85. package/docs/vibes/skills/test-authoring/references/test-types.md +0 -52
  86. /package/docs/{vibes → templates}/reusable-prompts/01-sdd-execute.md +0 -0
  87. /package/docs/{vibes/skills → templates/skills/architecture}/api-design/SKILL.md +0 -0
  88. /package/docs/{vibes/skills/analysis → templates/skills/architecture/system-analysis}/SKILL.md +0 -0
  89. /package/docs/{vibes/skills/code-audit → templates/skills/auditing/security-audit}/SKILL.md +0 -0
@@ -0,0 +1,13 @@
1
+ # Observability Setup Skill
2
+
3
+ You are a Site Reliability Engineer (SRE) focused on ensuring deep system observability and alerting.
4
+
5
+ ## Responsibilities
6
+ 1. Analyze backend architectures and inject proper structured logging, distributed tracing (e.g., OpenTelemetry), and performance metrics.
7
+ 2. Design actionable alerting rules and dashboards for detecting anomalies.
8
+ 3. Standardize error handling to ensure contextual data (user IDs, request IDs) is always logged without leaking PII.
9
+
10
+ ## Output Constraints
11
+ - Code modifications should use the project's existing logger (e.g., Winston, Pino) if one exists.
12
+ - Ensure all emitted metrics follow standard naming conventions (e.g., Prometheus format).
13
+ - Never log raw request bodies or unmasked sensitive credentials.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sallmarta/eye-hate-agent",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Template-and-engine toolkit for AI-agent-assisted project workflows.",
5
5
  "directories": {
6
6
  "doc": "docs"
@@ -8,10 +8,7 @@
8
8
  "files": [
9
9
  "bin",
10
10
  "src",
11
- "docs",
12
- ".claude",
13
- ".github",
14
- ".agents",
11
+ "docs/templates",
15
12
  "README.md"
16
13
  ],
17
14
  "scripts": {
@@ -44,8 +41,9 @@
44
41
  "node": ">=18"
45
42
  },
46
43
  "bin": {
44
+ "eha": "./bin/eha.js",
47
45
  "eye-hate-agent": "./bin/eha.js",
48
- "eha": "./bin/eha.js"
46
+ "eyehateagent": "./bin/eha.js"
49
47
  },
50
48
  "dependencies": {
51
49
  "commander": "^12.0.0",
@@ -1,22 +1,17 @@
1
1
  const { getWorkflow, listWorkflows } = require('./workflow-registry');
2
- const { findRepoRoot } = require('./state');
2
+ const { findRepoRoot, readConfig } = require('./state');
3
3
  const { listSupportedRuntimes } = require('./runtime-adapters');
4
- const {
5
- DEFAULT_RUNTIME_IDS,
6
- doctor,
7
- installRuntimes,
8
- prepareWorkflowRun,
9
- uninstallRuntimes,
10
- } = require('./install');
4
+ const { SUPPORTED_AGENT_IDS, doctor, initProject, readProjectManifest, removeProject } = require('./install');
11
5
 
12
6
  module.exports = {
13
- DEFAULT_RUNTIME_IDS,
7
+ SUPPORTED_AGENT_IDS,
14
8
  doctor,
15
9
  findRepoRoot,
16
10
  getWorkflow,
17
- installRuntimes,
11
+ initProject,
18
12
  listSupportedRuntimes,
19
13
  listWorkflows,
20
- prepareWorkflowRun,
21
- uninstallRuntimes,
14
+ readConfig,
15
+ readProjectManifest,
16
+ removeProject,
22
17
  };
@@ -1,222 +1,126 @@
1
1
  const fs = require('node:fs');
2
2
  const path = require('node:path');
3
+ const { version: EHA_PACKAGE_VERSION } = require('../../package.json');
3
4
 
4
- const { listWorkflows, getWorkflow } = require('./workflow-registry');
5
+ const { listWorkflows } = require('./workflow-registry');
6
+ const { listSkills } = require('./skill-registry');
5
7
  const { getRuntimeAdapter, listSupportedRuntimes } = require('./runtime-adapters');
6
8
  const {
7
9
  ensureDir,
8
10
  getBundledAssetPath,
9
11
  getEnginePaths,
12
+ readConfig,
10
13
  readJsonIfExists,
11
14
  removeEmptyParents,
12
15
  removeFileIfExists,
16
+ writeConfig,
13
17
  writeJson,
14
18
  writeText,
15
19
  } = require('./state');
16
20
 
17
- const DEFAULT_RUNTIME_IDS = ['claude', 'copilot'];
18
- const BUNDLED_CONTRACT_PATH = path.join('docs', 'eyehateagent-contract.md');
21
+ const SUPPORTED_AGENT_IDS = ['claude', 'copilot', 'antigravity'];
19
22
 
20
- function resolveRuntimeIds(runtimes) {
21
- const runtimeIds = runtimes && runtimes.length > 0 ? runtimes : DEFAULT_RUNTIME_IDS;
22
- return [...new Set(runtimeIds.map((runtime) => String(runtime).trim().toLowerCase()).filter(Boolean))];
23
+ function resolveAgentId(agentId) {
24
+ const normalized = String(agentId || '').trim().toLowerCase();
25
+ if (!SUPPORTED_AGENT_IDS.includes(normalized)) {
26
+ throw new Error(`Unsupported agent: ${agentId}. Choose one of: ${SUPPORTED_AGENT_IDS.join(', ')}.`);
27
+ }
28
+ return normalized;
23
29
  }
24
30
 
25
31
  function readManifest(manifestPath) {
26
32
  return (
27
33
  readJsonIfExists(manifestPath) || {
28
- generatedOutputsInsideRepo: true,
29
34
  manifestVersion: 1,
30
- runtimes: {},
35
+ agent: null,
36
+ files: [],
31
37
  }
32
38
  );
33
39
  }
34
40
 
35
- function buildManifestSummary(runtimeId, adapter, files) {
36
- return {
37
- files: files.map((file) => file.relativePath),
38
- supportTier: adapter.supportTier,
39
- updatedAt: new Date().toISOString(),
40
- };
41
- }
42
-
43
- function getGeneratedSourceRelativePath(repoRelativePath) {
44
- return path.join('.eha', 'generated', 'sources', repoRelativePath);
45
- }
46
-
47
- function materializeBundledSources(rootDir, workflows) {
48
- const repoRelativePaths = new Set([BUNDLED_CONTRACT_PATH]);
49
- for (const workflow of workflows) {
50
- repoRelativePaths.add(workflow.repoRelativePath);
51
- }
52
-
53
- const generatedSourcePaths = {};
54
-
55
- for (const repoRelativePath of repoRelativePaths) {
56
- const sourcePath = getBundledAssetPath(repoRelativePath);
57
- const targetRelativePath = getGeneratedSourceRelativePath(repoRelativePath);
58
- const targetPath = path.join(rootDir, targetRelativePath);
59
- writeText(targetPath, fs.readFileSync(sourcePath, 'utf8'));
60
- generatedSourcePaths[repoRelativePath] = targetRelativePath;
61
- }
62
-
63
- return {
64
- contractPath: generatedSourcePaths[BUNDLED_CONTRACT_PATH],
65
- workflowPaths: generatedSourcePaths,
66
- };
67
- }
68
-
69
- function installRuntimes({ rootDir, runtimes }) {
70
- const runtimeIds = resolveRuntimeIds(runtimes);
71
- const enginePaths = getEnginePaths(rootDir);
72
- const manifest = readManifest(enginePaths.manifestPath);
41
+ function initProject({ rootDir, agentId }) {
42
+ const normalizedAgentId = resolveAgentId(agentId);
43
+ const adapter = getRuntimeAdapter(normalizedAgentId);
73
44
  const workflows = listWorkflows();
74
- const bundledSources = materializeBundledSources(rootDir, workflows);
75
- const runtimeSummaries = [];
76
-
77
- for (const runtimeId of runtimeIds) {
78
- const adapter = getRuntimeAdapter(runtimeId);
79
- const files = adapter.generateFiles(rootDir, workflows, bundledSources);
45
+ const skills = listSkills();
46
+ const files = adapter.generateFiles(rootDir, workflows, skills);
80
47
 
81
- for (const file of files) {
82
- const absolutePath = path.join(rootDir, file.relativePath);
83
- ensureDir(path.dirname(absolutePath));
84
- writeText(absolutePath, file.content);
85
- }
86
-
87
- manifest.runtimes[runtimeId] = buildManifestSummary(runtimeId, adapter, files);
88
- runtimeSummaries.push({
89
- id: runtimeId,
90
- supportTier: adapter.supportTier,
91
- fileCount: files.length,
92
- });
48
+ for (const file of files) {
49
+ const absolutePath = path.join(rootDir, file.relativePath);
50
+ ensureDir(path.dirname(absolutePath));
51
+ writeText(absolutePath, file.content);
93
52
  }
94
53
 
54
+ const enginePaths = getEnginePaths(rootDir);
55
+ const manifest = {
56
+ manifestVersion: 1,
57
+ agent: normalizedAgentId,
58
+ files: files.map((f) => f.relativePath),
59
+ updatedAt: new Date().toISOString(),
60
+ packageVersion: EHA_PACKAGE_VERSION,
61
+ };
95
62
  writeJson(enginePaths.manifestPath, manifest);
63
+ const config = writeConfig(rootDir, { agent: normalizedAgentId });
96
64
 
97
65
  return {
98
66
  rootDir,
99
- runtimes: runtimeIds,
100
- manifestPath: enginePaths.manifestPath,
101
- runtimeSummaries,
67
+ agentId: normalizedAgentId,
68
+ config,
69
+ files: manifest.files,
70
+ fileCount: files.length,
102
71
  };
103
72
  }
104
73
 
105
- function uninstallRuntimes({ rootDir, runtimes }) {
74
+ function removeProject({ rootDir }) {
106
75
  const enginePaths = getEnginePaths(rootDir);
107
76
  const manifest = readManifest(enginePaths.manifestPath);
108
- const runtimeIds = resolveRuntimeIds(runtimes);
109
- const runtimeSummaries = [];
110
-
111
- for (const runtimeId of runtimeIds) {
112
- const manifestEntry = manifest.runtimes[runtimeId];
113
- if (!manifestEntry) {
114
- runtimeSummaries.push({ id: runtimeId, supportTier: 'unknown', fileCount: 0 });
115
- continue;
116
- }
77
+ const removedFiles = [];
117
78
 
118
- for (const relativePath of manifestEntry.files) {
119
- const absolutePath = path.join(rootDir, relativePath);
120
- removeFileIfExists(absolutePath);
121
- removeEmptyParents(path.dirname(absolutePath), rootDir);
122
- }
123
-
124
- runtimeSummaries.push({
125
- id: runtimeId,
126
- supportTier: manifestEntry.supportTier,
127
- fileCount: manifestEntry.files.length,
128
- });
129
- delete manifest.runtimes[runtimeId];
130
- }
131
-
132
- if (Object.keys(manifest.runtimes).length === 0) {
133
- removeFileIfExists(enginePaths.manifestPath);
134
- removeEmptyParents(path.dirname(enginePaths.manifestPath), rootDir);
135
- } else {
136
- writeJson(enginePaths.manifestPath, manifest);
137
- }
138
-
139
- return {
140
- rootDir,
141
- runtimes: runtimeIds,
142
- manifestPath: enginePaths.manifestPath,
143
- runtimeSummaries,
144
- };
145
- }
146
-
147
- function buildPromptContent(workflow, sourcePaths, contextText, invokedAs) {
148
- const commandLabel = invokedAs || workflow.commandName;
149
-
150
- let content = `# EHA Workflow Dispatch\n\n`;
151
- content += `Read \`${sourcePaths.contractPath}\` first.\n\n`;
152
- content += `Execute \`${sourcePaths.workflowPath}\`.\n\n`;
153
- content += `Requested via CLI command: \`${commandLabel}\`\n`;
154
-
155
- if (workflow.capabilityNote) {
156
- content += `\n> Note: ${workflow.capabilityNote}\n`;
79
+ for (const relativePath of manifest.files || []) {
80
+ const absolutePath = path.join(rootDir, relativePath);
81
+ removeFileIfExists(absolutePath);
82
+ removeEmptyParents(path.dirname(absolutePath), rootDir);
83
+ removedFiles.push(relativePath);
157
84
  }
158
85
 
159
- if (contextText) {
160
- content += `\n## Additional CLI Context\n\n${contextText}\n`;
161
- }
86
+ removeFileIfExists(enginePaths.manifestPath);
87
+ removeEmptyParents(path.dirname(enginePaths.manifestPath), rootDir);
88
+ removeFileIfExists(enginePaths.configPath);
89
+ removeEmptyParents(path.dirname(enginePaths.configPath), rootDir);
162
90
 
163
- return content;
164
- }
165
-
166
- function prepareWorkflowRun({ rootDir, workflowId, contextText = '', invokedAs = null }) {
167
- const workflow = getWorkflow(workflowId);
168
- const enginePaths = getEnginePaths(rootDir);
169
- const bundledSources = materializeBundledSources(rootDir, [workflow]);
170
- const promptContent = buildPromptContent(
171
- workflow,
172
- {
173
- contractPath: bundledSources.contractPath,
174
- workflowPath: bundledSources.workflowPaths[workflow.repoRelativePath],
175
- },
176
- contextText,
177
- invokedAs,
178
- );
179
-
180
- writeText(enginePaths.lastPromptPath, promptContent);
181
- writeJson(enginePaths.lastRunPath, {
182
- workflowId: workflow.id,
183
- invokedAs: invokedAs || workflow.commandName,
184
- promptPath: path.relative(rootDir, enginePaths.lastPromptPath),
185
- sourceWorkflowPath: workflow.repoRelativePath,
186
- contextText,
187
- updatedAt: new Date().toISOString(),
188
- });
189
-
190
- return {
191
- workflow,
192
- promptContent,
193
- promptPath: path.relative(rootDir, enginePaths.lastPromptPath),
194
- contextText,
195
- };
91
+ return { rootDir, removedFiles };
196
92
  }
197
93
 
198
94
  function doctor({ rootDir }) {
199
95
  const enginePaths = getEnginePaths(rootDir);
200
96
  const manifest = readManifest(enginePaths.manifestPath);
201
- const installedRuntimes = Object.entries(manifest.runtimes).map(([id, entry]) => ({
202
- id,
203
- supportTier: entry.supportTier,
204
- fileCount: entry.files.length,
97
+ const config = readConfig(rootDir);
98
+
99
+ const generatedFiles = (manifest.files || []).map((relativePath) => ({
100
+ relativePath,
101
+ exists: fs.existsSync(path.join(rootDir, relativePath)),
205
102
  }));
206
103
 
207
104
  return {
208
105
  rootDir,
209
- generatedOutputsInsideRepo: true,
106
+ config,
107
+ agentId: config.agent,
210
108
  paths: enginePaths,
211
- supportedRuntimes: listSupportedRuntimes(),
212
- installedRuntimes,
109
+ supportedAgents: listSupportedRuntimes(),
110
+ generatedFiles,
111
+ isInitialized: Boolean(config.agent),
213
112
  };
214
113
  }
215
114
 
115
+ function readProjectManifest(rootDir) {
116
+ const { manifestPath } = getEnginePaths(rootDir);
117
+ return readManifest(manifestPath);
118
+ }
119
+
216
120
  module.exports = {
217
- DEFAULT_RUNTIME_IDS,
121
+ SUPPORTED_AGENT_IDS,
218
122
  doctor,
219
- installRuntimes,
220
- prepareWorkflowRun,
221
- uninstallRuntimes,
123
+ initProject,
124
+ readProjectManifest,
125
+ removeProject,
222
126
  };