@dusky-bluehour/agent-service 0.6.4 → 0.6.6

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 (53) hide show
  1. package/README.md +33 -222
  2. package/antigravity/README.md +7 -1
  3. package/antigravity/agents/agent-catalog.json +5 -5
  4. package/antigravity/skills/change-safety-review/SKILL.md +40 -0
  5. package/antigravity/skills/code-review-and-improvement/SKILL.md +20 -0
  6. package/antigravity/skills/frontend-repetition-pack/SKILL.md +20 -0
  7. package/antigravity/skills/incident-response/SKILL.md +20 -0
  8. package/antigravity/skills/prd-to-production-pipeline/SKILL.md +21 -1
  9. package/antigravity/skills/release-and-operations/SKILL.md +20 -0
  10. package/antigravity/skills/security-hardening/SKILL.md +21 -1
  11. package/antigravity/skills/service-lifecycle-orchestration/SKILL.md +21 -1
  12. package/antigravity/workflows/definitions/WF-FRONTEND-REFACTOR.workflow.yaml +38 -0
  13. package/antigravity/workflows/definitions/WF-INCIDENT-RESPONSE.workflow.yaml +41 -0
  14. package/antigravity/workflows/definitions/WF-PRD-TO-PRODUCTION.workflow.yaml +76 -0
  15. package/antigravity/workflows/definitions/WF-SECURITY-HARDENING.workflow.yaml +40 -0
  16. package/antigravity/workflows/definitions/WF-SERVICE-E2E.workflow.yaml +67 -0
  17. package/antigravity/workflows/workflow-catalog.json +5 -5
  18. package/catalog/tool-catalog.ko.json +1 -1
  19. package/claude-code/README.md +4 -1
  20. package/claude-code/agent-teams/team-catalog.json +7 -7
  21. package/claude-code/skills/change-safety-review/SKILL.md +40 -0
  22. package/claude-code/skills/code-review-and-improvement/SKILL.md +21 -1
  23. package/claude-code/skills/frontend-repetition-pack/SKILL.md +21 -1
  24. package/claude-code/skills/incident-response/SKILL.md +21 -1
  25. package/claude-code/skills/prd-to-production-pipeline/SKILL.md +21 -1
  26. package/claude-code/skills/release-and-operations/SKILL.md +21 -1
  27. package/claude-code/skills/security-hardening/SKILL.md +21 -1
  28. package/claude-code/skills/service-lifecycle-orchestration/SKILL.md +21 -1
  29. package/claude-code/workflows/workflow-catalog.json +8 -8
  30. package/codex/README.md +5 -2
  31. package/codex/automations/automation-recipes.toml +4 -4
  32. package/codex/instructions/AGENTS.template.md +6 -5
  33. package/codex/skills/change-safety-review/SKILL.md +40 -0
  34. package/codex/skills/change-safety-review/agents/openai.yaml +4 -0
  35. package/codex/skills/code-review-and-improvement/SKILL.md +21 -1
  36. package/codex/skills/frontend-repetition-pack/SKILL.md +20 -0
  37. package/codex/skills/incident-response/SKILL.md +21 -1
  38. package/codex/skills/prd-to-production-pipeline/SKILL.md +21 -1
  39. package/codex/skills/release-and-operations/SKILL.md +20 -0
  40. package/codex/skills/security-hardening/SKILL.md +21 -1
  41. package/codex/skills/service-lifecycle-orchestration/SKILL.md +21 -1
  42. package/codex/workflows/workflow-catalog.json +6 -6
  43. package/common/antigravity/agent-catalog.json +72 -0
  44. package/common/antigravity/artifact-catalog.json +184 -0
  45. package/common/claude/subagent-catalog.json +419 -0
  46. package/common/claude/team-catalog.json +69 -0
  47. package/common/commands/command-catalog.json +942 -0
  48. package/common/skills/skill-catalog.json +566 -0
  49. package/common/workflows/workflow-catalog.json +1550 -0
  50. package/package.json +7 -4
  51. package/scripts/generate-from-common.mjs +387 -0
  52. package/scripts/init.mjs +81 -8
  53. package/scripts/validate.mjs +249 -2
@@ -188,6 +188,189 @@ async function validateCatalog() {
188
188
  }
189
189
  }
190
190
 
191
+ async function validateCommonSources() {
192
+ const requiredJsonFiles = [
193
+ 'common/commands/command-catalog.json',
194
+ 'common/workflows/workflow-catalog.json',
195
+ 'common/skills/skill-catalog.json',
196
+ 'common/claude/subagent-catalog.json',
197
+ 'common/claude/team-catalog.json',
198
+ 'common/antigravity/agent-catalog.json',
199
+ 'common/antigravity/artifact-catalog.json'
200
+ ];
201
+
202
+ const commonData = {};
203
+ for (const relPath of requiredJsonFiles) {
204
+ const fullPath = path.join(rootDir, relPath);
205
+ if (!(await exists(fullPath))) {
206
+ fail(`[common] 파일 누락: ${relPath}`);
207
+ continue;
208
+ }
209
+ try {
210
+ commonData[relPath] = await readJson(fullPath);
211
+ } catch (error) {
212
+ fail(`[common] JSON 파싱 실패: ${relPath} (${error.message})`);
213
+ }
214
+ }
215
+
216
+ const workflowCatalog = commonData['common/workflows/workflow-catalog.json'];
217
+ if (workflowCatalog) {
218
+ if (!Array.isArray(workflowCatalog.tools) || workflowCatalog.tools.length === 0) {
219
+ fail('[common/workflows] tools 배열 누락 또는 비어 있음');
220
+ }
221
+
222
+ const toolSet = new Set(Array.isArray(workflowCatalog.tools) ? workflowCatalog.tools : []);
223
+ for (const toolId of toolDirs) {
224
+ if (!toolSet.has(toolId)) {
225
+ fail(`[common/workflows] tools에 필수 tool 누락: ${toolId}`);
226
+ }
227
+ }
228
+
229
+ if (!workflowCatalog.workflow_policy || typeof workflowCatalog.workflow_policy !== 'object') {
230
+ fail('[common/workflows] workflow_policy 누락');
231
+ } else {
232
+ for (const toolId of toolSet) {
233
+ if (!(toolId in workflowCatalog.workflow_policy)) {
234
+ fail(`[common/workflows] workflow_policy 누락: ${toolId}`);
235
+ }
236
+ }
237
+ }
238
+
239
+ if (!Array.isArray(workflowCatalog.workflows) || workflowCatalog.workflows.length === 0) {
240
+ fail('[common/workflows] workflows 배열 누락 또는 비어 있음');
241
+ } else {
242
+ const workflowIds = new Set();
243
+ const workflowMap = new Map();
244
+ for (const workflow of workflowCatalog.workflows) {
245
+ if (!workflow?.id) {
246
+ fail('[common/workflows] workflow id 누락');
247
+ continue;
248
+ }
249
+ if (workflowIds.has(workflow.id)) {
250
+ fail(`[common/workflows] 중복 workflow id: ${workflow.id}`);
251
+ }
252
+ workflowIds.add(workflow.id);
253
+ workflowMap.set(workflow.id, workflow);
254
+
255
+ if (!workflow.profiles || typeof workflow.profiles !== 'object') {
256
+ fail(`[common/workflows] profiles 누락: ${workflow.id}`);
257
+ continue;
258
+ }
259
+
260
+ const profileTools = Object.keys(workflow.profiles);
261
+ if (profileTools.length === 0) {
262
+ fail(`[common/workflows] profile 비어 있음: ${workflow.id}`);
263
+ }
264
+
265
+ for (const toolId of profileTools) {
266
+ if (!toolSet.has(toolId)) {
267
+ fail(`[common/workflows] 알 수 없는 tool profile: ${workflow.id}/${toolId}`);
268
+ continue;
269
+ }
270
+ const profile = workflow.profiles[toolId];
271
+ if (!profile || typeof profile !== 'object') {
272
+ fail(`[common/workflows] profile 형식 오류: ${workflow.id}/${toolId}`);
273
+ continue;
274
+ }
275
+ if (!profile.name || !profile.summary || !profile.when_to_use) {
276
+ fail(`[common/workflows] profile 필수 필드 누락: ${workflow.id}/${toolId}`);
277
+ }
278
+ if (!Array.isArray(profile.stages) || profile.stages.length === 0) {
279
+ fail(`[common/workflows] profile stages 누락: ${workflow.id}/${toolId}`);
280
+ }
281
+ }
282
+ }
283
+
284
+ if (!workflowCatalog.workflow_order || typeof workflowCatalog.workflow_order !== 'object') {
285
+ fail('[common/workflows] workflow_order 누락');
286
+ } else {
287
+ for (const toolId of toolSet) {
288
+ const order = workflowCatalog.workflow_order[toolId];
289
+ if (!Array.isArray(order)) {
290
+ fail(`[common/workflows] workflow_order 형식 오류: ${toolId}`);
291
+ continue;
292
+ }
293
+ const seen = new Set();
294
+ for (const workflowId of order) {
295
+ if (!workflowIds.has(workflowId)) {
296
+ fail(`[common/workflows] workflow_order가 없는 id 참조: ${toolId}/${workflowId}`);
297
+ continue;
298
+ }
299
+ const workflow = workflowMap.get(workflowId);
300
+ if (!workflow?.profiles?.[toolId]) {
301
+ fail(`[common/workflows] workflow_order와 profile 불일치: ${toolId}/${workflowId}`);
302
+ }
303
+ if (seen.has(workflowId)) {
304
+ fail(`[common/workflows] workflow_order 중복: ${toolId}/${workflowId}`);
305
+ }
306
+ seen.add(workflowId);
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ const skillCatalog = commonData['common/skills/skill-catalog.json'];
314
+ if (skillCatalog) {
315
+ if (!Array.isArray(skillCatalog.skills) || skillCatalog.skills.length === 0) {
316
+ fail('[common/skills] skills 배열 누락 또는 비어 있음');
317
+ } else {
318
+ const toolSet = new Set(Array.isArray(skillCatalog.tools) ? skillCatalog.tools : []);
319
+ for (const toolId of toolDirs) {
320
+ if (!toolSet.has(toolId)) {
321
+ fail(`[common/skills] tools 누락: ${toolId}`);
322
+ }
323
+ }
324
+
325
+ const skillIds = new Set();
326
+ for (const skill of skillCatalog.skills) {
327
+ if (!skill?.id) {
328
+ fail('[common/skills] skill id 누락');
329
+ continue;
330
+ }
331
+ if (skillIds.has(skill.id)) {
332
+ fail(`[common/skills] 중복 skill id: ${skill.id}`);
333
+ }
334
+ skillIds.add(skill.id);
335
+
336
+ for (const toolId of toolSet) {
337
+ if (!skill.names?.[toolId] || !skill.descriptions?.[toolId]) {
338
+ fail(`[common/skills] 이름/설명 누락: ${skill.id}/${toolId}`);
339
+ }
340
+ if (!Array.isArray(skill.procedures?.[toolId]) || skill.procedures[toolId].length === 0) {
341
+ fail(`[common/skills] 실행 절차 누락: ${skill.id}/${toolId}`);
342
+ }
343
+ if (
344
+ !Array.isArray(skill.quality_rules?.[toolId]) ||
345
+ skill.quality_rules[toolId].length === 0
346
+ ) {
347
+ fail(`[common/skills] 품질 규칙 누락: ${skill.id}/${toolId}`);
348
+ }
349
+ }
350
+
351
+ if (!Array.isArray(skill.input_checklist) || skill.input_checklist.length === 0) {
352
+ fail(`[common/skills] 시작 전 체크리스트 누락: ${skill.id}`);
353
+ }
354
+ if (!Array.isArray(skill.report_format) || skill.report_format.length === 0) {
355
+ fail(`[common/skills] 결과 보고 형식 누락: ${skill.id}`);
356
+ }
357
+ if (!Array.isArray(skill.stop_conditions) || skill.stop_conditions.length === 0) {
358
+ fail(`[common/skills] 중단 조건 누락: ${skill.id}`);
359
+ }
360
+
361
+ if (!skill.codex_openai) {
362
+ fail(`[common/skills] codex_openai 누락: ${skill.id}`);
363
+ } else {
364
+ const ui = skill.codex_openai;
365
+ if (!ui.display_name || !ui.short_description || !ui.default_prompt) {
366
+ fail(`[common/skills] codex_openai 필수 필드 누락: ${skill.id}`);
367
+ }
368
+ }
369
+ }
370
+ }
371
+ }
372
+ }
373
+
191
374
  async function validatePackageJson() {
192
375
  const packagePath = path.join(rootDir, 'package.json');
193
376
  if (!(await exists(packagePath))) {
@@ -203,19 +386,32 @@ async function validatePackageJson() {
203
386
  return;
204
387
  }
205
388
 
206
- const requiredScripts = ['validate', 'pack:dry-run', 'prepublish:check', 'prepublishOnly'];
389
+ const requiredScripts = [
390
+ 'generate',
391
+ 'generate:check',
392
+ 'validate',
393
+ 'pack:dry-run',
394
+ 'prepublish:check',
395
+ 'prepublishOnly'
396
+ ];
207
397
  for (const scriptName of requiredScripts) {
208
398
  if (!pkg.scripts || !(scriptName in pkg.scripts)) {
209
399
  fail(`[package] scripts 누락: ${scriptName}`);
210
400
  }
211
401
  }
212
402
 
403
+ if (!pkg.bin || pkg.bin['tri-agent-manager'] !== 'scripts/init.mjs') {
404
+ fail('[package] bin 설정 오류: tri-agent-manager -> scripts/init.mjs 가 필요합니다.');
405
+ }
406
+
213
407
  const requiredFiles = [
408
+ 'common',
214
409
  'claude-code',
215
410
  'antigravity',
216
411
  'codex',
217
412
  'catalog/tool-catalog.ko.json',
218
413
  'scripts/init.mjs',
414
+ 'scripts/generate-from-common.mjs',
219
415
  'scripts/validate.mjs'
220
416
  ];
221
417
  for (const fileEntry of requiredFiles) {
@@ -228,7 +424,8 @@ async function validatePackageJson() {
228
424
  'docs/COMPOSITION.ko.md',
229
425
  'docs/DEPLOYMENT-GUIDE.ko.md',
230
426
  'docs/UPDATE-GUIDE.ko.md',
231
- 'docs/UX-FLOW.ko.md'
427
+ 'docs/UX-FLOW.ko.md',
428
+ 'docs/NPM-PUBLISH-REPO-ONLY.ko.md'
232
429
  ];
233
430
  for (const fileEntry of excludedFromPublish) {
234
431
  if (Array.isArray(pkg.files) && pkg.files.includes(fileEntry)) {
@@ -277,10 +474,29 @@ async function validateSkillDirectory(toolName) {
277
474
  fail(`[${toolName}] frontmatter name/description 누락: ${skillFile}`);
278
475
  }
279
476
 
477
+ for (const heading of [
478
+ '# 시작 전 체크리스트',
479
+ '# 실행 절차',
480
+ '# 결과 보고 형식',
481
+ '# 중단 조건',
482
+ '# 품질 규칙'
483
+ ]) {
484
+ if (!content.includes(heading)) {
485
+ fail(`[${toolName}] SKILL 섹션 누락: ${skillName}/${heading}`);
486
+ }
487
+ }
488
+
280
489
  if (toolName === 'codex') {
281
490
  const openaiYaml = path.join(skillsPath, skillName, 'agents', 'openai.yaml');
282
491
  if (!(await exists(openaiYaml))) {
283
492
  fail(`[codex] openai.yaml 누락: ${skillName}`);
493
+ } else {
494
+ const raw = await fs.readFile(openaiYaml, 'utf8');
495
+ for (const key of ['display_name', 'short_description', 'default_prompt']) {
496
+ if (!new RegExp(`\\b${key}:\\s+\".+\"`).test(raw)) {
497
+ fail(`[codex] openai.yaml 필수 필드 누락: ${skillName}/${key}`);
498
+ }
499
+ }
284
500
  }
285
501
  }
286
502
  }
@@ -447,6 +663,36 @@ async function validateAntigravityExtras() {
447
663
  fail(`[antigravity] JSON 파싱 실패: ${path.relative(rootDir, f)} (${error.message})`);
448
664
  }
449
665
  }
666
+
667
+ const workflowCatalogPath = path.join(rootDir, 'antigravity', 'workflows', 'workflow-catalog.json');
668
+ const workflowDefsDir = path.join(rootDir, 'antigravity', 'workflows', 'definitions');
669
+
670
+ if (!(await exists(workflowDefsDir))) {
671
+ fail('[antigravity] workflow definitions 디렉터리 누락');
672
+ return;
673
+ }
674
+
675
+ let workflowCatalog;
676
+ try {
677
+ workflowCatalog = await readJson(workflowCatalogPath);
678
+ } catch (error) {
679
+ fail(`[antigravity] workflow-catalog.json 파싱 실패: ${error.message}`);
680
+ return;
681
+ }
682
+
683
+ const workflowIds = new Set(
684
+ Array.isArray(workflowCatalog.workflows) ? workflowCatalog.workflows.map((wf) => wf.id) : []
685
+ );
686
+ const definitionFiles = (await fs.readdir(workflowDefsDir))
687
+ .filter((file) => file.endsWith('.workflow.yaml'))
688
+ .sort();
689
+
690
+ for (const workflowId of workflowIds) {
691
+ const expected = `${workflowId}.workflow.yaml`;
692
+ if (!definitionFiles.includes(expected)) {
693
+ fail(`[antigravity] workflow definition 누락: ${expected}`);
694
+ }
695
+ }
450
696
  }
451
697
 
452
698
  async function validateReadmes() {
@@ -621,6 +867,7 @@ async function runCliSmokeTests() {
621
867
 
622
868
  async function main() {
623
869
  await validatePackageJson();
870
+ await validateCommonSources();
624
871
  await validateCatalog();
625
872
  await validateReadmes();
626
873