solmate-skills 2.0.12 → 2.0.13

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 (36) hide show
  1. package/AGENTS.md +9 -0
  2. package/CLAUDE.md +13 -3
  3. package/README.md +91 -5
  4. package/USAGE.md +118 -12
  5. package/bin/cli.js +171 -1
  6. package/bin/harness-artifact.js +621 -0
  7. package/bin/harness-artifact.test.js +520 -0
  8. package/bin/harness-check.js +373 -0
  9. package/bin/harness-check.test.js +159 -0
  10. package/bin/test.js +2 -0
  11. package/docs/01_Concept_Design/01_AGENT_HARNESS_REQUIREMENTS_ANALYSIS.md +162 -0
  12. package/docs/03_Technical_Specs/01_AGENT_HARNESS_ARCHITECTURE.md +376 -0
  13. package/docs/03_Technical_Specs/assets/01_agent_harness_data_flow.svg +94 -0
  14. package/docs/04_Logic_Progress/00_BACKLOG.md +339 -0
  15. package/docs/04_Logic_Progress/01_EXECUTION_PLAN.md +160 -0
  16. package/docs/04_Logic_Progress/03_DECISION_LOG.md +98 -0
  17. package/docs/05_QA_Validation/01_TEST_SCENARIOS.md +313 -0
  18. package/docs/05_QA_Validation/02_AGENT_HARNESS_DESIGN_REVIEW.md +100 -0
  19. package/docs/05_QA_Validation/03_AGENT_HARNESS_CONTRACT_QA.md +96 -0
  20. package/manage-collaboration/SKILL.md +2 -0
  21. package/package.json +6 -4
  22. package/rules-docs/SKILL.md +15 -1
  23. package/rules-product/SKILL.md +30 -6
  24. package/rules-product/agents/openai.yaml +2 -2
  25. package/rules-workflow/SKILL.md +32 -7
  26. package/rules-workflow/adapters/claude/solmate-context-reader.md +17 -0
  27. package/rules-workflow/adapters/claude/solmate-implementer.md +20 -0
  28. package/rules-workflow/adapters/claude/solmate-verifier.md +21 -0
  29. package/rules-workflow/agents/openai.yaml +2 -2
  30. package/rules-workflow/resources/agent-harness-contract.md +187 -0
  31. package/rules-workflow/resources/agent-harness-v1.schema.json +432 -0
  32. package/verify-docs/SKILL.md +33 -6
  33. package/verify-docs/agents/openai.yaml +2 -2
  34. package/verify-implementation/SKILL.md +14 -2
  35. package/verify-implementation/agents/openai.yaml +2 -2
  36. package/verify-skills/SKILL.md +27 -0
package/bin/cli.js CHANGED
@@ -3,6 +3,16 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
+ const {
7
+ checkHarnessTask,
8
+ formatHarnessResult,
9
+ getHarnessExitCode,
10
+ } = require('./harness-check');
11
+ const {
12
+ checkHarnessArtifact,
13
+ formatHarnessArtifactResult,
14
+ getHarnessArtifactExitCode,
15
+ } = require('./harness-artifact');
6
16
 
7
17
  const IGNORED_FOLDERS = ['bin', 'node_modules', '.git', '.github', '.gemini', '.agent'];
8
18
  const IGNORED_FILES = ['package.json', 'package-lock.json', 'AGENTS.md', 'SKILL.md', 'init-skills.sh', 'README.md', '.DS_Store', 'old_AGENTS.md'];
@@ -19,6 +29,8 @@ const POST_INSTALL_SCRIPTS = {
19
29
  const packageRoot = path.join(__dirname, '..');
20
30
  const targetProjectRoot = process.cwd();
21
31
  const targetSkillsDir = path.join(targetProjectRoot, '.agent', 'skills');
32
+ const claudeAgentSourceDir = path.join(packageRoot, 'rules-workflow', 'adapters', 'claude');
33
+ const targetClaudeAgentsDir = path.join(targetProjectRoot, '.claude', 'agents');
22
34
 
23
35
  function getAvailableSkills() {
24
36
  return fs.readdirSync(packageRoot, { withFileTypes: true })
@@ -61,13 +73,40 @@ function copyFolderSync(from, to) {
61
73
  });
62
74
  }
63
75
 
76
+ function installAgentAdapters() {
77
+ if (!fs.existsSync(claudeAgentSourceDir)) {
78
+ console.error('Error: Claude agent adapters not found in rules-workflow.');
79
+ process.exit(1);
80
+ }
81
+
82
+ fs.mkdirSync(targetClaudeAgentsDir, { recursive: true });
83
+ const agentFiles = fs.readdirSync(claudeAgentSourceDir)
84
+ .filter(fileName => fileName.startsWith('solmate-') && fileName.endsWith('.md'));
85
+
86
+ for (const fileName of agentFiles) {
87
+ fs.copyFileSync(
88
+ path.join(claudeAgentSourceDir, fileName),
89
+ path.join(targetClaudeAgentsDir, fileName),
90
+ );
91
+ }
92
+
93
+ console.log(`Installed ${agentFiles.length} Claude agent adapters to .claude/agents`);
94
+ console.log('Codex uses the same contract through rules-workflow; linked AGENTS.md reinforces it globally.');
95
+ }
96
+
64
97
  function listSkills() {
65
98
  const skills = getAvailableSkills();
66
99
  console.log('\nAvailable skills to install:');
67
100
  skills.forEach(skill => console.log(` - ${skill}`));
68
101
  console.log('\nUtilities:');
69
102
  console.log(' - hooks (install with: npx solmate-skills install hooks)');
70
- console.log('\nUsage: npx solmate-skills install <skill-name> | all | hooks\n');
103
+ console.log(' - agents (install with: npx solmate-skills install agents)');
104
+ console.log('\nHarness checks:');
105
+ console.log(' - npx solmate-skills preflight TASK-000 [--strict]');
106
+ console.log(' - npx solmate-skills verify TASK-000 [--strict]');
107
+ console.log(' - npx solmate-skills validate-harness <manifest|message|events> <path> [--manifest <path>] [--strict]');
108
+ console.log(' message and events validation require --manifest <path>');
109
+ console.log('\nUsage: npx solmate-skills install <skill-name> | all | hooks | agents\n');
71
110
  }
72
111
 
73
112
  function installHooks() {
@@ -123,6 +162,10 @@ function installSkill(skillName, options = {}) {
123
162
  copyFolderSync(sourcePath, destPath);
124
163
  console.log(`Successfully installed ${skillName} to .agent/skills/${skillName}`);
125
164
 
165
+ if (skillName === 'rules-workflow') {
166
+ installAgentAdapters();
167
+ }
168
+
126
169
  // Run post-install script if defined for this skill
127
170
  if (POST_INSTALL_SCRIPTS[skillName]) {
128
171
  const scriptPath = path.join(destPath, POST_INSTALL_SCRIPTS[skillName]);
@@ -141,6 +184,120 @@ function installSkill(skillName, options = {}) {
141
184
  }
142
185
  }
143
186
 
187
+ function installHarnessAgents() {
188
+ installSkill('rules-workflow');
189
+ }
190
+
191
+ function parseHarnessOptions(rawArgs) {
192
+ const options = { mode: 'warning' };
193
+
194
+ for (let index = 0; index < rawArgs.length; index += 1) {
195
+ const arg = rawArgs[index];
196
+ if (arg === '--strict') {
197
+ options.mode = 'blocking';
198
+ } else if (arg === '--mode') {
199
+ if (!rawArgs[index + 1]) {
200
+ throw new Error('--mode requires warning or blocking.');
201
+ }
202
+ options.mode = rawArgs[index + 1];
203
+ index += 1;
204
+ } else if (arg === '--backlog') {
205
+ if (!rawArgs[index + 1]) {
206
+ throw new Error('--backlog requires a file path.');
207
+ }
208
+ options.backlogPath = rawArgs[index + 1];
209
+ index += 1;
210
+ } else if (arg === '--json') {
211
+ options.json = true;
212
+ } else {
213
+ throw new Error(`Unknown option: ${arg}`);
214
+ }
215
+ }
216
+
217
+ return options;
218
+ }
219
+
220
+ function runHarnessCommand(stage, taskId, rawArgs) {
221
+ let options;
222
+ try {
223
+ options = parseHarnessOptions(rawArgs);
224
+ } catch (error) {
225
+ console.error(`Error: ${error.message}`);
226
+ process.exitCode = 2;
227
+ return;
228
+ }
229
+
230
+ const result = checkHarnessTask({
231
+ stage,
232
+ taskId,
233
+ mode: options.mode,
234
+ backlogPath: options.backlogPath,
235
+ cwd: targetProjectRoot,
236
+ });
237
+
238
+ if (options.json) {
239
+ console.log(JSON.stringify(result, null, 2));
240
+ } else {
241
+ console.log(formatHarnessResult(result));
242
+ }
243
+ process.exitCode = getHarnessExitCode(result);
244
+ }
245
+
246
+ function parseHarnessArtifactOptions(rawArgs) {
247
+ const options = { mode: 'warning' };
248
+
249
+ for (let index = 0; index < rawArgs.length; index += 1) {
250
+ const arg = rawArgs[index];
251
+ if (arg === '--strict') {
252
+ options.mode = 'blocking';
253
+ } else if (arg === '--mode') {
254
+ if (!rawArgs[index + 1]) {
255
+ throw new Error('--mode requires warning or blocking.');
256
+ }
257
+ options.mode = rawArgs[index + 1];
258
+ index += 1;
259
+ } else if (arg === '--manifest') {
260
+ if (!rawArgs[index + 1]) {
261
+ throw new Error('--manifest requires a file path.');
262
+ }
263
+ options.manifestPath = rawArgs[index + 1];
264
+ index += 1;
265
+ } else if (arg === '--json') {
266
+ options.json = true;
267
+ } else {
268
+ throw new Error(`Unknown option: ${arg}`);
269
+ }
270
+ }
271
+
272
+ return options;
273
+ }
274
+
275
+ function runHarnessArtifactCommand(artifactType, filePath, rawArgs) {
276
+ let options;
277
+ try {
278
+ options = parseHarnessArtifactOptions(rawArgs);
279
+ } catch (error) {
280
+ console.error(`Error: ${error.message}`);
281
+ process.exitCode = 2;
282
+ return;
283
+ }
284
+
285
+ const result = checkHarnessArtifact({
286
+ artifactType,
287
+ filePath,
288
+ mode: options.mode,
289
+ manifestPath: options.manifestPath,
290
+ cwd: targetProjectRoot,
291
+ });
292
+
293
+ if (options.json) {
294
+ console.log(JSON.stringify(result, null, 2));
295
+ } else {
296
+ console.log(formatHarnessArtifactResult(result));
297
+ }
298
+ process.exitCode = getHarnessArtifactExitCode(result);
299
+ }
300
+
144
301
  const args = process.argv.slice(2);
145
302
  const command = args[0];
146
303
  const subCommand = args[1];
@@ -157,6 +314,8 @@ if (!command || command === 'list') {
157
314
  installSkill('install-all');
158
315
  } else if (subCommand === 'hooks' || subCommand === 'install-hooks') {
159
316
  installHooks();
317
+ } else if (subCommand === 'agents' || subCommand === 'install-agents') {
318
+ installHarnessAgents();
160
319
  } else {
161
320
  installSkill(subCommand);
162
321
  }
@@ -164,6 +323,17 @@ if (!command || command === 'list') {
164
323
  installSkill('install-all');
165
324
  } else if (command === 'install-hooks' || command === 'hooks') {
166
325
  installHooks();
326
+ } else if (command === 'install-agents' || command === 'agents') {
327
+ installHarnessAgents();
328
+ } else if (command === 'preflight' || command === 'verify') {
329
+ if (!subCommand) {
330
+ console.error(`Error: ${command} requires a backlog task ID.`);
331
+ process.exitCode = 2;
332
+ } else {
333
+ runHarnessCommand(command, subCommand, args.slice(2));
334
+ }
335
+ } else if (command === 'validate-harness') {
336
+ runHarnessArtifactCommand(subCommand, args[2], args.slice(3));
167
337
  } else {
168
338
  console.log(`Unknown command: ${command}`);
169
339
  listSkills();