@modus-ai/modus 0.1.0 → 0.1.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 (57) hide show
  1. package/dist/cli/index.js +41 -2
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/global.d.ts +15 -0
  4. package/dist/commands/global.d.ts.map +1 -0
  5. package/dist/commands/global.js +222 -0
  6. package/dist/commands/global.js.map +1 -0
  7. package/dist/commands/init.d.ts +17 -1
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +278 -58
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/update.d.ts +8 -1
  12. package/dist/commands/update.d.ts.map +1 -1
  13. package/dist/commands/update.js +27 -4
  14. package/dist/commands/update.js.map +1 -1
  15. package/dist/generators/codebuddy.d.ts +5 -1
  16. package/dist/generators/codebuddy.d.ts.map +1 -1
  17. package/dist/generators/codebuddy.js +358 -5
  18. package/dist/generators/codebuddy.js.map +1 -1
  19. package/dist/utils/config.d.ts +17 -0
  20. package/dist/utils/config.d.ts.map +1 -1
  21. package/dist/utils/config.js +15 -0
  22. package/dist/utils/config.js.map +1 -1
  23. package/package.json +1 -1
  24. package/templates/agents/modus-harness-00-skills-builder.md +12 -0
  25. package/templates/agents/modus-harness-01-5-design.md +40 -0
  26. package/templates/agents/modus-harness-01-analysis.md +14 -0
  27. package/templates/agents/modus-harness-02-dev.md +16 -0
  28. package/templates/agents/modus-harness-03-test.md +16 -0
  29. package/templates/agents/modus-harness-04-perf.md +16 -0
  30. package/templates/agents/modus-harness-05-security.md +16 -0
  31. package/templates/agents/modus-harness-06-review.md +16 -0
  32. package/templates/agents/modus-harness-07-deploy.md +16 -0
  33. package/templates/commands/modus.md +25 -0
  34. package/templates/hooks/post-tool-use-lint.py +78 -0
  35. package/templates/hooks/pre-compact-save.py +117 -0
  36. package/templates/hooks/pre-tool-use-safety.py +80 -0
  37. package/templates/hooks/session-start.py +86 -0
  38. package/templates/hooks/stop-update-skills.py +91 -0
  39. package/templates/hooks-config.json +83 -0
  40. package/templates/rules/modus-constitution/RULE.mdc +40 -0
  41. package/templates/rules/modus-design-brief/RULE.mdc +127 -0
  42. package/templates/rules/modus-workflow/RULE.mdc +64 -0
  43. package/templates/skills/modus-design-brief/SKILL.md +324 -0
  44. package/templates/skills/modus-harness/SKILL.md +17 -0
  45. package/templates/skills/modus-harness-agents/00-skills-builder/SKILL.md +80 -6
  46. package/templates/skills/modus-harness-agents/01-5-design/SKILL.md +140 -0
  47. package/templates/skills/modus-harness-agents/01-analysis/SKILL.md +7 -0
  48. package/templates/skills/modus-harness-agents/02-dev/SKILL.md +7 -0
  49. package/templates/skills/modus-harness-agents/03-test/SKILL.md +7 -0
  50. package/templates/skills/modus-harness-agents/04-perf/SKILL.md +7 -0
  51. package/templates/skills/modus-harness-agents/05-security/SKILL.md +7 -0
  52. package/templates/skills/modus-harness-agents/06-review/SKILL.md +7 -0
  53. package/templates/skills/modus-harness-agents/07-deploy/SKILL.md +7 -0
  54. package/templates/skills/modus-init/SKILL.md +24 -0
  55. package/templates/skills/modus-plan/SKILL.md +65 -8
  56. package/templates/skills/modus-spec/SKILL.md +71 -4
  57. package/templates/skills/modus-vibe/SKILL.md +89 -6
@@ -1,10 +1,20 @@
1
1
  // CodeBuddy-specific file generator.
2
- // Writes SKILL.md files to .codebuddy/skills/modus-{name}/
3
- // and command files to .codebuddy/commands/modus/{name}.md
2
+ // Writes SKILL.md files, command files, agent definitions, hook scripts,
3
+ // rules, and settings.json (hooks + MCP) to the project's .codebuddy/ directory.
4
+ import fs from 'node:fs';
4
5
  import path from 'node:path';
5
- import { writeFile, readTemplate } from '../utils/file-system.js';
6
+ import { writeFile, readTemplate, fileExists, readFile, listDirs, ensureDir } from '../utils/file-system.js';
7
+ import { getGlobalDir, getTeamDir } from '../utils/config.js';
6
8
  const SKILLS_BASE = path.join('.codebuddy', 'skills');
7
9
  const COMMANDS_BASE = path.join('.codebuddy', 'commands', 'modus');
10
+ const COMMANDS_ROOT = path.join('.codebuddy', 'commands');
11
+ const AGENTS_BASE = path.join('.codebuddy', 'agents');
12
+ const HOOKS_BASE = path.join('.codebuddy', 'hooks');
13
+ const RULES_BASE = path.join('.codebuddy', 'rules');
14
+ const SETTINGS_PATH = path.join('.codebuddy', 'settings.json');
15
+ // ---------------------------------------------------------------------------
16
+ // Skills
17
+ // ---------------------------------------------------------------------------
8
18
  /** All framework skills (non-business) that are always generated */
9
19
  const FRAMEWORK_SKILLS = [
10
20
  'modus-init',
@@ -37,12 +47,148 @@ const SKILL_TEMPLATE_MAP = {
37
47
  'modus-harness-06-review': 'modus-harness-agents/06-review/SKILL.md',
38
48
  'modus-harness-07-deploy': 'modus-harness-agents/07-deploy/SKILL.md',
39
49
  };
50
+ // ---------------------------------------------------------------------------
51
+ // Agents
52
+ // ---------------------------------------------------------------------------
53
+ const HARNESS_AGENTS = [
54
+ 'modus-harness-00-skills-builder',
55
+ 'modus-harness-01-analysis',
56
+ 'modus-harness-02-dev',
57
+ 'modus-harness-03-test',
58
+ 'modus-harness-04-perf',
59
+ 'modus-harness-05-security',
60
+ 'modus-harness-06-review',
61
+ 'modus-harness-07-deploy',
62
+ ];
63
+ // ---------------------------------------------------------------------------
64
+ // Commands
65
+ // ---------------------------------------------------------------------------
40
66
  const COMMAND_IDS = ['init', 'vibe', 'plan', 'spec', 'harness'];
41
- export function generateCodeBuddyFiles(projectRoot, config) {
67
+ // ---------------------------------------------------------------------------
68
+ // Hooks
69
+ // ---------------------------------------------------------------------------
70
+ const HOOK_SCRIPTS = [
71
+ 'session-start.py',
72
+ 'pre-tool-use-safety.py',
73
+ 'post-tool-use-lint.py',
74
+ 'stop-update-skills.py',
75
+ 'pre-compact-save.py',
76
+ ];
77
+ // ---------------------------------------------------------------------------
78
+ // Rules
79
+ // ---------------------------------------------------------------------------
80
+ const RULE_DIRS = ['modus-workflow', 'modus-constitution'];
81
+ export function generateCodeBuddyFiles(projectRoot, config, opts = {}) {
82
+ // Step 1: Copy Skills/Rules from global→team→project (lower priority first)
83
+ copyFromHigherScopes(projectRoot, config, opts.syncScopes);
84
+ // Step 2: Generate framework Skills (always overwrite — managed by modus)
42
85
  generateSkills(projectRoot, config);
43
86
  generateCommands(projectRoot, config);
87
+ generateAgents(projectRoot, config);
88
+ generateHooks(projectRoot, config);
89
+ generateRules(projectRoot, config);
90
+ generateMcpConfig(projectRoot, config);
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Three-scope copy: Global → Team → Project
94
+ // ---------------------------------------------------------------------------
95
+ /**
96
+ * Copy Skills and Rules from the global and team directories into the project's
97
+ * .codebuddy/ directory, following the priority chain:
98
+ *
99
+ * Global (lowest) → Team (overrides global) → Project (highest, never overwritten)
100
+ *
101
+ * Framework Skills (modus-init, modus-vibe, …) are excluded from copying
102
+ * since they are always regenerated from templates.
103
+ *
104
+ * @param syncScopes - When true, overwrite existing project files from scope dirs.
105
+ * When false (default on `modus init`), skip files that already
106
+ * exist in the project to preserve local edits.
107
+ */
108
+ function copyFromHigherScopes(projectRoot, config, syncScopes = false) {
109
+ const scopeDirs = [
110
+ { dir: getGlobalDir(), scope: 'global' },
111
+ ];
112
+ if (config.teamName) {
113
+ scopeDirs.push({ dir: getTeamDir(config.teamName), scope: `team:${config.teamName}` });
114
+ }
115
+ for (const { dir, scope } of scopeDirs) {
116
+ copyScopeSkills(projectRoot, dir, scope, syncScopes);
117
+ copyScopeRules(projectRoot, dir, scope, syncScopes);
118
+ }
119
+ }
120
+ /**
121
+ * Copy Skill directories from a scope's skills/ into project .codebuddy/skills/.
122
+ * Skips framework Skills that are managed by modus itself.
123
+ */
124
+ function copyScopeSkills(projectRoot, scopeDir, scope, overwrite) {
125
+ const srcSkillsDir = path.join(scopeDir, 'skills');
126
+ if (!fs.existsSync(srcSkillsDir))
127
+ return;
128
+ const skillDirs = listDirs(srcSkillsDir);
129
+ for (const skillDirName of skillDirs) {
130
+ // Skip framework Skills — they are always regenerated from templates
131
+ if (FRAMEWORK_SKILLS.includes(skillDirName))
132
+ continue;
133
+ const srcSkillPath = path.join(srcSkillsDir, skillDirName, 'SKILL.md');
134
+ if (!fs.existsSync(srcSkillPath))
135
+ continue;
136
+ const destSkillDir = path.join(projectRoot, SKILLS_BASE, skillDirName);
137
+ const destSkillPath = path.join(destSkillDir, 'SKILL.md');
138
+ if (!overwrite && fileExists(destSkillPath))
139
+ continue;
140
+ ensureDir(destSkillDir);
141
+ const content = injectSourceMeta(readFile(srcSkillPath), scope);
142
+ writeFile(destSkillPath, content);
143
+ }
144
+ }
145
+ /**
146
+ * Copy Rule directories from a scope's rules/ into project .codebuddy/rules/.
147
+ */
148
+ function copyScopeRules(projectRoot, scopeDir, scope, overwrite) {
149
+ const srcRulesDir = path.join(scopeDir, 'rules');
150
+ if (!fs.existsSync(srcRulesDir))
151
+ return;
152
+ const ruleDirs = listDirs(srcRulesDir);
153
+ for (const ruleDirName of ruleDirs) {
154
+ const srcRulePath = path.join(srcRulesDir, ruleDirName, 'RULE.mdc');
155
+ if (!fs.existsSync(srcRulePath))
156
+ continue;
157
+ const destRuleDir = path.join(projectRoot, RULES_BASE, ruleDirName);
158
+ const destRulePath = path.join(destRuleDir, 'RULE.mdc');
159
+ if (!overwrite && fileExists(destRulePath))
160
+ continue;
161
+ ensureDir(destRuleDir);
162
+ writeFile(destRulePath, readFile(srcRulePath));
163
+ }
44
164
  }
45
- function generateSkills(projectRoot, config) {
165
+ /**
166
+ * Inject or update `source` and `source_synced` fields in SKILL.md frontmatter.
167
+ * This allows tracking where a Skill was copied from without losing the original content.
168
+ */
169
+ function injectSourceMeta(content, scope) {
170
+ const today = new Date().toISOString().slice(0, 10);
171
+ const sourceTag = `source: "${scope}"\nsource_synced: "${today}"`;
172
+ // If frontmatter exists, inject/replace source fields
173
+ if (content.startsWith('---\n')) {
174
+ const endIdx = content.indexOf('\n---\n', 4);
175
+ if (endIdx !== -1) {
176
+ let frontmatter = content.slice(4, endIdx);
177
+ // Remove existing source / source_synced lines
178
+ frontmatter = frontmatter
179
+ .replace(/^source:.*\n?/m, '')
180
+ .replace(/^source_synced:.*\n?/m, '');
181
+ const newFrontmatter = frontmatter.trimEnd() + '\n' + sourceTag;
182
+ return `---\n${newFrontmatter}\n---\n${content.slice(endIdx + 5)}`;
183
+ }
184
+ }
185
+ // No frontmatter — prepend one
186
+ return `---\n${sourceTag}\n---\n\n${content}`;
187
+ }
188
+ // ---------------------------------------------------------------------------
189
+ // Skills
190
+ // ---------------------------------------------------------------------------
191
+ function generateSkills(projectRoot, _config) {
46
192
  for (const skillId of FRAMEWORK_SKILLS) {
47
193
  const templatePath = `skills/${SKILL_TEMPLATE_MAP[skillId]}`;
48
194
  let content;
@@ -57,7 +203,18 @@ function generateSkills(projectRoot, config) {
57
203
  writeFile(destPath, content);
58
204
  }
59
205
  }
206
+ // ---------------------------------------------------------------------------
207
+ // Commands
208
+ // ---------------------------------------------------------------------------
60
209
  function generateCommands(projectRoot, config) {
210
+ // Generate root /modus command (always, regardless of enabled list)
211
+ try {
212
+ const rootContent = readTemplate('commands/modus.md');
213
+ writeFile(path.join(projectRoot, COMMANDS_ROOT, 'modus.md'), rootContent);
214
+ }
215
+ catch {
216
+ console.warn(' [warn] Root command template not found: commands/modus.md');
217
+ }
61
218
  const enabled = new Set(config.commands.enabled);
62
219
  for (const cmdId of COMMAND_IDS) {
63
220
  if (!enabled.has(cmdId))
@@ -74,4 +231,200 @@ function generateCommands(projectRoot, config) {
74
231
  writeFile(destPath, content);
75
232
  }
76
233
  }
234
+ // ---------------------------------------------------------------------------
235
+ // Agents — CodeBuddy agentic SubAgent definitions
236
+ // ---------------------------------------------------------------------------
237
+ function generateAgents(projectRoot, _config) {
238
+ for (const agentId of HARNESS_AGENTS) {
239
+ const templatePath = `agents/${agentId}.md`;
240
+ let content;
241
+ try {
242
+ content = readTemplate(templatePath);
243
+ }
244
+ catch {
245
+ console.warn(` [warn] Agent template not found: ${templatePath}`);
246
+ continue;
247
+ }
248
+ const destPath = path.join(projectRoot, AGENTS_BASE, `${agentId}.md`);
249
+ writeFile(destPath, content);
250
+ }
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // Hooks — scripts + settings.json merge
254
+ // ---------------------------------------------------------------------------
255
+ function generateHooks(projectRoot, _config) {
256
+ // 1. Copy hook scripts and set executable permission
257
+ for (const script of HOOK_SCRIPTS) {
258
+ const templatePath = `hooks/${script}`;
259
+ let content;
260
+ try {
261
+ content = readTemplate(templatePath);
262
+ }
263
+ catch {
264
+ console.warn(` [warn] Hook script template not found: ${templatePath}`);
265
+ continue;
266
+ }
267
+ const destPath = path.join(projectRoot, HOOKS_BASE, script);
268
+ writeFile(destPath, content);
269
+ try {
270
+ fs.chmodSync(destPath, 0o755);
271
+ }
272
+ catch {
273
+ // chmod may fail on some platforms; non-fatal
274
+ }
275
+ }
276
+ // 2. Merge hook configuration into .codebuddy/settings.json
277
+ const hooksConfigTemplate = readTemplateJson('hooks-config.json');
278
+ if (!hooksConfigTemplate) {
279
+ console.warn(' [warn] hooks-config.json template not found, skipping settings.json update');
280
+ return;
281
+ }
282
+ // Rewrite hook command paths to use absolute project-relative path
283
+ const hooksConfigStr = JSON.stringify(hooksConfigTemplate)
284
+ .replace(/\$CODEBUDDY_PROJECT_DIR\//g, path.join(projectRoot, '.codebuddy', 'hooks', '').replace(/\\/g, '/'));
285
+ const hooksConfig = JSON.parse(hooksConfigStr);
286
+ mergeSettings(projectRoot, hooksConfig);
287
+ }
288
+ // ---------------------------------------------------------------------------
289
+ // Rules — CodeBuddy rules in .codebuddy/rules/
290
+ // ---------------------------------------------------------------------------
291
+ function generateRules(projectRoot, config) {
292
+ for (const ruleDir of RULE_DIRS) {
293
+ const templatePath = `rules/${ruleDir}/RULE.mdc`;
294
+ let content;
295
+ try {
296
+ content = readTemplate(templatePath);
297
+ }
298
+ catch {
299
+ console.warn(` [warn] Rule template not found: ${templatePath}`);
300
+ continue;
301
+ }
302
+ // For modus-constitution: substitute {{PLACEHOLDERS}} from config
303
+ if (ruleDir === 'modus-constitution') {
304
+ content = fillConstitutionTemplate(content, config);
305
+ }
306
+ const destPath = path.join(projectRoot, RULES_BASE, ruleDir, 'RULE.mdc');
307
+ writeFile(destPath, content);
308
+ }
309
+ }
310
+ /** Substitute {{PLACEHOLDERS}} in the constitution rule template with config values. */
311
+ function fillConstitutionTemplate(template, config) {
312
+ const any = config;
313
+ const constitution = any['constitution'] ?? {};
314
+ const techStack = String(constitution['tech_stack'] ?? config.techStack ?? '(请在 modus/config.yaml 中填写 constitution.tech_stack)');
315
+ const buildCmd = String(constitution['build_command'] ?? '(请在 modus/config.yaml 中填写 constitution.build_command)');
316
+ const testCmd = String(constitution['test_command'] ?? '(请在 modus/config.yaml 中填写 constitution.test_command)');
317
+ const hardRules = Array.isArray(constitution['hard_rules'])
318
+ ? constitution['hard_rules'].map((r) => `- ${r}`).join('\n')
319
+ : '(请在 modus/config.yaml 中填写 constitution.hard_rules)';
320
+ const keyPatterns = Array.isArray(constitution['key_patterns'])
321
+ ? constitution['key_patterns'].map((p) => `- ${p}`).join('\n')
322
+ : '(暂无,可在 modus/config.yaml 中填写 constitution.key_patterns)';
323
+ return template
324
+ .replace('{{TECH_STACK}}', techStack)
325
+ .replace('{{BUILD_COMMAND}}', buildCmd)
326
+ .replace('{{TEST_COMMAND}}', testCmd)
327
+ .replace('{{HARD_RULES}}', hardRules)
328
+ .replace('{{KEY_PATTERNS}}', keyPatterns);
329
+ }
330
+ // ---------------------------------------------------------------------------
331
+ // MCP Config — placeholder stubs in .codebuddy/settings.json
332
+ // ---------------------------------------------------------------------------
333
+ function generateMcpConfig(projectRoot, config) {
334
+ // Start with any MCP servers collected during `modus init`
335
+ const userServers = { ...(config.mcpServers ?? {}) };
336
+ // If tapdProjectId is set but no tapd server configured yet, add a hint entry
337
+ if (config.tapdProjectId && !('tapd' in userServers)) {
338
+ userServers['__tapd_hint__'] = {
339
+ _comment: `Modus: tapdProjectId=${config.tapdProjectId} detected. Replace this entry with your TAPD MCP server config.`,
340
+ type: 'stdio',
341
+ command: 'npx',
342
+ args: ['-y', '@your-org/tapd-mcp-server'],
343
+ };
344
+ }
345
+ const mcpSection = {
346
+ mcpServers: userServers,
347
+ };
348
+ mergeSettings(projectRoot, mcpSection);
349
+ }
350
+ // ---------------------------------------------------------------------------
351
+ // Helpers
352
+ // ---------------------------------------------------------------------------
353
+ /** Read a template JSON file and parse it. Returns null on error. */
354
+ function readTemplateJson(templateRelPath) {
355
+ try {
356
+ const raw = readTemplate(templateRelPath);
357
+ return JSON.parse(raw);
358
+ }
359
+ catch {
360
+ return null;
361
+ }
362
+ }
363
+ /**
364
+ * Deep-merges `patch` into the existing `.codebuddy/settings.json`.
365
+ * Existing keys are preserved; only missing keys are added.
366
+ * For the `hooks` field, each event array is merged by appending new entries.
367
+ */
368
+ function mergeSettings(projectRoot, patch) {
369
+ const settingsPath = path.join(projectRoot, SETTINGS_PATH);
370
+ let existing = {};
371
+ if (fileExists(settingsPath)) {
372
+ try {
373
+ existing = JSON.parse(readFile(settingsPath));
374
+ }
375
+ catch {
376
+ console.warn(' [warn] Could not parse existing settings.json; will overwrite');
377
+ existing = {};
378
+ }
379
+ }
380
+ const merged = deepMergeSettings(existing, patch);
381
+ writeFile(settingsPath, JSON.stringify(merged, null, 2) + '\n');
382
+ }
383
+ /**
384
+ * Merge strategy:
385
+ * - `hooks` field: per-event arrays are merged (no duplicate commands)
386
+ * - `mcpServers` field: object keys are merged (existing servers preserved)
387
+ * - Other fields: existing value wins (do not overwrite user config)
388
+ */
389
+ function deepMergeSettings(existing, patch) {
390
+ const result = { ...existing };
391
+ for (const [key, patchVal] of Object.entries(patch)) {
392
+ if (!(key in result)) {
393
+ result[key] = patchVal;
394
+ continue;
395
+ }
396
+ if (key === 'hooks') {
397
+ result[key] = mergeHooks(existing[key], patchVal);
398
+ }
399
+ else if (key === 'mcpServers') {
400
+ // Merge mcpServers: preserve existing, add new keys only
401
+ const existingServers = existing[key] ?? {};
402
+ const patchServers = patchVal ?? {};
403
+ result[key] = { ...patchServers, ...existingServers };
404
+ }
405
+ else {
406
+ // Existing value wins
407
+ result[key] = existing[key];
408
+ }
409
+ }
410
+ return result;
411
+ }
412
+ /**
413
+ * Merge hook event arrays.
414
+ * Deduplicates by `command` string so re-running `modus update` is idempotent.
415
+ */
416
+ function mergeHooks(existing, patch) {
417
+ const result = { ...(existing ?? {}) };
418
+ for (const [event, patchEntries] of Object.entries(patch)) {
419
+ if (!(event in result)) {
420
+ result[event] = patchEntries;
421
+ continue;
422
+ }
423
+ const existingEntries = result[event];
424
+ const existingCommands = new Set(existingEntries.flatMap((e) => (e.hooks ?? []).map((h) => h.command ?? '')));
425
+ const newEntries = patchEntries.filter((entry) => (entry.hooks ?? []).some((h) => h.command && !existingCommands.has(h.command)));
426
+ result[event] = [...existingEntries, ...newEntries];
427
+ }
428
+ return result;
429
+ }
77
430
  //# sourceMappingURL=codebuddy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"codebuddy.js","sourceRoot":"","sources":["../../src/generators/codebuddy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codebuddy.js","sourceRoot":"","sources":["../../src/generators/codebuddy.ts"],"names":[],"mappings":"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"}
@@ -6,8 +6,25 @@ export interface ModusConfig {
6
6
  context?: string;
7
7
  techStack?: string;
8
8
  tapdProjectId?: string;
9
+ /**
10
+ * Team name — references ~/.codebuddy/team/{teamName}/ for Skills/Rules reuse.
11
+ * Leave empty to skip team-level scoping.
12
+ */
13
+ teamName?: string;
14
+ /** MCP server configs collected during `modus init`. Written to .codebuddy/settings.json. */
15
+ mcpServers?: Record<string, unknown>;
9
16
  }
10
17
  export declare function getConfigPath(projectRoot: string): string;
18
+ /**
19
+ * Returns the global Modus directory: ~/.codebuddy/global/
20
+ * Stores organization-wide Skills and Rules (code style, security conventions).
21
+ */
22
+ export declare function getGlobalDir(): string;
23
+ /**
24
+ * Returns the team-scoped directory: ~/.codebuddy/team/{teamName}/
25
+ * Stores team-specific business memory (domain Skills, team conventions).
26
+ */
27
+ export declare function getTeamDir(teamName: string): string;
11
28
  export declare function loadConfig(projectRoot: string): ModusConfig;
12
29
  export declare function saveConfig(projectRoot: string, config: ModusConfig): void;
13
30
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AASD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAK3D;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAIzE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AASD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAK3D;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAIzE"}
@@ -1,4 +1,5 @@
1
1
  import path from 'node:path';
2
+ import os from 'node:os';
2
3
  import yaml from 'js-yaml';
3
4
  import { fileExists, readFile, writeFile } from './file-system.js';
4
5
  const DEFAULT_CONFIG = {
@@ -10,6 +11,20 @@ const DEFAULT_CONFIG = {
10
11
  export function getConfigPath(projectRoot) {
11
12
  return path.join(projectRoot, 'modus', 'config.yaml');
12
13
  }
14
+ /**
15
+ * Returns the global Modus directory: ~/.codebuddy/global/
16
+ * Stores organization-wide Skills and Rules (code style, security conventions).
17
+ */
18
+ export function getGlobalDir() {
19
+ return path.join(os.homedir(), '.codebuddy', 'global');
20
+ }
21
+ /**
22
+ * Returns the team-scoped directory: ~/.codebuddy/team/{teamName}/
23
+ * Stores team-specific business memory (domain Skills, team conventions).
24
+ */
25
+ export function getTeamDir(teamName) {
26
+ return path.join(os.homedir(), '.codebuddy', 'team', teamName);
27
+ }
13
28
  export function loadConfig(projectRoot) {
14
29
  const configPath = getConfigPath(projectRoot);
15
30
  if (!fileExists(configPath))
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAYnE,MAAM,cAAc,GAAgB;IAClC,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE;QACR,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACrD;CACF,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAmB;IAC5C,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAgB,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAmB,EAAE,MAAmB;IACjE,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAmBnE,MAAM,cAAc,GAAgB;IAClC,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE;QACR,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACrD;CACF,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAmB;IAC5C,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAgB,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAmB,EAAE,MAAmB;IACjE,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modus-ai/modus",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Modus — Business-grounded AI coding accelerator for CodeBuddy IDE",
5
5
  "keywords": [
6
6
  "ai",
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: modus-harness-00-skills-builder
3
+ description: Use this agent when any Modus workflow needs to create, update, or extract knowledge to/from Business Skill files. Examples: - Harness orchestrator calls this during INIT phase to refresh business Skills before analysis. - /modus:plan calls this for pre/post Skill update. - /modus:init calls this to generate initial Business Skill files from codebase scan. - Harness ARCHIVE phase calls this to extract decision/guideline/pitfall from artifacts into Skills.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob, Bash
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-00-skills-builder/SKILL.md` 中的执行规范和五种工作模式(A: 新建 Skill / B: 增量更新 / C: 知识回写 / D: Harness 归档提取 / E: 基础 Skill 初始化)。
11
+
12
+ 调用方必须在 prompt 中明确指定工作模式(A/B/C/D/E)和目标业务域列表。
@@ -0,0 +1,40 @@
1
+ # modus-harness-01-5-design
2
+
3
+ SubAgent 01.5 — 设计方案生成。
4
+
5
+ ## Instructions
6
+
7
+ Read and follow the skill at `.codebuddy/skills/modus-harness-agents/01-5-design/SKILL.md` to execute this SubAgent.
8
+
9
+ ## Quick Summary
10
+
11
+ 1. Read `modus/plans/active/{story-id}/01-analysis.md` and its HANDOFF block
12
+ 2. Load relevant business Skills (passed in by Orchestrator)
13
+ 3. Ask 1-3 architecture clarification questions (AskUserQuestion)
14
+ 4. Generate `01.5-design-brief.md` with full 9-section design-brief
15
+ 5. Write HANDOFF block with `gate_status`
16
+ 6. Output progress card for Orchestrator
17
+
18
+ ## Input
19
+
20
+ - `01-analysis.md` — requirements analysis from SubAgent 01
21
+ - Business Skill files — loaded by Orchestrator in INIT phase
22
+ - `modus/config.yaml` — constitution and project constraints
23
+ - Architecture decisions — confirmed by user in Step 2
24
+
25
+ ## Output
26
+
27
+ ```
28
+ modus/plans/active/{story-id}/01.5-design-brief.md
29
+ ```
30
+
31
+ Contains:
32
+ - HANDOFF block (machine-readable, for Orchestrator Gate A0 check)
33
+ - 9-section design-brief (human-readable, for SubAgent 02 coding reference)
34
+
35
+ ## Gate A0
36
+
37
+ Orchestrator checks this file's HANDOFF block before starting SubAgent 02:
38
+ - `gate_status: passed` → proceed to SubAgent 02
39
+ - `gate_status: warning` → proceed with note (SubAgent 02 handles ⚠️ items)
40
+ - `gate_status: failed` → re-run SubAgent 01.5 (max 2 retries)
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: modus-harness-01-analysis
3
+ description: Use this agent when the Harness orchestrator needs to perform requirements analysis for a TAPD Story. Fetches the story content, identifies affected business domains and code files at method level, assesses risk level, and produces 01-analysis.md with a machine-readable HANDOFF block. Triggered as the first sequential step in Harness Loop 1 after knowledge injection.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob, WebFetch
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-01-analysis/SKILL.md` 中的执行规范。
11
+
12
+ 产出物路径:`modus/plans/active/{story-id}/01-analysis.md`
13
+
14
+ 产出物头部必须包含 HANDOFF 块,包含 `agent`、`story_id`、`domains`、`risk_level`、`key_constraints`、`skill_refs`、`gate_status` 字段。
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: modus-harness-02-dev
3
+ description: Use this agent when the Harness orchestrator needs to implement code based on 01-analysis.md. Implements changes layer by layer (data → service → orchestration → interface), runs build compilation as Gate A check, and produces 02-sprint-contract.md. Also triggered during Loop 2 re-entry to fix P1/P2 issues identified in cr-report.md.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob, Bash
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-02-dev/SKILL.md` 中的执行规范。
11
+
12
+ 输入依赖:`modus/plans/active/{story-id}/01-analysis.md` 的 HANDOFF 块 + 相关业务 Skill 内容(由 Orchestrator 传入)。
13
+
14
+ 产出物路径:`modus/plans/active/{story-id}/02-sprint-contract.md` + 实际代码变更。
15
+
16
+ 完成后执行 `constitution.build_command` 进行 Gate A 编译验证,exit code 必须为 0。
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: modus-harness-03-test
3
+ description: Use this agent when the Harness orchestrator needs to generate unit tests for code changes after Gate A passes. Covers Happy Path, boundary conditions (null/empty/max), exception paths (lock failure, transaction rollback, auth check), and concurrency scenarios using @MockBean to isolate dependencies. Runs in parallel with SubAgents 04 and 05.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob, Bash
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-03-test/SKILL.md` 中的执行规范。
11
+
12
+ 输入依赖:`modus/plans/active/{story-id}/02-sprint-contract.md` 的 HANDOFF 块 + 代码变更文件。
13
+
14
+ 产出物路径:`modus/plans/active/{story-id}/03-test-report.md` + 单元测试代码文件。
15
+
16
+ 产出物头部必须包含 HANDOFF 块。
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: modus-harness-04-perf
3
+ description: Use this agent when the Harness orchestrator needs to perform static performance audit on code changes after Gate A passes. Detects N+1 queries (DB calls inside loops), missing batch operations, unbounded large data fetches without pagination protection, ES queries missing fetchSource/trackTotalHits, and deep pagination risks. Runs in parallel with SubAgents 03 and 05.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-04-perf/SKILL.md` 中的执行规范。
11
+
12
+ 输入依赖:`modus/plans/active/{story-id}/02-sprint-contract.md` 的 HANDOFF 块 + 代码变更文件。
13
+
14
+ 产出物路径:`modus/plans/active/{story-id}/04-perf-report.md`。
15
+
16
+ 每个风险点需量化影响(如 N 条数据 → N 次 SQL),按高/中/低分级输出。产出物头部必须包含 HANDOFF 块。
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: modus-harness-05-security
3
+ description: Use this agent when the Harness orchestrator needs to perform security audit on code changes after Gate A passes. Checks multi-tenant data isolation (tenantId source), missing @UserAuthorization on Facade layer, sensitive data logging (bank card/ID/phone), SQL injection via ${} concatenation, and bypass interfaces lacking tenantId protection. Runs in parallel with SubAgents 03 and 04.
4
+ agentMode: agentic
5
+ tools: Read, Write, Glob
6
+ enabledAutoRun: true
7
+ enabled: true
8
+ ---
9
+
10
+ 读取并严格遵循 `.codebuddy/skills/modus-harness-05-security/SKILL.md` 中的执行规范。
11
+
12
+ 输入依赖:`modus/plans/active/{story-id}/02-sprint-contract.md` 的 HANDOFF 块 + 代码变更文件。
13
+
14
+ 产出物路径:`modus/plans/active/{story-id}/05-security-report.md`。
15
+
16
+ 按严重/高/低三级输出,产出物头部必须包含 HANDOFF 块。