ganbatte-os 0.2.1

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 (200) hide show
  1. package/AGENTS.md +46 -0
  2. package/CLAUDE.md +31 -0
  3. package/GEMINI.md +17 -0
  4. package/LICENSE +21 -0
  5. package/README.md +141 -0
  6. package/agents/profiles/architect.md +13 -0
  7. package/agents/profiles/dev.md +13 -0
  8. package/agents/profiles/devops.md +12 -0
  9. package/agents/profiles/ganbatte-os-master.md +444 -0
  10. package/agents/profiles/index.json +14 -0
  11. package/agents/profiles/po.md +7 -0
  12. package/agents/profiles/qa.md +456 -0
  13. package/agents/profiles/sm.md +7 -0
  14. package/agents/profiles/squad-creator.md +7 -0
  15. package/agents/profiles/ux-design-expert.md +14 -0
  16. package/config.json +15 -0
  17. package/docs/curation.md +60 -0
  18. package/docs/gos_installation_guide.md +114 -0
  19. package/docs/ide-compatibility.md +20 -0
  20. package/docs/plan/plan-git-operations.md +51 -0
  21. package/docs/plan-distribuicao-publica.md +360 -0
  22. package/docs/stacks/stack-git-operations.md +154 -0
  23. package/docs/toolchain-map.md +18 -0
  24. package/integrations/README.md +42 -0
  25. package/integrations/antigravity/README.md +29 -0
  26. package/integrations/antigravity/command-map.json +29 -0
  27. package/integrations/claude/README.md +35 -0
  28. package/integrations/claude/agent-map.json +46 -0
  29. package/integrations/claude/command-map.json +32 -0
  30. package/integrations/claude/litellm-proxy.md +93 -0
  31. package/integrations/claude/mcp-specifics.md +121 -0
  32. package/integrations/codex/README.md +29 -0
  33. package/integrations/codex/command-map.json +29 -0
  34. package/integrations/cursor/README.md +8 -0
  35. package/integrations/cursor/command-map.json +11 -0
  36. package/integrations/gemini/README.md +13 -0
  37. package/integrations/gemini/command-map.json +11 -0
  38. package/integrations/kilo-code/README.md +7 -0
  39. package/integrations/kilo-code/command-map.json +11 -0
  40. package/integrations/opencode/README.md +91 -0
  41. package/integrations/opencode/command-map.json +46 -0
  42. package/integrations/registry.json +20 -0
  43. package/manifests/g-os-runtime-manifest.json +39 -0
  44. package/manifests/gos-install-manifest.json +46 -0
  45. package/opencode.json +7 -0
  46. package/package.json +51 -0
  47. package/playbooks/feature-development-playbook.md +239 -0
  48. package/playbooks/sprint-planner-playbook.md +127 -0
  49. package/playbooks/squad-pipeline-runner.md +196 -0
  50. package/playbooks/ssh-multi-account-setup.md +185 -0
  51. package/prompts/01-search.md +18 -0
  52. package/prompts/02-spec.md +19 -0
  53. package/prompts/03-tasks.md +15 -0
  54. package/prompts/04-code.md +10 -0
  55. package/prompts/05-reviews.md +11 -0
  56. package/rules/plan-mode.md +60 -0
  57. package/scripts/cli/gos-cli.js +679 -0
  58. package/scripts/hooks/pre-commit-validate.js +201 -0
  59. package/scripts/integrations/check-ide-compat.js +44 -0
  60. package/scripts/integrations/setup-ide-adapters.js +87 -0
  61. package/scripts/tools/clickup-preprocess.js +218 -0
  62. package/scripts/tools/clickup.js +1058 -0
  63. package/skills/agent-teams/SKILL.md +78 -0
  64. package/skills/agent-teams/presets/team-all.yaml +14 -0
  65. package/skills/agent-teams/presets/team-fullstack.yaml +17 -0
  66. package/skills/agent-teams/presets/team-ide-minimal.yaml +9 -0
  67. package/skills/agent-teams/presets/team-no-ui.yaml +12 -0
  68. package/skills/agent-teams/presets/team-qa-focused.yaml +83 -0
  69. package/skills/clickup/SKILL.md +151 -0
  70. package/skills/component-dedup/SKILL.md +101 -0
  71. package/skills/design-to-code/SKILL.md +255 -0
  72. package/skills/figma-implement-design/SKILL.md +227 -0
  73. package/skills/figma-make-analyzer/SKILL.md +140 -0
  74. package/skills/frontend-dev/SKILL.md +271 -0
  75. package/skills/git-ssh-setup/SKILL.md +164 -0
  76. package/skills/interface-design/SKILL.md +350 -0
  77. package/skills/interface-design/references/audit.md +76 -0
  78. package/skills/interface-design/references/craft-examples.md +134 -0
  79. package/skills/interface-design/references/critique.md +92 -0
  80. package/skills/interface-design/references/extract.md +92 -0
  81. package/skills/interface-design/references/principles.md +348 -0
  82. package/skills/interface-design/references/templates/system-precision.md +73 -0
  83. package/skills/interface-design/references/templates/system-warmth.md +67 -0
  84. package/skills/interface-design/references/validation.md +137 -0
  85. package/skills/make-code-triage/SKILL.md +135 -0
  86. package/skills/make-version-diff/SKILL.md +87 -0
  87. package/skills/plan-to-tasks/SKILL.md +136 -0
  88. package/skills/react-best-practices/AGENTS.md +2975 -0
  89. package/skills/react-best-practices/SKILL.md +151 -0
  90. package/skills/react-best-practices/metadata.json +15 -0
  91. package/skills/react-best-practices/rules/_sections.md +46 -0
  92. package/skills/react-best-practices/rules/_template.md +28 -0
  93. package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  94. package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  95. package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  96. package/skills/react-best-practices/rules/async-api-routes.md +38 -0
  97. package/skills/react-best-practices/rules/async-defer-await.md +80 -0
  98. package/skills/react-best-practices/rules/async-dependencies.md +51 -0
  99. package/skills/react-best-practices/rules/async-parallel.md +28 -0
  100. package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  101. package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  102. package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  103. package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  104. package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  105. package/skills/react-best-practices/rules/bundle-preload.md +50 -0
  106. package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  107. package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  108. package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  109. package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  110. package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  111. package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  112. package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  113. package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  114. package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  115. package/skills/react-best-practices/rules/js-early-exit.md +50 -0
  116. package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  117. package/skills/react-best-practices/rules/js-index-maps.md +37 -0
  118. package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  119. package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  120. package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  121. package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  122. package/skills/react-best-practices/rules/rendering-activity.md +26 -0
  123. package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  124. package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  125. package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  126. package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  127. package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  128. package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  129. package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  130. package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  131. package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  132. package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  133. package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  134. package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  135. package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  136. package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  137. package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  138. package/skills/react-best-practices/rules/rerender-memo.md +44 -0
  139. package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  140. package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  141. package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  142. package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  143. package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  144. package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  145. package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  146. package/skills/react-best-practices/rules/server-cache-react.md +76 -0
  147. package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  148. package/skills/react-best-practices/rules/server-hoist-static-io.md +142 -0
  149. package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  150. package/skills/react-best-practices/rules/server-serialization.md +38 -0
  151. package/skills/react-doctor/SKILL.md +74 -0
  152. package/skills/registry.json +21 -0
  153. package/skills/sprint-planner/SKILL.md +434 -0
  154. package/squads/design-delivery/README.md +10 -0
  155. package/squads/design-delivery/squad.yaml +30 -0
  156. package/squads/design-delivery/workflows/wf-design-delivery.yaml +27 -0
  157. package/squads/design-squad/README.md +31 -0
  158. package/squads/design-squad/agents/brad-frost.md +185 -0
  159. package/squads/design-squad/agents/dan-mall.md +178 -0
  160. package/squads/design-squad/agents/dave-malouf.md +198 -0
  161. package/squads/design-squad/agents/design-chief.md +109 -0
  162. package/squads/design-squad/agents/design-system-architect.md +109 -0
  163. package/squads/design-squad/agents/ui-engineer.md +102 -0
  164. package/squads/design-squad/agents/ux-designer.md +105 -0
  165. package/squads/design-squad/agents/visual-generator.md +108 -0
  166. package/squads/design-squad/checklists/output-quality.md +76 -0
  167. package/squads/design-squad/config/config.yaml +65 -0
  168. package/squads/design-squad/data/design-patterns-catalog.yaml +276 -0
  169. package/squads/design-squad/data/routing-catalog.yaml +95 -0
  170. package/squads/design-squad/squad.yaml +88 -0
  171. package/squads/design-squad/tasks/audit-design.md +174 -0
  172. package/squads/design-squad/tasks/create-component-spec.md +185 -0
  173. package/squads/design-squad/tasks/create-design-system.md +179 -0
  174. package/squads/design-squad/tasks/design-ux-flow.md +184 -0
  175. package/squads/design-squad/tasks/diagnose.md +138 -0
  176. package/squads/design-squad/tasks/generate-handoff.md +186 -0
  177. package/squads/design-squad/tasks/review.md +133 -0
  178. package/squads/design-squad/tasks/setup-design-ops.md +177 -0
  179. package/squads/design-squad/workflows/wf-design-system-creation.yaml +131 -0
  180. package/squads/design-squad/workflows/wf-feature-design.yaml +114 -0
  181. package/squads/git-operations/README.md +30 -0
  182. package/squads/git-operations/squad.yaml +27 -0
  183. package/squads/git-operations/workflows/wf-safe-commit.yaml +27 -0
  184. package/squads/git-operations/workflows/wf-ssh-setup.yaml +27 -0
  185. package/squads/sprint-planning/agents/sprint-chief.md +47 -0
  186. package/squads/sprint-planning/agents/sprint-planner-agent.md +43 -0
  187. package/squads/sprint-planning/agents/sprint-tracker.md +43 -0
  188. package/squads/sprint-planning/agents/task-importer.md +44 -0
  189. package/squads/sprint-planning/checklists/sprint-readiness.md +27 -0
  190. package/squads/sprint-planning/config/config.yaml +65 -0
  191. package/squads/sprint-planning/data/clickup-field-mapping.yaml +94 -0
  192. package/squads/sprint-planning/squad.yaml +52 -0
  193. package/squads/sprint-planning/tasks/close-sprint.md +43 -0
  194. package/squads/sprint-planning/tasks/create-sprint.md +42 -0
  195. package/squads/sprint-planning/tasks/import-tasks.md +39 -0
  196. package/squads/sprint-planning/tasks/sync-status.md +31 -0
  197. package/squads/sprint-planning/workflows/wf-sprint-creation.yaml +59 -0
  198. package/squads/sprint-planning/workflows/wf-sprint-sync.yaml +35 -0
  199. package/templates/adr-tmpl.yaml +76 -0
  200. package/templates/sprint-clickup.template.md +80 -0
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * pre-commit-validate.js
5
+ *
6
+ * Validacao pre-commit: roda tsc --noEmit e testes antes do commit.
7
+ * Zero-dependency. Usa execFileSync para seguranca (sem shell injection).
8
+ *
9
+ * Uso:
10
+ * node scripts/hooks/pre-commit-validate.js [--json] [--skip-tests] [--skip-tsc]
11
+ *
12
+ * Exit codes:
13
+ * 0 — todos os checks passaram
14
+ * 1 — um ou mais checks falharam
15
+ */
16
+
17
+ const { execFileSync } = require('child_process');
18
+ const { existsSync, readFileSync } = require('fs');
19
+ const { join } = require('path');
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Flags
23
+ // ---------------------------------------------------------------------------
24
+ const args = process.argv.slice(2);
25
+ const jsonOutput = args.includes('--json');
26
+ const skipTests = args.includes('--skip-tests');
27
+ const skipTsc = args.includes('--skip-tsc');
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Detectar diretorio do projeto
31
+ // ---------------------------------------------------------------------------
32
+ // Se chamado de dentro de um workspace, usar cwd.
33
+ // Se chamado via scripts/hooks/, subir ate a raiz do projeto.
34
+ function findProjectRoot() {
35
+ let dir = process.cwd();
36
+ // Procurar package.json subindo no maximo 5 niveis
37
+ for (let i = 0; i < 5; i++) {
38
+ if (existsSync(join(dir, 'package.json'))) return dir;
39
+ const parent = join(dir, '..');
40
+ if (parent === dir) break;
41
+ dir = parent;
42
+ }
43
+ return process.cwd();
44
+ }
45
+
46
+ const PROJECT_ROOT = findProjectRoot();
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Detectar package manager
50
+ // ---------------------------------------------------------------------------
51
+ function detectPackageManager() {
52
+ if (existsSync(join(PROJECT_ROOT, 'pnpm-lock.yaml'))) return 'pnpm';
53
+ if (existsSync(join(PROJECT_ROOT, 'bun.lockb')) || existsSync(join(PROJECT_ROOT, 'bun.lock'))) return 'bun';
54
+ if (existsSync(join(PROJECT_ROOT, 'yarn.lock'))) return 'yarn';
55
+ return 'npm';
56
+ }
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Ler package.json
60
+ // ---------------------------------------------------------------------------
61
+ function readPkg() {
62
+ const pkgPath = join(PROJECT_ROOT, 'package.json');
63
+ if (!existsSync(pkgPath)) return {};
64
+ try {
65
+ return JSON.parse(readFileSync(pkgPath, 'utf8'));
66
+ } catch {
67
+ return {};
68
+ }
69
+ }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Rodar comando com execFileSync
73
+ // ---------------------------------------------------------------------------
74
+ function runCheck(name, cmd, cmdArgs, opts = {}) {
75
+ const start = Date.now();
76
+ try {
77
+ const output = execFileSync(cmd, cmdArgs, {
78
+ cwd: PROJECT_ROOT,
79
+ encoding: 'utf8',
80
+ stdio: ['pipe', 'pipe', 'pipe'],
81
+ timeout: 300_000, // 5 min max
82
+ ...opts
83
+ });
84
+ return {
85
+ name,
86
+ status: 'pass',
87
+ output: output.trim().slice(0, 2000),
88
+ duration: Date.now() - start
89
+ };
90
+ } catch (err) {
91
+ const stderr = err.stderr ? err.stderr.toString().trim() : '';
92
+ const stdout = err.stdout ? err.stdout.toString().trim() : '';
93
+ return {
94
+ name,
95
+ status: 'fail',
96
+ output: (stderr || stdout || err.message).slice(0, 4000),
97
+ duration: Date.now() - start
98
+ };
99
+ }
100
+ }
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // Detectar script de teste disponivel
104
+ // ---------------------------------------------------------------------------
105
+ function detectTestScript(pkg) {
106
+ const scripts = pkg.scripts || {};
107
+ // Prioridade: test:run (vitest --run) > test:e2e > test
108
+ if (scripts['test:run']) return 'test:run';
109
+ if (scripts['test:e2e']) return 'test:e2e';
110
+ if (scripts['test']) {
111
+ // Se o script test e apenas "vitest" (sem --run), adicionar --run
112
+ // para evitar watch mode
113
+ return 'test';
114
+ }
115
+ return null;
116
+ }
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // Main
120
+ // ---------------------------------------------------------------------------
121
+ function main() {
122
+ const pm = detectPackageManager();
123
+ const pkg = readPkg();
124
+ const checks = [];
125
+
126
+ // Check 1: TypeScript (tsc --noEmit)
127
+ if (!skipTsc) {
128
+ const hasTsConfig = existsSync(join(PROJECT_ROOT, 'tsconfig.json'));
129
+ if (hasTsConfig) {
130
+ // Tentar usar npx para garantir que tsc esta disponivel
131
+ const check = runCheck('tsc --noEmit', 'npx', ['tsc', '--noEmit']);
132
+ checks.push(check);
133
+ } else {
134
+ checks.push({
135
+ name: 'tsc --noEmit',
136
+ status: 'skip',
137
+ output: 'tsconfig.json nao encontrado',
138
+ duration: 0
139
+ });
140
+ }
141
+ }
142
+
143
+ // Check 2: Testes
144
+ if (!skipTests) {
145
+ const testScript = detectTestScript(pkg);
146
+ if (testScript) {
147
+ // Construir comando: <pm> run <script> -- --run (para vitest)
148
+ const cmdArgs = ['run', testScript];
149
+
150
+ // Se o script e "test" e usa vitest, adicionar --run para evitar watch
151
+ const scriptCmd = (pkg.scripts || {})[testScript] || '';
152
+ if (scriptCmd.includes('vitest') && !scriptCmd.includes('--run')) {
153
+ cmdArgs.push('--', '--run');
154
+ }
155
+
156
+ const check = runCheck(`${pm} run ${testScript}`, pm, cmdArgs);
157
+ checks.push(check);
158
+ } else {
159
+ checks.push({
160
+ name: 'tests',
161
+ status: 'skip',
162
+ output: 'Nenhum script de teste encontrado no package.json',
163
+ duration: 0
164
+ });
165
+ }
166
+ }
167
+
168
+ // Resultado
169
+ const passed = checks.every(c => c.status === 'pass' || c.status === 'skip');
170
+ const result = {
171
+ passed,
172
+ packageManager: pm,
173
+ projectRoot: PROJECT_ROOT,
174
+ checks,
175
+ timestamp: new Date().toISOString()
176
+ };
177
+
178
+ if (jsonOutput) {
179
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
180
+ } else {
181
+ // Output legivel
182
+ const icon = passed ? '\u2705' : '\u274C';
183
+ console.log(`\n${icon} Pre-Commit Validation\n`);
184
+ for (const c of checks) {
185
+ const statusIcon = c.status === 'pass' ? '\u2705' : c.status === 'skip' ? '\u23ED' : '\u274C';
186
+ console.log(` ${statusIcon} ${c.name} (${c.duration}ms)`);
187
+ if (c.status === 'fail') {
188
+ // Mostrar primeiras linhas do output de erro
189
+ const lines = c.output.split('\n').slice(0, 15);
190
+ for (const line of lines) {
191
+ console.log(` ${line}`);
192
+ }
193
+ }
194
+ }
195
+ console.log(`\n${passed ? 'Todos os checks passaram.' : 'Checks falharam. Corrija os erros antes do commit.'}\n`);
196
+ }
197
+
198
+ process.exit(passed ? 0 : 1);
199
+ }
200
+
201
+ main();
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const root = process.cwd();
7
+ const required = [
8
+ 'AGENTS.md',
9
+ 'CLAUDE.md',
10
+ 'GEMINI.md',
11
+ 'prompts/01-search.md',
12
+ 'prompts/02-spec.md',
13
+ 'prompts/03-tasks.md',
14
+ 'prompts/04-code.md',
15
+ 'prompts/05-reviews.md',
16
+ 'integrations/registry.json',
17
+ 'integrations/claude/command-map.json',
18
+ 'integrations/codex/command-map.json',
19
+ 'integrations/opencode/command-map.json',
20
+ 'integrations/antigravity/command-map.json',
21
+ 'integrations/gemini/command-map.json',
22
+ 'integrations/cursor/command-map.json',
23
+ 'integrations/kilo-code/command-map.json',
24
+ '.claude/commands/gos/agents/dev.md',
25
+ '.claude/commands/gos/skills/design-to-code.md',
26
+ '.codex/skills/gos-design-to-code.md',
27
+ '.gemini/skills/gos-design-to-code/SKILL.md',
28
+ '.opencode/skills/gos-design-to-code/SKILL.md',
29
+ '.antigravity/instructions.md',
30
+ '.cursor/rules/g-os.mdc',
31
+ '.kilocode/rules/g-os.md'
32
+ ];
33
+
34
+ const missing = required.filter((entry) => !fs.existsSync(path.join(root, entry)));
35
+
36
+ if (missing.length > 0) {
37
+ console.error('Missing compatibility artifacts:');
38
+ for (const entry of missing) {
39
+ console.error(`- ${entry}`);
40
+ }
41
+ process.exit(1);
42
+ }
43
+
44
+ console.log('All IDE compatibility artifacts are present.');
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const root = process.cwd();
7
+
8
+ function ensureDir(dirPath) {
9
+ fs.mkdirSync(dirPath, { recursive: true });
10
+ }
11
+
12
+ function writeFile(filePath, content) {
13
+ ensureDir(path.dirname(filePath));
14
+ fs.writeFileSync(filePath, content.replace(/\r?\n/g, '\n') + '\n');
15
+ }
16
+
17
+ function readJson(filePath) {
18
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
19
+ }
20
+
21
+ function relativeTarget(fromFile, targetFile) {
22
+ return path.relative(path.dirname(fromFile), targetFile).replace(/\\/g, '/');
23
+ }
24
+
25
+ function agentWrapper(agentId, target) {
26
+ return `# ${agentId}\n\nFonte canonica: \`${target}\`\n\nLeia e siga o perfil em \`${target}\`.\nEste arquivo existe apenas como adapter fino para a IDE.`;
27
+ }
28
+
29
+ function skillWrapper(slug, target) {
30
+ return `# gos-${slug}\n\nFonte canonica: \`${target}\`\n\nLeia e siga a skill em \`${target}\`.\nEste arquivo existe apenas como adapter fino para a IDE.`;
31
+ }
32
+
33
+ function main() {
34
+ const agents = readJson(path.join(root, 'agents', 'profiles', 'index.json')).profiles;
35
+ const skills = readJson(path.join(root, 'skills', 'registry.json')).skills;
36
+
37
+ for (const agent of agents) {
38
+ const claudeFile = path.join(root, '.claude', 'commands', 'gos', 'agents', `${agent.id}.md`);
39
+ const target = relativeTarget(claudeFile, path.join(root, 'agents', 'profiles', agent.path));
40
+ writeFile(claudeFile, agentWrapper(agent.id, target));
41
+ }
42
+
43
+ for (const skill of skills) {
44
+ const skillTargetPath = skill.skillFile || skill.path;
45
+ const claudeSkill = path.join(root, '.claude', 'commands', 'gos', 'skills', `${skill.slug}.md`);
46
+ const codexSkill = path.join(root, '.codex', 'skills', `gos-${skill.slug}.md`);
47
+ const geminiSkill = path.join(root, '.gemini', 'skills', `gos-${skill.slug}`, 'SKILL.md');
48
+ const opencodeSkill = path.join(root, '.opencode', 'skills', `gos-${skill.slug}`, 'SKILL.md');
49
+
50
+ writeFile(claudeSkill, skillWrapper(skill.slug, relativeTarget(claudeSkill, path.join(root, skillTargetPath))));
51
+ writeFile(codexSkill, skillWrapper(skill.slug, relativeTarget(codexSkill, path.join(root, skillTargetPath))));
52
+ writeFile(geminiSkill, skillWrapper(skill.slug, relativeTarget(geminiSkill, path.join(root, skillTargetPath))));
53
+ writeFile(opencodeSkill, skillWrapper(skill.slug, relativeTarget(opencodeSkill, path.join(root, skillTargetPath))));
54
+ }
55
+
56
+ const antigravityInstructions = [
57
+ '# G-OS Antigravity Instructions',
58
+ '',
59
+ 'Leia sempre:',
60
+ '- `AGENTS.md`',
61
+ '- `CLAUDE.md`',
62
+ '- `docs/toolchain-map.md`',
63
+ '',
64
+ 'Agentes disponiveis:',
65
+ ...agents.map((agent) => `- ${agent.id}`),
66
+ '',
67
+ 'Skills curadas:',
68
+ ...skills.map((skill) => `- ${skill.slug}`)
69
+ ].join('\n');
70
+
71
+ writeFile(path.join(root, '.antigravity', 'instructions.md'), antigravityInstructions);
72
+ writeFile(
73
+ path.join(root, '.antigravity', 'config.json'),
74
+ JSON.stringify(
75
+ {
76
+ project: 'g-os',
77
+ instructions: ['instructions.md', '../AGENTS.md', '../CLAUDE.md']
78
+ },
79
+ null,
80
+ 2
81
+ )
82
+ );
83
+
84
+ console.log(`Adapters generated for ${agents.length} agents and ${skills.length} skills.`);
85
+ }
86
+
87
+ main();
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict'
4
+
5
+ const ACCENT_FIXES = {
6
+ 'nao': 'não', 'entao': 'então', 'tambem': 'também', 'codigo': 'código',
7
+ 'pagina': 'página', 'unico': 'único', 'analise': 'análise', 'modulo': 'módulo',
8
+ 'numero': 'número', 'especifico': 'específico', 'diretorio': 'diretório',
9
+ 'padrao': 'padrão', 'configuracao': 'configuração', 'validacao': 'validação',
10
+ 'implementacao': 'implementação', 'descricao': 'descrição', 'opcao': 'opção',
11
+ 'sessao': 'sessão', 'secao': 'seção', 'funcao': 'função', 'acao': 'ação',
12
+ 'informacao': 'informação', 'versao': 'versão', 'conexao': 'conexão',
13
+ 'excecao': 'exceção', 'condicao': 'condição', 'operacao': 'operação',
14
+ 'autenticacao': 'autenticação', 'migracao': 'migração', 'integracao': 'integração',
15
+ }
16
+
17
+ const AI_PATTERNS = [
18
+ /\bvale ressaltar\b/gi, /\be importante destacar\b/gi,
19
+ /\bnesse sentido\b/gi, /\bdiante disso\b/gi,
20
+ /\bem suma\b/gi, /\bpor fim\b/gi,
21
+ /\brobusto\b/gi, /\babrangente\b/gi,
22
+ /\binovador\b/gi, /\bestrategico\b/gi,
23
+ /\bholistic[oa]\b/gi, /\balem disso\b/gi,
24
+ ]
25
+
26
+ function fixAccents(text) {
27
+ if (typeof text !== 'string' || !text) return text
28
+ let output = text
29
+ for (const [wrong, right] of Object.entries(ACCENT_FIXES)) {
30
+ output = output.replace(new RegExp(`\\b${wrong}\\b`, 'gi'), (match) => {
31
+ if (match === match.toUpperCase()) return right.toUpperCase()
32
+ if (match[0] === match[0].toUpperCase()) return right[0].toUpperCase() + right.slice(1)
33
+ return right
34
+ })
35
+ }
36
+ return output
37
+ }
38
+
39
+ function detectAIPatterns(text) {
40
+ if (!text) return { count: 0, matches: [] }
41
+ const haystack = Array.isArray(text) ? text.join('\n') : String(text)
42
+ const matches = []
43
+ let count = 0
44
+ for (const pattern of AI_PATTERNS) {
45
+ const found = haystack.match(pattern)
46
+ if (found) {
47
+ count += found.length
48
+ matches.push({ pattern: pattern.source, count: found.length })
49
+ }
50
+ }
51
+ return { count, matches }
52
+ }
53
+
54
+ function buildTaskDescription(task) {
55
+ const sections = []
56
+
57
+ // Descrição principal (texto livre, sem header)
58
+ if (task.description) sections.push(task.description)
59
+
60
+ // Seções estruturadas — headers H3, sem emojis, português com acentos
61
+ if (task.context) sections.push(`### Contexto\n${task.context}`)
62
+ if (task.steps?.length) sections.push(`### Como fazer\n${task.steps.map((s, i) => `${i + 1}. ${s}`).join('\n')}`)
63
+ if (task.businessRules?.length) sections.push(`### Regras de Negócio\n${task.businessRules.map((r) => `\`${r}\``).join(' · ')}`)
64
+ if (task.files?.length) sections.push(`### Arquivos\n${task.files.map((f) => `- \`${f}\``).join('\n')}`)
65
+ if (task.dependencies?.length) sections.push(`### Dependências\n${task.dependencies.map((d) => `- ${d}`).join('\n')}`)
66
+ if (task.acceptanceCriteria?.length) sections.push(`### Critérios de Aceite\n${task.acceptanceCriteria.map((a) => `- [ ] ${a}`).join('\n')}`)
67
+ if (task.ref) sections.push(`### Referência\n${task.ref}`)
68
+ if (task.technicalNotes) sections.push(`### Notas Técnicas\n${task.technicalNotes}`)
69
+ if (task.dod) sections.push(`### Definition of Done\n${task.dod}`)
70
+
71
+ // Primeira seção (descrição) separada das demais por ---
72
+ if (sections.length > 1) {
73
+ return sections[0] + '\n\n---\n\n' + sections.slice(1).join('\n\n')
74
+ }
75
+ return sections.join('\n\n')
76
+ }
77
+
78
+
79
+ function scoreCompleteness(task) {
80
+ let score = 0
81
+ const suggestions = []
82
+
83
+ if (task.description && task.description.length > 50) {
84
+ score += 20
85
+ } else if (task.description) {
86
+ score += 5
87
+ suggestions.push(`Descricao muito curta (${task.description.length} chars).`)
88
+ } else {
89
+ suggestions.push('Sem descricao.')
90
+ }
91
+
92
+ if (task.acceptanceCriteria?.length >= 2 && task.acceptanceCriteria.every((a) => a.length > 20)) {
93
+ score += 25
94
+ } else if (task.acceptanceCriteria?.length) {
95
+ score += 10
96
+ suggestions.push(`ACs insuficientes (${task.acceptanceCriteria.length} item(ns)).`)
97
+ } else {
98
+ suggestions.push('Sem criterios de aceite.')
99
+ }
100
+
101
+ if (task.steps?.length || task.subtasks?.length) score += 15
102
+ else suggestions.push('Sem steps de implementacao.')
103
+
104
+ if (task.files?.length) score += 10
105
+ else suggestions.push('Sem arquivos listados.')
106
+
107
+ if (task.points && task.points >= 1 && task.points <= 13) score += 10
108
+ else suggestions.push('Sem story points validos.')
109
+
110
+ if (task.dependencies?.length >= 0) score += 5
111
+
112
+ if (task.context || task.businessRules?.length) score += 10
113
+ else suggestions.push('Sem contexto de negocio.')
114
+
115
+ if (task.dod || task.acceptanceCriteria?.some((a) => /\b(dado|quando|entao|given|when|then)\b/i.test(a))) score += 5
116
+ else suggestions.push('Sem Definition of Done explicito.')
117
+
118
+ return { score, suggestions }
119
+ }
120
+
121
+ function sanitizeTaskTexts(task) {
122
+ const copy = { ...task }
123
+ let aiPatternCount = 0
124
+ const textFields = ['description', 'context', 'technicalNotes', 'dod', 'title', 'name', 'ref']
125
+ const arrayFields = ['acceptanceCriteria', 'steps', 'businessRules', 'dependencies', 'files']
126
+
127
+ for (const field of textFields) {
128
+ if (typeof copy[field] === 'string') {
129
+ copy[field] = fixAccents(copy[field])
130
+ aiPatternCount += detectAIPatterns(copy[field]).count
131
+ }
132
+ }
133
+
134
+ for (const field of arrayFields) {
135
+ if (Array.isArray(copy[field])) {
136
+ copy[field] = copy[field].map((item) => {
137
+ if (typeof item !== 'string') return item
138
+ const fixed = fixAccents(item)
139
+ aiPatternCount += detectAIPatterns(fixed).count
140
+ return fixed
141
+ })
142
+ }
143
+ }
144
+
145
+ const completeness = scoreCompleteness(copy)
146
+ const description = buildTaskDescription(copy)
147
+ return {
148
+ task: {
149
+ ...copy,
150
+ completenessScore: completeness.score,
151
+ completenessSuggestions: completeness.suggestions,
152
+ aiPatternCount,
153
+ description,
154
+ },
155
+ aiPatternCount,
156
+ completenessScore: completeness.score,
157
+ completenessSuggestions: completeness.suggestions,
158
+ description,
159
+ }
160
+ }
161
+
162
+ function processPayload(payload) {
163
+ if (Array.isArray(payload)) {
164
+ return { tasks: payload.map((task) => sanitizeTaskTexts(task).task) }
165
+ }
166
+ if (payload && Array.isArray(payload.tasks)) {
167
+ return { ...payload, tasks: payload.tasks.map((task) => sanitizeTaskTexts(task).task) }
168
+ }
169
+ if (payload && typeof payload === 'object') {
170
+ return sanitizeTaskTexts(payload).task
171
+ }
172
+ return payload
173
+ }
174
+
175
+ function readStdin() {
176
+ return new Promise((resolve, reject) => {
177
+ let data = ''
178
+ process.stdin.setEncoding('utf8')
179
+ process.stdin.on('data', (chunk) => { data += chunk })
180
+ process.stdin.on('end', () => resolve(data))
181
+ process.stdin.on('error', reject)
182
+ })
183
+ }
184
+
185
+ async function main() {
186
+ if (!process.argv.includes('--json')) {
187
+ console.error(JSON.stringify({ error: 'Use --json and provide JSON via stdin' }))
188
+ process.exit(1)
189
+ }
190
+
191
+ const input = await readStdin()
192
+ let parsed
193
+ try {
194
+ parsed = input.trim() ? JSON.parse(input) : {}
195
+ } catch (error) {
196
+ console.error(JSON.stringify({ error: `Invalid JSON input: ${error.message}` }))
197
+ process.exit(1)
198
+ }
199
+
200
+ const output = processPayload(parsed)
201
+ process.stdout.write(JSON.stringify(output, null, 2) + '\n')
202
+ }
203
+
204
+ if (require.main === module) {
205
+ main().catch((error) => {
206
+ console.error(JSON.stringify({ error: error.message }))
207
+ process.exit(1)
208
+ })
209
+ }
210
+
211
+ module.exports = {
212
+ fixAccents,
213
+ detectAIPatterns,
214
+ scoreCompleteness,
215
+ buildTaskDescription,
216
+ sanitizeTaskTexts,
217
+ processPayload,
218
+ }