@dusky-bluehour/agent-service 0.6.7 → 0.6.8
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.
- package/README.md +263 -36
- package/catalog/tool-catalog.ko.json +17 -43
- package/claude-code/README.md +84 -66
- package/codex/README.md +55 -33
- package/common/settings/security-policy.json +1 -1
- package/common/skills/skill-catalog.json +368 -136
- package/common/workflows/workflow-catalog.json +89 -1238
- package/gemini/README.md +104 -0
- package/{antigravity/commands/definitions/cmd-dev-be-api.md → gemini/commands/definitions/cmd-dev-be-api.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-fe-hook-separate.md → gemini/commands/definitions/cmd-dev-fe-hook-separate.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-fe-ui-componentize.md → gemini/commands/definitions/cmd-dev-fe-ui-componentize.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-perf-optimize.md → gemini/commands/definitions/cmd-dev-perf-optimize.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-sequential-autorun.md → gemini/commands/definitions/cmd-dev-sequential-autorun.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-doc-handoff.md → gemini/commands/definitions/cmd-doc-handoff.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-improve-techdebt.md → gemini/commands/definitions/cmd-improve-techdebt.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-incident-triage.md → gemini/commands/definitions/cmd-incident-triage.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-ci-cd-gate.md → gemini/commands/definitions/cmd-ops-ci-cd-gate.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-deploy.md → gemini/commands/definitions/cmd-ops-deploy.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-monitoring.md → gemini/commands/definitions/cmd-ops-monitoring.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-arch-decision.md → gemini/commands/definitions/cmd-plan-arch-decision.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-implementation-bootstrap.md → gemini/commands/definitions/cmd-plan-implementation-bootstrap.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-prd-details.md → gemini/commands/definitions/cmd-plan-prd-details.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-prd-master.md → gemini/commands/definitions/cmd-plan-prd-master.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-req-lock.md → gemini/commands/definitions/cmd-plan-req-lock.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-review-code.md → gemini/commands/definitions/cmd-review-code.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-sec-dependency-audit.md → gemini/commands/definitions/cmd-sec-dependency-audit.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-sec-threat-model.md → gemini/commands/definitions/cmd-sec-threat-model.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-test-unit-integration.md → gemini/commands/definitions/cmd-test-unit-integration.toml} +13 -21
- package/gemini/gemini-extension.json +6 -0
- package/{antigravity → gemini}/settings/editor-policy.json +1 -1
- package/{antigravity → gemini}/skills/change-safety-review/SKILL.md +8 -6
- package/{antigravity → gemini}/skills/code-review-and-improvement/SKILL.md +8 -3
- package/gemini/skills/frontend-repetition-pack/SKILL.md +44 -0
- package/gemini/skills/incident-response/SKILL.md +44 -0
- package/{antigravity → gemini}/skills/prd-to-production-pipeline/SKILL.md +13 -4
- package/{antigravity → gemini}/skills/release-and-operations/SKILL.md +11 -3
- package/gemini/skills/security-hardening/SKILL.md +43 -0
- package/gemini/skills/service-lifecycle-orchestration/SKILL.md +46 -0
- package/{antigravity → gemini}/workflows/workflow-catalog.json +1 -1
- package/package.json +4 -4
- package/scripts/generate-from-common.mjs +99 -70
- package/scripts/init.mjs +41 -21
- package/scripts/validate.mjs +66 -33
- package/antigravity/README.md +0 -50
- package/antigravity/skills/frontend-repetition-pack/SKILL.md +0 -35
- package/antigravity/skills/incident-response/SKILL.md +0 -35
- package/antigravity/skills/security-hardening/SKILL.md +0 -35
- package/antigravity/skills/service-lifecycle-orchestration/SKILL.md +0 -36
- package/claude-code/workflows/workflow-catalog.json +0 -688
- package/codex/workflows/workflow-catalog.json +0 -450
- /package/{antigravity/agents → common/gemini}/agent-catalog.json +0 -0
- /package/{antigravity/artifacts → common/gemini}/artifact-catalog.json +0 -0
- /package/{common/antigravity → gemini/agents}/agent-catalog.json +0 -0
- /package/{common/antigravity → gemini/artifacts}/artifact-catalog.json +0 -0
- /package/{antigravity → gemini}/commands/command-catalog.json +0 -0
- /package/{antigravity/instructions/WORKSPACE-RULES.template.md → gemini/instructions/GEMINI.template.md} +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-FRONTEND-REFACTOR.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-INCIDENT-RESPONSE.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-PRD-TO-PRODUCTION.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-SECURITY-HARDENING.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-SERVICE-E2E.workflow.yaml +0 -0
package/scripts/init.mjs
CHANGED
|
@@ -26,9 +26,9 @@ const PROJECT_RULE_BOOTSTRAP = {
|
|
|
26
26
|
sourceRelativePath: path.join('codex', 'instructions', 'AGENTS.template.md'),
|
|
27
27
|
destinationRelativePath: 'AGENTS.md'
|
|
28
28
|
},
|
|
29
|
-
|
|
30
|
-
sourceRelativePath: path.join('
|
|
31
|
-
destinationRelativePath: '
|
|
29
|
+
gemini: {
|
|
30
|
+
sourceRelativePath: path.join('gemini', 'instructions', 'GEMINI.template.md'),
|
|
31
|
+
destinationRelativePath: 'GEMINI.md'
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -48,7 +48,7 @@ const HELP_TEXT = [
|
|
|
48
48
|
' --tool 도구 선택 (예: codex,claude-code) / all',
|
|
49
49
|
' --components 구성요소 선택 (예: skills,workflows,commands) / all',
|
|
50
50
|
' --target 설치 경로 (기본: .)',
|
|
51
|
-
' --install-root 도구별 설치 루트 오버라이드 (예: codex=.codex,
|
|
51
|
+
' --install-root 도구별 설치 루트 오버라이드 (예: codex=.codex,gemini=.gemini)',
|
|
52
52
|
' --project-rules 프로젝트 규칙 파일 정책 (always|if-instructions|if-present|never)',
|
|
53
53
|
' --force install 시 기존 파일 덮어쓰기',
|
|
54
54
|
' --dry-run 복사하지 않고 작업 계획만 출력',
|
|
@@ -316,7 +316,7 @@ function parseInstallRootFlag(installRootFlag, catalog) {
|
|
|
316
316
|
const idx = token.indexOf('=');
|
|
317
317
|
if (idx <= 0 || idx === token.length - 1) {
|
|
318
318
|
throw new Error(
|
|
319
|
-
`--install-root 형식이 올바르지 않습니다: ${token} (예: codex=.codex,
|
|
319
|
+
`--install-root 형식이 올바르지 않습니다: ${token} (예: codex=.codex,gemini=.gemini)`
|
|
320
320
|
);
|
|
321
321
|
}
|
|
322
322
|
|
|
@@ -501,13 +501,9 @@ function getToolExecutionGuide(tool, installRoot) {
|
|
|
501
501
|
];
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
-
if (tool.id === '
|
|
504
|
+
if (tool.id === 'gemini') {
|
|
505
505
|
return [
|
|
506
|
-
|
|
507
|
-
installRoot,
|
|
508
|
-
'rules',
|
|
509
|
-
'workspace-core-rules.md'
|
|
510
|
-
)}\`(자동 생성됨)를 열고 운영 규칙을 확정합니다.`,
|
|
506
|
+
'`GEMINI.md`(자동 생성됨)를 열고 운영 규칙을 확정합니다.',
|
|
511
507
|
`\`${path.join(
|
|
512
508
|
installRoot,
|
|
513
509
|
'workflows',
|
|
@@ -558,13 +554,9 @@ function getToolInteractionTips(tool, installRoot) {
|
|
|
558
554
|
];
|
|
559
555
|
}
|
|
560
556
|
|
|
561
|
-
if (tool.id === '
|
|
557
|
+
if (tool.id === 'gemini') {
|
|
562
558
|
return [
|
|
563
|
-
|
|
564
|
-
installRoot,
|
|
565
|
-
'rules',
|
|
566
|
-
'workspace-core-rules.md'
|
|
567
|
-
)}\`를 Manager 단계의 승인 규칙 문서로 사용하세요.`,
|
|
559
|
+
'`GEMINI.md`를 Manager 단계의 승인 규칙 문서로 사용하세요.',
|
|
568
560
|
`워크플로우 선택은 \`${path.join(
|
|
569
561
|
installRoot,
|
|
570
562
|
'workflows',
|
|
@@ -744,11 +736,11 @@ function resolveComponentsFromFlag(componentFlag, tool, mode) {
|
|
|
744
736
|
}
|
|
745
737
|
|
|
746
738
|
function clearTuiScreen() {
|
|
747
|
-
output.write('\
|
|
739
|
+
output.write('\x1B[2J\x1B[H');
|
|
748
740
|
}
|
|
749
741
|
|
|
750
742
|
function formatTuiLine(prefix, label, selected = false) {
|
|
751
|
-
const marker = selected ? '
|
|
743
|
+
const marker = selected ? '\x1B[32m[x]\x1B[0m' : '[ ]';
|
|
752
744
|
return `${prefix} ${marker} ${label}`;
|
|
753
745
|
}
|
|
754
746
|
|
|
@@ -833,8 +825,8 @@ async function runMultiSelectMenu({
|
|
|
833
825
|
const selected = new Set(preselectedIds);
|
|
834
826
|
const optionRows = [
|
|
835
827
|
...choices.map((choice) => ({ kind: 'choice', ...choice })),
|
|
836
|
-
{ kind: 'action', action: 'toggle-all', label: '
|
|
837
|
-
{ kind: 'action', action: 'done', label: '
|
|
828
|
+
{ kind: 'action', action: 'toggle-all', label: '[*] 전체 선택/해제' },
|
|
829
|
+
{ kind: 'action', action: 'done', label: '[>] 선택 완료' }
|
|
838
830
|
];
|
|
839
831
|
let cursor = 0;
|
|
840
832
|
let notice = '';
|
|
@@ -1455,6 +1447,12 @@ function printPlan(catalog, selection, mode, targetDir, dryRun = false) {
|
|
|
1455
1447
|
);
|
|
1456
1448
|
console.log(`선택 도구 : ${selection.selectedToolIds.length}개`);
|
|
1457
1449
|
|
|
1450
|
+
let totalComponents = 0;
|
|
1451
|
+
for (const toolId of selection.selectedToolIds) {
|
|
1452
|
+
totalComponents += (selection.componentSelection[toolId] ?? []).length;
|
|
1453
|
+
}
|
|
1454
|
+
console.log(`총 구성요소 : ${totalComponents}개`);
|
|
1455
|
+
|
|
1458
1456
|
selection.selectedToolIds.forEach((toolId, index) => {
|
|
1459
1457
|
const tool = findTool(catalog, toolId);
|
|
1460
1458
|
if (!tool) {
|
|
@@ -1608,6 +1606,22 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1608
1606
|
|
|
1609
1607
|
const results = [];
|
|
1610
1608
|
|
|
1609
|
+
let totalSteps = 0;
|
|
1610
|
+
for (const toolId of selection.selectedToolIds) {
|
|
1611
|
+
const componentIds = selection.componentSelection[toolId] ?? [];
|
|
1612
|
+
totalSteps += 1 + componentIds.length + 1;
|
|
1613
|
+
}
|
|
1614
|
+
let currentStep = 0;
|
|
1615
|
+
const logStep = (label) => {
|
|
1616
|
+
currentStep += 1;
|
|
1617
|
+
const progress = `[${String(currentStep).padStart(String(totalSteps).length, ' ')}/${totalSteps}]`;
|
|
1618
|
+
if (output.isTTY) {
|
|
1619
|
+
output.write(`\r\x1B[K${progress} ${label}`);
|
|
1620
|
+
} else {
|
|
1621
|
+
console.log(`${progress} ${label}`);
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1611
1625
|
for (const toolId of selection.selectedToolIds) {
|
|
1612
1626
|
const tool = findTool(catalog, toolId);
|
|
1613
1627
|
if (!tool) {
|
|
@@ -1618,6 +1632,7 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1618
1632
|
const toolDestRoot = path.join(targetDir, installRoot);
|
|
1619
1633
|
await fs.mkdir(toolDestRoot, { recursive: true });
|
|
1620
1634
|
|
|
1635
|
+
logStep(`${tool.title} README 복사 중...`);
|
|
1621
1636
|
const readmeSrc = path.join(rootDir, tool.root, tool.readme);
|
|
1622
1637
|
const readmeDst = path.join(toolDestRoot, `README.tri-agent-manager.${tool.id}.md`);
|
|
1623
1638
|
const readmeResult = await copyEntry(readmeSrc, readmeDst, { overwrite, dryRun });
|
|
@@ -1635,6 +1650,7 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1635
1650
|
throw new Error(`[${tool.id}] 알 수 없는 구성요소: ${componentId}`);
|
|
1636
1651
|
}
|
|
1637
1652
|
|
|
1653
|
+
logStep(`${tool.title} ${component.title} 복사 중...`);
|
|
1638
1654
|
const src = path.join(rootDir, tool.root, component.path);
|
|
1639
1655
|
const componentInstallPath = getComponentInstallPath(component);
|
|
1640
1656
|
const dst = path.join(targetDir, installRoot, componentInstallPath);
|
|
@@ -1647,6 +1663,7 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1647
1663
|
});
|
|
1648
1664
|
}
|
|
1649
1665
|
|
|
1666
|
+
logStep(`${tool.title} 프로젝트 규칙 처리 중...`);
|
|
1650
1667
|
const ruleResult = await copyProjectRuleBootstrap({
|
|
1651
1668
|
toolId,
|
|
1652
1669
|
targetDir,
|
|
@@ -1661,6 +1678,9 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1661
1678
|
}
|
|
1662
1679
|
}
|
|
1663
1680
|
|
|
1681
|
+
if (output.isTTY) {
|
|
1682
|
+
output.write('\r\x1B[K');
|
|
1683
|
+
}
|
|
1664
1684
|
console.log('');
|
|
1665
1685
|
console.log('━━━━━━━━ 적용 결과 ━━━━━━━━');
|
|
1666
1686
|
const summaryCounter = {
|
package/scripts/validate.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
12
12
|
const __dirname = path.dirname(__filename);
|
|
13
13
|
const rootDir = path.resolve(__dirname, '..');
|
|
14
14
|
|
|
15
|
-
const toolDirs = ['claude-code', 'codex', '
|
|
15
|
+
const toolDirs = ['claude-code', 'codex', 'gemini'];
|
|
16
16
|
const errors = [];
|
|
17
17
|
|
|
18
18
|
function fail(message) {
|
|
@@ -208,8 +208,8 @@ async function validateCommonSources() {
|
|
|
208
208
|
'common/settings/security-policy.json',
|
|
209
209
|
'common/claude/subagent-catalog.json',
|
|
210
210
|
'common/claude/team-catalog.json',
|
|
211
|
-
'common/
|
|
212
|
-
'common/
|
|
211
|
+
'common/gemini/agent-catalog.json',
|
|
212
|
+
'common/gemini/artifact-catalog.json'
|
|
213
213
|
];
|
|
214
214
|
|
|
215
215
|
const commonData = {};
|
|
@@ -233,10 +233,8 @@ async function validateCommonSources() {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
const toolSet = new Set(Array.isArray(workflowCatalog.tools) ? workflowCatalog.tools : []);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
fail(`[common/workflows] tools에 필수 tool 누락: ${toolId}`);
|
|
239
|
-
}
|
|
236
|
+
if (!toolSet.has('gemini')) {
|
|
237
|
+
fail('[common/workflows] tools에 필수 tool 누락: gemini');
|
|
240
238
|
}
|
|
241
239
|
|
|
242
240
|
if (!workflowCatalog.workflow_policy || typeof workflowCatalog.workflow_policy !== 'object') {
|
|
@@ -371,6 +369,21 @@ async function validateCommonSources() {
|
|
|
371
369
|
fail(`[common/skills] 중단 조건 누락: ${skill.id}`);
|
|
372
370
|
}
|
|
373
371
|
|
|
372
|
+
for (const toolId of toolSet) {
|
|
373
|
+
const procedures = skill.procedures?.[toolId] ?? [];
|
|
374
|
+
for (const step of procedures) {
|
|
375
|
+
if (/\bCMD-[A-Z]/.test(step)) {
|
|
376
|
+
fail(`[common/skills] CMD-* 참조 금지 위반: ${skill.id}/${toolId} → "${step.slice(0, 60)}…"`);
|
|
377
|
+
}
|
|
378
|
+
if (/\bWF-[A-Z]/.test(step)) {
|
|
379
|
+
fail(`[common/skills] WF-* 참조 금지 위반: ${skill.id}/${toolId} → "${step.slice(0, 60)}…"`);
|
|
380
|
+
}
|
|
381
|
+
if (/\bART-[A-Z]/.test(step)) {
|
|
382
|
+
fail(`[common/skills] ART-* 참조 금지 위반: ${skill.id}/${toolId} → "${step.slice(0, 60)}…"`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
374
387
|
if (!skill.codex_openai) {
|
|
375
388
|
fail(`[common/skills] codex_openai 누락: ${skill.id}`);
|
|
376
389
|
} else {
|
|
@@ -444,7 +457,7 @@ async function validatePackageJson() {
|
|
|
444
457
|
const requiredFiles = [
|
|
445
458
|
'common',
|
|
446
459
|
'claude-code',
|
|
447
|
-
'
|
|
460
|
+
'gemini',
|
|
448
461
|
'codex',
|
|
449
462
|
'catalog/tool-catalog.ko.json',
|
|
450
463
|
'scripts/init.mjs',
|
|
@@ -718,28 +731,28 @@ async function validateCodexExtras(commandFileBases) {
|
|
|
718
731
|
}
|
|
719
732
|
}
|
|
720
733
|
|
|
721
|
-
async function
|
|
722
|
-
const agentCatalog = path.join(rootDir, '
|
|
723
|
-
const artifactCatalog = path.join(rootDir, '
|
|
734
|
+
async function validateGeminiExtras(commandFileBases) {
|
|
735
|
+
const agentCatalog = path.join(rootDir, 'gemini', 'agents', 'agent-catalog.json');
|
|
736
|
+
const artifactCatalog = path.join(rootDir, 'gemini', 'artifacts', 'artifact-catalog.json');
|
|
724
737
|
|
|
725
738
|
for (const f of [agentCatalog, artifactCatalog]) {
|
|
726
739
|
if (!(await exists(f))) {
|
|
727
|
-
fail(`[
|
|
740
|
+
fail(`[gemini] 누락: ${path.relative(rootDir, f)}`);
|
|
728
741
|
continue;
|
|
729
742
|
}
|
|
730
743
|
|
|
731
744
|
try {
|
|
732
745
|
await readJson(f);
|
|
733
746
|
} catch (error) {
|
|
734
|
-
fail(`[
|
|
747
|
+
fail(`[gemini] JSON 파싱 실패: ${path.relative(rootDir, f)} (${error.message})`);
|
|
735
748
|
}
|
|
736
749
|
}
|
|
737
750
|
|
|
738
|
-
const workflowCatalogPath = path.join(rootDir, '
|
|
739
|
-
const workflowDefsDir = path.join(rootDir, '
|
|
751
|
+
const workflowCatalogPath = path.join(rootDir, 'gemini', 'workflows', 'workflow-catalog.json');
|
|
752
|
+
const workflowDefsDir = path.join(rootDir, 'gemini', 'workflows', 'definitions');
|
|
740
753
|
|
|
741
754
|
if (!(await exists(workflowDefsDir))) {
|
|
742
|
-
fail('[
|
|
755
|
+
fail('[gemini] workflow definitions 디렉터리 누락');
|
|
743
756
|
return;
|
|
744
757
|
}
|
|
745
758
|
|
|
@@ -747,7 +760,7 @@ async function validateAntigravityExtras(commandFileBases) {
|
|
|
747
760
|
try {
|
|
748
761
|
workflowCatalog = await readJson(workflowCatalogPath);
|
|
749
762
|
} catch (error) {
|
|
750
|
-
fail(`[
|
|
763
|
+
fail(`[gemini] workflow-catalog.json 파싱 실패: ${error.message}`);
|
|
751
764
|
return;
|
|
752
765
|
}
|
|
753
766
|
|
|
@@ -761,23 +774,39 @@ async function validateAntigravityExtras(commandFileBases) {
|
|
|
761
774
|
for (const workflowId of workflowIds) {
|
|
762
775
|
const expected = `${workflowId}.workflow.yaml`;
|
|
763
776
|
if (!definitionFiles.includes(expected)) {
|
|
764
|
-
fail(`[
|
|
777
|
+
fail(`[gemini] workflow definition 누락: ${expected}`);
|
|
765
778
|
}
|
|
766
779
|
}
|
|
767
780
|
|
|
768
|
-
const commandDefinitionsDir = path.join(rootDir, '
|
|
781
|
+
const commandDefinitionsDir = path.join(rootDir, 'gemini', 'commands', 'definitions');
|
|
769
782
|
if (!(await exists(commandDefinitionsDir))) {
|
|
770
|
-
fail('[
|
|
783
|
+
fail('[gemini] commands/definitions 디렉터리 누락');
|
|
771
784
|
return;
|
|
772
785
|
}
|
|
773
786
|
|
|
774
787
|
const commandDefinitionFiles = new Set(
|
|
775
|
-
(await fs.readdir(commandDefinitionsDir)).filter((file) => file.endsWith('.
|
|
788
|
+
(await fs.readdir(commandDefinitionsDir)).filter((file) => file.endsWith('.toml'))
|
|
776
789
|
);
|
|
777
790
|
for (const base of commandFileBases) {
|
|
778
|
-
const expected = `${base}.
|
|
791
|
+
const expected = `${base}.toml`;
|
|
779
792
|
if (!commandDefinitionFiles.has(expected)) {
|
|
780
|
-
fail(`[
|
|
793
|
+
fail(`[gemini] command definition 누락: commands/definitions/${expected}`);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
const extensionJsonPath = path.join(rootDir, 'gemini', 'gemini-extension.json');
|
|
798
|
+
if (!(await exists(extensionJsonPath))) {
|
|
799
|
+
fail('[gemini] gemini-extension.json 누락');
|
|
800
|
+
} else {
|
|
801
|
+
try {
|
|
802
|
+
const extensionData = await readJson(extensionJsonPath);
|
|
803
|
+
for (const field of ['name', 'version', 'description']) {
|
|
804
|
+
if (!extensionData[field]) {
|
|
805
|
+
fail(`[gemini] gemini-extension.json 필수 필드 누락: ${field}`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
} catch (error) {
|
|
809
|
+
fail(`[gemini] gemini-extension.json 파싱 실패: ${error.message}`);
|
|
781
810
|
}
|
|
782
811
|
}
|
|
783
812
|
}
|
|
@@ -795,7 +824,7 @@ async function validateSettingsOutputs() {
|
|
|
795
824
|
const settingsFiles = [
|
|
796
825
|
'claude-code/settings/settings.json',
|
|
797
826
|
'claude-code/settings/settings.local.json',
|
|
798
|
-
'
|
|
827
|
+
'gemini/settings/editor-policy.json',
|
|
799
828
|
'codex/settings/runtime-policy.json'
|
|
800
829
|
];
|
|
801
830
|
|
|
@@ -857,7 +886,7 @@ async function validateProjectRuleTemplates() {
|
|
|
857
886
|
const requiredFiles = [
|
|
858
887
|
'claude-code/instructions/CLAUDE.template.md',
|
|
859
888
|
'codex/instructions/AGENTS.template.md',
|
|
860
|
-
'
|
|
889
|
+
'gemini/instructions/GEMINI.template.md'
|
|
861
890
|
];
|
|
862
891
|
|
|
863
892
|
for (const relPath of requiredFiles) {
|
|
@@ -893,7 +922,7 @@ async function runCliSmokeTests() {
|
|
|
893
922
|
'--tool',
|
|
894
923
|
'codex',
|
|
895
924
|
'--components',
|
|
896
|
-
'skills,
|
|
925
|
+
'skills,commands',
|
|
897
926
|
'--target',
|
|
898
927
|
'/tmp/tri-agent-manager-validate',
|
|
899
928
|
'--dry-run',
|
|
@@ -935,7 +964,7 @@ async function runCliSmokeTests() {
|
|
|
935
964
|
'--tool',
|
|
936
965
|
'codex',
|
|
937
966
|
'--components',
|
|
938
|
-
'skills,
|
|
967
|
+
'skills,commands',
|
|
939
968
|
'--target',
|
|
940
969
|
'/tmp/tri-agent-manager-validate',
|
|
941
970
|
'--dry-run',
|
|
@@ -955,11 +984,11 @@ async function runCliSmokeTests() {
|
|
|
955
984
|
cliPath,
|
|
956
985
|
'install',
|
|
957
986
|
'--tool',
|
|
958
|
-
'
|
|
987
|
+
'gemini',
|
|
959
988
|
'--components',
|
|
960
989
|
'skills,workflows',
|
|
961
990
|
'--install-root',
|
|
962
|
-
'
|
|
991
|
+
'gemini=.gemini-custom',
|
|
963
992
|
'--target',
|
|
964
993
|
'/tmp/tri-agent-manager-validate',
|
|
965
994
|
'--dry-run',
|
|
@@ -979,7 +1008,7 @@ async function runCliSmokeTests() {
|
|
|
979
1008
|
cliPath,
|
|
980
1009
|
'install',
|
|
981
1010
|
'--tool',
|
|
982
|
-
'
|
|
1011
|
+
'gemini',
|
|
983
1012
|
'--components',
|
|
984
1013
|
'skills',
|
|
985
1014
|
'--project-rules',
|
|
@@ -1045,7 +1074,7 @@ async function runCliSmokeTests() {
|
|
|
1045
1074
|
'--tool',
|
|
1046
1075
|
'codex',
|
|
1047
1076
|
'--components',
|
|
1048
|
-
'skills,
|
|
1077
|
+
'skills,commands',
|
|
1049
1078
|
'--target',
|
|
1050
1079
|
'/tmp/tri-agent-manager-validate',
|
|
1051
1080
|
'--dry-run',
|
|
@@ -1068,16 +1097,20 @@ async function main() {
|
|
|
1068
1097
|
await validateProjectRuleTemplates();
|
|
1069
1098
|
|
|
1070
1099
|
const commandFileBaseByTool = {};
|
|
1100
|
+
let geminiCommandIds = new Set();
|
|
1071
1101
|
for (const toolName of toolDirs) {
|
|
1072
1102
|
await validateSkillDirectory(toolName);
|
|
1073
1103
|
const { commandIds, commandFileBases } = await validateCommandCatalog(toolName);
|
|
1074
1104
|
commandFileBaseByTool[toolName] = commandFileBases;
|
|
1075
|
-
|
|
1105
|
+
if (toolName === 'gemini') {
|
|
1106
|
+
geminiCommandIds = commandIds;
|
|
1107
|
+
}
|
|
1076
1108
|
}
|
|
1109
|
+
await validateWorkflowCatalog('gemini', geminiCommandIds);
|
|
1077
1110
|
|
|
1078
1111
|
await validateClaudeExtras(commandFileBaseByTool['claude-code'] ?? new Set());
|
|
1079
1112
|
await validateCodexExtras(commandFileBaseByTool.codex ?? new Set());
|
|
1080
|
-
await
|
|
1113
|
+
await validateGeminiExtras(commandFileBaseByTool.gemini ?? new Set());
|
|
1081
1114
|
await runCliSmokeTests();
|
|
1082
1115
|
|
|
1083
1116
|
if (errors.length > 0) {
|
package/antigravity/README.md
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# Antigravity 운영팩
|
|
2
|
-
|
|
3
|
-
이 폴더는 Antigravity의 Manager-에이전트-Artifact 흐름을 기준으로, 서비스 운영 전체를 실행 가능한 형태로 정리한 패키지입니다.
|
|
4
|
-
정의 원천은 저장소 `common/*`이며, 이 폴더의 파일은 생성 스크립트(`npm run generate`) 결과입니다.
|
|
5
|
-
직접 수정 대신 공통 원천을 수정한 뒤 재생성해 주세요.
|
|
6
|
-
|
|
7
|
-
## 폴더 구성
|
|
8
|
-
|
|
9
|
-
- `skills/`: 역할별 실행 스킬
|
|
10
|
-
- `agents/agent-catalog.json`: 에이전트 역할 카탈로그
|
|
11
|
-
- `artifacts/artifact-catalog.json`: 단계별 Artifact 계약
|
|
12
|
-
- `workflows/workflow-catalog.json`: 오케스트레이션 워크플로우
|
|
13
|
-
- `workflows/definitions/*.workflow.yaml`: Antigravity 실행용 워크플로우 정의 파일
|
|
14
|
-
- `commands/command-catalog.json`: 공통 명령 계약
|
|
15
|
-
- `commands/definitions/*.md`: 공통 명령 계약에서 변환된 Antigravity 명령 정의 파일
|
|
16
|
-
- `instructions/WORKSPACE-RULES.template.md`: `.agent/rules/workspace-core-rules.md` 자동 생성용 템플릿
|
|
17
|
-
- `settings/editor-policy.json`: 에디터 반영용 보안/권한 정책 템플릿
|
|
18
|
-
|
|
19
|
-
## 빠른 시작
|
|
20
|
-
|
|
21
|
-
1. `WF-SERVICE-E2E`(기본 E2E), `WF-SECURITY-HARDENING`(보안), `WF-INCIDENT-RESPONSE`(장애 대응), `WF-PRD-TO-PRODUCTION`(PRD→구현) 등 목적별 워크플로우를 선택해 주세요.
|
|
22
|
-
2. 각 단계의 `input_artifact` 필드를 먼저 검증해 주세요.
|
|
23
|
-
3. 지정된 `agent`가 `commands`를 수행합니다.
|
|
24
|
-
4. `output_artifact` 검증 후 다음 단계로 진행해 주세요.
|
|
25
|
-
|
|
26
|
-
워크플로우 카탈로그에서 선택한 ID와 동일한 이름의 정의 파일을 `workflows/definitions/`에서 사용하시면 됩니다. 예: `WF-SERVICE-E2E.workflow.yaml`
|
|
27
|
-
명령 실행 시에는 `commands/definitions/`의 대응 파일(`cmd-*.md`)을 함께 참조해 입력/게이트/핸드오프를 고정해 주세요.
|
|
28
|
-
|
|
29
|
-
에디터 권한 정책은 `settings/editor-policy.json`을 기준으로 팀 표준을 맞춰 반영해 주세요.
|
|
30
|
-
설치 시 `<install-root>/rules/workspace-core-rules.md`가 자동 생성되며(기존 파일 유지), Manager 승인/운영 규칙 문서로 사용할 수 있습니다.
|
|
31
|
-
|
|
32
|
-
## 반복 작업 역할 분리
|
|
33
|
-
|
|
34
|
-
- UI 컴포넌트화: `frontend-repetition-agent` + `CMD-DEV-FE-UI-COMPONENTIZE`
|
|
35
|
-
- Hook 분리: `frontend-repetition-agent` + `CMD-DEV-FE-HOOK-SEPARATE`
|
|
36
|
-
- 성능 최적화: `performance-agent` + `CMD-DEV-PERF-OPTIMIZE`
|
|
37
|
-
- 변경점 안전 검토: `change-safety-review` + `CMD-TEST-UNIT-INTEGRATION`, `CMD-REVIEW-CODE`
|
|
38
|
-
- PRD 작성: `prd-writer-agent`
|
|
39
|
-
|
|
40
|
-
## 운영 규칙
|
|
41
|
-
|
|
42
|
-
- Manager 에이전트가 단계 전환 권한을 가집니다.
|
|
43
|
-
- Artifact 검증 실패 시 단계 중단 후 원인 수정을 우선해 주세요.
|
|
44
|
-
- 보안/배포 단계는 우회 없이 게이트를 통과해야 합니다.
|
|
45
|
-
|
|
46
|
-
## 참고 문서 (검증일: 2026-02-17)
|
|
47
|
-
|
|
48
|
-
- [Google Antigravity 발표](https://developers.googleblog.com/build-with-google-antigravity-our-new-agentic-development-platform/)
|
|
49
|
-
- [Antigravity 공식 문서](https://antigravity.dev/docs)
|
|
50
|
-
- [Antigravity 워크플로우 문서](https://antigravity.im/documentation)
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: frontend-repetition-pack
|
|
3
|
-
description: UI 컴포넌트화, Hook 분리, 성능 최적화를 표준 단계로 실행한다. 반복 프론트엔드 개선 작업에서 사용한다.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 시작 전 체크리스트
|
|
7
|
-
|
|
8
|
-
- 중복 UI 후보 목록을 수집한다 (화면/컴포넌트/사용 횟수).
|
|
9
|
-
- 기준 지표를 기록한다 (번들 크기, 렌더 횟수, 핵심 UX 지연 시간).
|
|
10
|
-
- 디자인 토큰/컴포넌트 규칙을 확인한다.
|
|
11
|
-
- 상태 로직 분리 대상(부수효과/비동기/공유 상태)을 표시한다.
|
|
12
|
-
|
|
13
|
-
# 실행 절차
|
|
14
|
-
|
|
15
|
-
1. `CMD-DEV-FE-UI-COMPONENTIZE`
|
|
16
|
-
2. `CMD-DEV-FE-HOOK-SEPARATE`
|
|
17
|
-
3. `CMD-DEV-PERF-OPTIMIZE`
|
|
18
|
-
|
|
19
|
-
# 결과 보고 형식
|
|
20
|
-
|
|
21
|
-
- 컴포넌트화 결과: 기존->신규 매핑, 공통 Props 계약
|
|
22
|
-
- Hook 분리 결과: Hook 이름, 입력/출력, 부수효과 정책
|
|
23
|
-
- 성능 결과: 전/후 지표와 측정 조건
|
|
24
|
-
- 남은 리팩터 항목: 우선순위와 예상 영향
|
|
25
|
-
|
|
26
|
-
# 중단 조건
|
|
27
|
-
|
|
28
|
-
- 시각적 회귀가 차단 이슈 수준으로 발생한 경우
|
|
29
|
-
- 컴포넌트 계약이 확정되지 않아 호출부 정리가 불가능한 경우
|
|
30
|
-
- 전/후 성능 비교가 불가능해 개선 효과를 증명할 수 없는 경우
|
|
31
|
-
|
|
32
|
-
# 품질 규칙
|
|
33
|
-
|
|
34
|
-
- 단계별 전후 지표를 Artifact에 남긴다.
|
|
35
|
-
- 계약 없는 리팩터링 금지
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: incident-response
|
|
3
|
-
description: 장애 대응, 근본 원인 수정, 재발 방지까지 수행한다. 운영 장애 및 핫픽스 대응에서 사용한다.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 시작 전 체크리스트
|
|
7
|
-
|
|
8
|
-
- 장애 심각도(SEV), 영향 범위, 시작 시각을 확정한다.
|
|
9
|
-
- 즉시 복구 경로(롤백/우회/트래픽 차단)를 준비한다.
|
|
10
|
-
- 커뮤니케이션 채널과 의사결정 책임자를 지정한다.
|
|
11
|
-
- 로그/메트릭/알림 스냅샷을 보존한다.
|
|
12
|
-
|
|
13
|
-
# 실행 절차
|
|
14
|
-
|
|
15
|
-
1. `CMD-INCIDENT-TRIAGE`로 복구 우선
|
|
16
|
-
2. `CMD-IMPROVE-TECHDEBT`로 근본 원인 보완
|
|
17
|
-
3. `CMD-DOC-HANDOFF`로 재발 방지 문서화
|
|
18
|
-
|
|
19
|
-
# 결과 보고 형식
|
|
20
|
-
|
|
21
|
-
- 타임라인: 탐지->완화->복구 시각
|
|
22
|
-
- 복구 조치: 실행 명령/설정 변경/결과
|
|
23
|
-
- 근본 원인: 기술 원인, 프로세스 원인
|
|
24
|
-
- 재발 방지 액션: 담당자, 마감일, 검증 방법
|
|
25
|
-
|
|
26
|
-
# 중단 조건
|
|
27
|
-
|
|
28
|
-
- 고객 영향이 지속되는데 복구 경로가 없는 경우
|
|
29
|
-
- 데이터 손상 가능성이 있어 즉시 격리가 필요한 경우
|
|
30
|
-
- 재발 방지 액션의 책임자/기한이 확정되지 않은 경우
|
|
31
|
-
|
|
32
|
-
# 품질 규칙
|
|
33
|
-
|
|
34
|
-
- RCA와 재발 방지 액션 없는 종료 금지
|
|
35
|
-
- 복구와 개선을 분리 보고
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: security-hardening
|
|
3
|
-
description: 위협 모델링과 취약점 감사를 수행하고 보완 및 재검증까지 실행한다. 보안 강화 요청에서 사용한다.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 시작 전 체크리스트
|
|
7
|
-
|
|
8
|
-
- 신뢰 경계와 보호 대상 자산을 확정한다.
|
|
9
|
-
- 의존성 목록과 현재 취약점 현황을 수집한다.
|
|
10
|
-
- 위협 모델링 범위(인증/인가/데이터/운영)를 고정한다.
|
|
11
|
-
- 예외 승인 정책(책임자, 만료일)을 준비한다.
|
|
12
|
-
|
|
13
|
-
# 실행 절차
|
|
14
|
-
|
|
15
|
-
1. `WF-SECURITY-HARDENING` 실행
|
|
16
|
-
2. `CMD-SEC-THREAT-MODEL`, `CMD-SEC-DEPENDENCY-AUDIT` 수행
|
|
17
|
-
3. 보완 반영 후 테스트/리뷰 재실행
|
|
18
|
-
|
|
19
|
-
# 결과 보고 형식
|
|
20
|
-
|
|
21
|
-
- 위협/취약점 목록: 심각도, 영향, 우선순위
|
|
22
|
-
- 보완 적용 내역: 코드/설정 변경과 근거
|
|
23
|
-
- 재검증 결과: 스캔/테스트/리뷰 결과
|
|
24
|
-
- 잔여 위험 및 예외 승인: 책임자, 만료일
|
|
25
|
-
|
|
26
|
-
# 중단 조건
|
|
27
|
-
|
|
28
|
-
- 치명 취약점이 남아 있는데 배포를 진행하려는 경우
|
|
29
|
-
- 고위험 위협에 대한 완화 통제가 정의되지 않은 경우
|
|
30
|
-
- 예외 승인이 만료일 없이 요청된 경우
|
|
31
|
-
|
|
32
|
-
# 품질 규칙
|
|
33
|
-
|
|
34
|
-
- 치명 취약점 0건 전까지 종료 금지
|
|
35
|
-
- 예외 수용은 만료일 포함
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: service-lifecycle-orchestration
|
|
3
|
-
description: Plan-Implement-Test-Review-Release 흐름을 Manager 중심으로 실행한다. 신규 서비스 구축 및 대형 기능 출시에 사용한다.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 시작 전 체크리스트
|
|
7
|
-
|
|
8
|
-
- 요구사항/ADR/범위/비범위를 확정한다.
|
|
9
|
-
- 각 단계 책임 역할과 승인자를 지정한다.
|
|
10
|
-
- 단계별 진입/종료 기준을 작업 시작 전에 확인한다.
|
|
11
|
-
- 리스크와 롤백 전략을 초기 단계에서 기록한다.
|
|
12
|
-
|
|
13
|
-
# 실행 절차
|
|
14
|
-
|
|
15
|
-
1. `WF-SERVICE-E2E`를 선택한다.
|
|
16
|
-
2. 단계별 입력 Artifact 스키마를 검증한다.
|
|
17
|
-
3. 해당 단계 에이전트가 명령 ID를 수행한다.
|
|
18
|
-
4. 출력 Artifact 검증 후 다음 단계로 진행한다.
|
|
19
|
-
|
|
20
|
-
# 결과 보고 형식
|
|
21
|
-
|
|
22
|
-
- 단계 상태: 완료/미완료/차단요인
|
|
23
|
-
- 실행 근거: 단계별 명령 ID와 결과
|
|
24
|
-
- 품질 상태: 테스트/보안/리뷰 게이트 결과
|
|
25
|
-
- 다음 행동: 담당자, 마감 조건, 선행 조건
|
|
26
|
-
|
|
27
|
-
# 중단 조건
|
|
28
|
-
|
|
29
|
-
- 진입 기준이 충족되지 않은 단계가 있는 경우
|
|
30
|
-
- 차단 이슈가 해결되지 않았는데 다음 단계로 이동하려는 경우
|
|
31
|
-
- 롤백 전략 없이 배포 단계 진입이 요청된 경우
|
|
32
|
-
|
|
33
|
-
# 품질 규칙
|
|
34
|
-
|
|
35
|
-
- Artifact 검증 실패 시 단계 진행 금지
|
|
36
|
-
- command ID 없는 임의 실행 금지
|