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,679 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * gos-cli.js — CLI do ganbatte-os para setup, update e validacao de workspace.
5
+ * Zero dependencies externas. Usa apenas modulos nativos do Node.js.
6
+ *
7
+ * Comandos:
8
+ * gos init Setup pos-clone (remote, dirs, IDEs)
9
+ * gos update Fetch + merge de upstream/main
10
+ * gos doctor Validar integridade do workspace
11
+ * gos version Mostrar versao e checar atualizacoes
12
+ */
13
+
14
+ const fs = require('node:fs');
15
+ const path = require('node:path');
16
+ const { execFileSync, execSync } = require('node:child_process');
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Constantes
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const VERSION = '0.2.0';
23
+ const UPSTREAM_REMOTE = 'upstream';
24
+ const UPSTREAM_BRANCH = 'main';
25
+ const LOCAL_DIR = '.gos-local';
26
+ const MANIFEST_PATH = 'manifests/gos-install-manifest.json';
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Utilitarios
30
+ // ---------------------------------------------------------------------------
31
+
32
+ const log = (msg) => console.log(`[ganbatte-os] ${msg}`);
33
+ const info = (msg) => console.log(` i ${msg}`);
34
+ const ok = (msg) => console.log(` v ${msg}`);
35
+ const warn = (msg) => console.log(` ! ${msg}`);
36
+ const fail = (msg) => console.error(` x ${msg}`);
37
+
38
+ function pathExists(p) { return fs.existsSync(p); }
39
+
40
+ function ensureDir(p) {
41
+ if (!pathExists(p)) fs.mkdirSync(p, { recursive: true });
42
+ }
43
+
44
+ function readJson(filePath, fallback = null) {
45
+ if (!pathExists(filePath)) return fallback;
46
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
47
+ catch { return fallback; }
48
+ }
49
+
50
+ function writeJson(filePath, value) {
51
+ ensureDir(path.dirname(filePath));
52
+ fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n');
53
+ }
54
+
55
+ /**
56
+ * Executa comando git via execFileSync (sem shell injection).
57
+ * Retorna stdout como string. Em caso de erro, retorna '' se ignoreError=true.
58
+ */
59
+ function git(args, opts = {}) {
60
+ const options = { encoding: 'utf8', cwd: opts.cwd, stdio: opts.quiet ? 'pipe' : 'inherit' };
61
+ try {
62
+ return execFileSync('git', args, options);
63
+ } catch (e) {
64
+ if (opts.ignoreError) return (e.stdout || '').toString();
65
+ throw e;
66
+ }
67
+ }
68
+
69
+ /** Executa git e captura stdout silenciosamente. */
70
+ function gitCapture(args, opts = {}) {
71
+ try {
72
+ return execFileSync('git', args, { encoding: 'utf8', stdio: 'pipe', cwd: opts.cwd }).trim();
73
+ } catch {
74
+ return '';
75
+ }
76
+ }
77
+
78
+ /** Executa node script via execFileSync. */
79
+ function runNode(scriptPath, opts = {}) {
80
+ const options = { encoding: 'utf8', cwd: opts.cwd, stdio: opts.quiet ? 'pipe' : 'inherit' };
81
+ try {
82
+ return execFileSync(process.execPath, [scriptPath], options);
83
+ } catch (e) {
84
+ if (opts.ignoreError) return '';
85
+ throw e;
86
+ }
87
+ }
88
+
89
+ function getFlagValue(args, flag) {
90
+ const prefix = `--${flag}=`;
91
+ const found = args.find(a => a.startsWith(prefix));
92
+ if (found) return found.slice(prefix.length);
93
+ const idx = args.indexOf(`--${flag}`);
94
+ if (idx !== -1 && idx + 1 < args.length) return args[idx + 1];
95
+ return null;
96
+ }
97
+
98
+ function getRoot() {
99
+ return path.resolve(__dirname, '..', '..');
100
+ }
101
+
102
+ /**
103
+ * Copia recursiva de diretórios (zero dependencies).
104
+ */
105
+ function copyDirRecursive(source, target, options = {}) {
106
+ const { exclude = [] } = options;
107
+ if (!fs.existsSync(target)) fs.mkdirSync(target, { recursive: true });
108
+
109
+ const entries = fs.readdirSync(source, { withFileTypes: true });
110
+
111
+ for (const entry of entries) {
112
+ const srcPath = path.join(source, entry.name);
113
+ const destPath = path.join(target, entry.name);
114
+
115
+ // Skip excluded names
116
+ if (exclude.includes(entry.name)) continue;
117
+
118
+ if (entry.isDirectory()) {
119
+ copyDirRecursive(srcPath, destPath, options);
120
+ } else {
121
+ fs.copyFileSync(srcPath, destPath);
122
+ }
123
+ }
124
+ }
125
+
126
+ function getManifest(root) {
127
+ const manifestFile = path.join(root, MANIFEST_PATH);
128
+ const manifest = readJson(manifestFile);
129
+ if (!manifest) {
130
+ fail(`Manifest nao encontrado: ${MANIFEST_PATH}`);
131
+ process.exit(1);
132
+ }
133
+ return manifest;
134
+ }
135
+
136
+ // ---------------------------------------------------------------------------
137
+ // Merge .gitignore
138
+ // ---------------------------------------------------------------------------
139
+
140
+ function mergeGitignore(root, entries) {
141
+ const gitignorePath = path.join(root, '.gitignore');
142
+ let content = '';
143
+ if (pathExists(gitignorePath)) {
144
+ content = fs.readFileSync(gitignorePath, 'utf8');
145
+ }
146
+
147
+ const missing = entries.filter(e => !content.includes(e.trim()));
148
+ if (missing.length === 0) return false;
149
+
150
+ const block = '\n# G-OS managed entries\n' + missing.join('\n') + '\n';
151
+ fs.writeFileSync(gitignorePath, content.trimEnd() + '\n' + block);
152
+ return true;
153
+ }
154
+
155
+ // ---------------------------------------------------------------------------
156
+ // gos init
157
+ // ---------------------------------------------------------------------------
158
+
159
+ function cmdInit(root, args) {
160
+ const force = args.includes('--force');
161
+
162
+ log('Inicializando workspace ganbatte-os...');
163
+
164
+ // 1. Validar Node >= 18
165
+ const nodeVersion = parseInt(process.version.slice(1), 10);
166
+ if (nodeVersion < 18) {
167
+ fail(`Node.js >= 18 necessario. Versao atual: ${process.version}`);
168
+ process.exit(1);
169
+ }
170
+
171
+ // 2. Checar se ja inicializado
172
+ const installLog = path.join(root, LOCAL_DIR, 'install-log.json');
173
+ if (pathExists(installLog) && !force) {
174
+ warn('Workspace ja inicializado.');
175
+ info('Use --force para reinicializar.');
176
+ return;
177
+ }
178
+
179
+ // 3. Renomear remote origin -> upstream (se origin existir)
180
+ const remotes = gitCapture(['remote'], { cwd: root });
181
+ if (remotes.includes('origin') && !remotes.includes(UPSTREAM_REMOTE)) {
182
+ log('Renomeando remote origin -> upstream...');
183
+ git(['remote', 'rename', 'origin', UPSTREAM_REMOTE], { cwd: root });
184
+ ok('Remote renomeado: origin -> upstream');
185
+ info('Agora voce pode adicionar seu proprio origin com: git remote add origin <url>');
186
+ } else if (remotes.includes(UPSTREAM_REMOTE)) {
187
+ ok('Remote upstream ja existe.');
188
+ } else {
189
+ warn('Nenhum remote origin encontrado. Configure manualmente:');
190
+ info(` git remote add ${UPSTREAM_REMOTE} https://github.com/adrianomorais-ganbatte/ganbatte-os.git`);
191
+ }
192
+
193
+ // 4. Criar diretorios locais
194
+ const localDirs = ['worktrees', 'outputs', 'task-queue'];
195
+ for (const dir of localDirs) {
196
+ ensureDir(path.join(root, LOCAL_DIR, dir));
197
+ }
198
+ ok(`Diretorio ${LOCAL_DIR}/ criado com subdirs.`);
199
+
200
+ // 5. Criar packages/ com .gitkeep
201
+ const packagesDir = path.join(root, 'packages');
202
+ if (!pathExists(packagesDir)) {
203
+ ensureDir(packagesDir);
204
+ fs.writeFileSync(path.join(packagesDir, '.gitkeep'), '');
205
+ ok('Diretorio packages/ criado.');
206
+ }
207
+
208
+ // 6. Sync IDE adapters
209
+ const ideSetupScript = path.join(root, 'scripts', 'integrations', 'setup-ide-adapters.js');
210
+ if (pathExists(ideSetupScript)) {
211
+ log('Sincronizando IDE adapters...');
212
+ runNode(ideSetupScript, { cwd: root });
213
+ ok('IDE adapters sincronizados.');
214
+ } else {
215
+ warn('setup-ide-adapters.js nao encontrado. Pulando sync de IDEs.');
216
+ }
217
+
218
+ // 7. Validar IDEs
219
+ const ideCheckScript = path.join(root, 'scripts', 'integrations', 'check-ide-compat.js');
220
+ if (pathExists(ideCheckScript)) {
221
+ runNode(ideCheckScript, { cwd: root, ignoreError: true });
222
+ }
223
+
224
+ // 8. Merge .gitignore
225
+ const manifest = getManifest(root);
226
+ const gitignoreUpdated = mergeGitignore(root, manifest.gitignoreEntries || []);
227
+ if (gitignoreUpdated) ok('.gitignore atualizado com entradas do manifest.');
228
+
229
+ // 9. Salvar install log
230
+ writeJson(installLog, {
231
+ version: VERSION,
232
+ initializedAt: new Date().toISOString(),
233
+ nodeVersion: process.version
234
+ });
235
+
236
+ // 10. Sucesso
237
+ console.log('');
238
+ ok('Workspace ganbatte-os inicializado com sucesso!');
239
+ console.log('');
240
+ console.log(` Versao: ${VERSION}`);
241
+ console.log(` Local dir: ${LOCAL_DIR}/`);
242
+ console.log(` .gitignore: ${gitignoreUpdated ? 'atualizado' : 'ja estava ok'}`);
243
+ console.log('');
244
+ console.log(' Proximos passos:');
245
+
246
+ const finalRemotes = gitCapture(['remote'], { cwd: root });
247
+ if (!finalRemotes.includes('origin')) {
248
+ console.log(' 1. Adicione seu remote: git remote add origin <seu-repo>');
249
+ }
250
+
251
+ console.log(' 2. Crie projetos em packages/');
252
+ console.log(' 3. Para atualizar o framework: npm run gos:update');
253
+ console.log('');
254
+ }
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // gos install
258
+ // ---------------------------------------------------------------------------
259
+
260
+ function cmdInstall(args) {
261
+ const targetRoot = process.cwd();
262
+ const sourceRoot = getRoot();
263
+
264
+ // Se ja estamos na raiz do G-OS, apenas rodamos o init
265
+ if (path.resolve(sourceRoot) === path.resolve(targetRoot)) {
266
+ log('Executando na raiz do framework. Redirecionando para "init"...');
267
+ cmdInit(targetRoot, args);
268
+ return;
269
+ }
270
+
271
+ log(`Instalando ganbatte-os em: ${targetRoot}`);
272
+
273
+ // 1. Validar se diretorio ja tem G-OS (a menos que use --force)
274
+ if (pathExists(path.join(targetRoot, LOCAL_DIR)) && !args.includes('--force')) {
275
+ fail('Workspace ganbatte-os ja detectado neste diretorio.');
276
+ info('Use --force para reinstalar/sobrescrever.');
277
+ process.exit(1);
278
+ }
279
+
280
+ // 2. Copiar arquivos do framework (exceto os internos/git)
281
+ const exclude = ['.git', '.gos-local', 'node_modules', 'package-lock.json', 'install-log.json', 'update-log.json'];
282
+ log('Copiando arquivos do framework...');
283
+ try {
284
+ copyDirRecursive(sourceRoot, targetRoot, { exclude });
285
+ ok('Arquivos copiados com sucesso.');
286
+ } catch (e) {
287
+ fail(`Erro ao copiar arquivos: ${e.message}`);
288
+ process.exit(1);
289
+ }
290
+
291
+ // 3. Executar o init no target para finalizar configs
292
+ cmdInit(targetRoot, args);
293
+
294
+ // 4. Garantir que o remote upstream existe caso tenha sido instalado via npx
295
+ const remotes = gitCapture(['remote'], { cwd: targetRoot });
296
+ if (!remotes.includes(UPSTREAM_REMOTE)) {
297
+ try {
298
+ git(['remote', 'add', UPSTREAM_REMOTE, 'https://github.com/adrianomorais-ganbatte/ganbatte-os.git'], { cwd: targetRoot });
299
+ ok(`Remote "${UPSTREAM_REMOTE}" adicionado.`);
300
+ } catch {
301
+ warn(`Nao foi possivel adicionar o remote "${UPSTREAM_REMOTE}". Configure manualmente.`);
302
+ }
303
+ }
304
+ }
305
+
306
+ // ---------------------------------------------------------------------------
307
+ // gos update
308
+ // ---------------------------------------------------------------------------
309
+
310
+ function cmdUpdate(root, args) {
311
+ const skipStash = args.includes('--no-stash');
312
+
313
+ log('Atualizando workspace ganbatte-os...');
314
+
315
+ // 1. Verificar remote upstream
316
+ const remotes = gitCapture(['remote'], { cwd: root });
317
+ if (!remotes.includes(UPSTREAM_REMOTE)) {
318
+ fail(`Remote "${UPSTREAM_REMOTE}" nao encontrado.`);
319
+ info(`Adicione com: git remote add ${UPSTREAM_REMOTE} https://github.com/adrianomorais-ganbatte/ganbatte-os.git`);
320
+ process.exit(1);
321
+ }
322
+
323
+ // 2. Checar se ha mudancas locais e fazer stash
324
+ const status = gitCapture(['status', '--porcelain'], { cwd: root });
325
+ let didStash = false;
326
+ if (status && !skipStash) {
327
+ log('Mudancas locais detectadas. Fazendo stash...');
328
+ git(['stash', 'push', '-m', 'gos-update-auto-stash'], { cwd: root });
329
+ didStash = true;
330
+ ok('Stash criado.');
331
+ }
332
+
333
+ // 3. Fetch upstream
334
+ log(`Buscando atualizacoes de ${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}...`);
335
+ git(['fetch', UPSTREAM_REMOTE, UPSTREAM_BRANCH], { cwd: root });
336
+
337
+ // 4. Checar se ha commits novos
338
+ const behind = gitCapture(
339
+ ['rev-list', '--count', `HEAD..${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}`],
340
+ { cwd: root }
341
+ );
342
+ if (behind === '0') {
343
+ ok('Workspace ja esta atualizado.');
344
+ if (didStash) git(['stash', 'pop'], { cwd: root });
345
+ return;
346
+ }
347
+
348
+ const commitBefore = gitCapture(['rev-parse', '--short', 'HEAD'], { cwd: root });
349
+
350
+ // 5. Merge
351
+ log(`${behind} commit(s) novo(s). Fazendo merge...`);
352
+ const manifest = getManifest(root);
353
+ const frameworkPaths = manifest.frameworkManaged || [];
354
+
355
+ try {
356
+ git(['merge', `${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}`, '--no-edit'], { cwd: root, quiet: true });
357
+ ok('Merge concluido sem conflitos.');
358
+ } catch {
359
+ // Checar conflitos
360
+ const conflictFiles = gitCapture(['diff', '--name-only', '--diff-filter=U'], { cwd: root });
361
+ if (!conflictFiles) {
362
+ fail('Merge falhou por motivo desconhecido.');
363
+ if (didStash) info('Stash preservado. Rode: git stash pop');
364
+ process.exit(1);
365
+ }
366
+
367
+ const conflicts = conflictFiles.split('\n').filter(Boolean);
368
+ const userConflicts = [];
369
+ const fwConflicts = [];
370
+
371
+ for (const file of conflicts) {
372
+ const isFramework = frameworkPaths.some(fp => file.startsWith(fp.replace(/\/$/, '')));
373
+ if (isFramework) {
374
+ fwConflicts.push(file);
375
+ } else {
376
+ userConflicts.push(file);
377
+ }
378
+ }
379
+
380
+ // Auto-resolve framework files
381
+ for (const file of fwConflicts) {
382
+ git(['checkout', '--theirs', file], { cwd: root, quiet: true });
383
+ git(['add', file], { cwd: root, quiet: true });
384
+ }
385
+ if (fwConflicts.length > 0) {
386
+ ok(`${fwConflicts.length} conflito(s) em arquivos do framework resolvidos automaticamente.`);
387
+ }
388
+
389
+ // User conflicts = abort
390
+ if (userConflicts.length > 0) {
391
+ fail('Conflitos em arquivos do usuario:');
392
+ for (const file of userConflicts) {
393
+ console.log(` - ${file}`);
394
+ }
395
+ info('Resolva os conflitos manualmente e rode: git merge --continue');
396
+ if (didStash) info('Stash preservado. Apos resolver: git stash pop');
397
+ process.exit(1);
398
+ }
399
+
400
+ // Continuar merge se todos os conflitos foram resolvidos
401
+ git(['merge', '--continue', '--no-edit'], { cwd: root, quiet: true, ignoreError: true });
402
+ }
403
+
404
+ const commitAfter = gitCapture(['rev-parse', '--short', 'HEAD'], { cwd: root });
405
+
406
+ // 6. Re-sync IDEs
407
+ const ideSetupScript = path.join(root, 'scripts', 'integrations', 'setup-ide-adapters.js');
408
+ if (pathExists(ideSetupScript)) {
409
+ log('Re-sincronizando IDE adapters...');
410
+ runNode(ideSetupScript, { cwd: root, quiet: true });
411
+ ok('IDE adapters atualizados.');
412
+ }
413
+
414
+ // 7. Validar IDEs
415
+ const ideCheckScript = path.join(root, 'scripts', 'integrations', 'check-ide-compat.js');
416
+ if (pathExists(ideCheckScript)) {
417
+ runNode(ideCheckScript, { cwd: root, ignoreError: true, quiet: true });
418
+ }
419
+
420
+ // 8. Pop stash
421
+ if (didStash) {
422
+ log('Restaurando mudancas locais (stash pop)...');
423
+ try {
424
+ git(['stash', 'pop'], { cwd: root, quiet: true });
425
+ ok('Mudancas locais restauradas.');
426
+ } catch {
427
+ warn('Falha ao restaurar stash. Rode manualmente: git stash pop');
428
+ }
429
+ }
430
+
431
+ // 9. Salvar update log
432
+ const updateLog = path.join(root, LOCAL_DIR, 'update-log.json');
433
+ const previousLog = readJson(updateLog, {});
434
+ writeJson(updateLog, {
435
+ version: VERSION,
436
+ lastUpdate: new Date().toISOString(),
437
+ previousVersion: previousLog.version || null,
438
+ commitBefore,
439
+ commitAfter
440
+ });
441
+
442
+ // 10. Changelog
443
+ console.log('');
444
+ ok(`Atualizado: ${commitBefore} -> ${commitAfter} (${behind} commits)`);
445
+ console.log('');
446
+ console.log(' Changelog:');
447
+ const changelog = gitCapture(
448
+ ['log', '--oneline', `${commitBefore}..${commitAfter}`],
449
+ { cwd: root }
450
+ );
451
+ if (changelog) {
452
+ for (const line of changelog.split('\n')) {
453
+ console.log(` ${line}`);
454
+ }
455
+ }
456
+ console.log('');
457
+ }
458
+
459
+ // ---------------------------------------------------------------------------
460
+ // gos doctor
461
+ // ---------------------------------------------------------------------------
462
+
463
+ function cmdDoctor(root) {
464
+ log('Validando workspace ganbatte-os...');
465
+ console.log('');
466
+
467
+ let issues = 0;
468
+ let checks = 0;
469
+
470
+ function check(label, condition) {
471
+ checks++;
472
+ if (condition) {
473
+ ok(label);
474
+ } else {
475
+ fail(label);
476
+ issues++;
477
+ }
478
+ }
479
+
480
+ // 1. Manifest existe
481
+ const manifest = readJson(path.join(root, MANIFEST_PATH));
482
+ check('Manifest gos-install-manifest.json', !!manifest);
483
+ if (!manifest) {
484
+ fail('Sem manifest, validacao abortada.');
485
+ process.exit(1);
486
+ }
487
+
488
+ // 2. Required paths
489
+ const requiredPaths = manifest.requiredPaths || [];
490
+ for (const rp of requiredPaths) {
491
+ check(`Path: ${rp}`, pathExists(path.join(root, rp)));
492
+ }
493
+
494
+ // 3. Runtime manifest
495
+ const runtime = readJson(path.join(root, 'manifests', 'g-os-runtime-manifest.json'));
496
+ check('Runtime manifest g-os-runtime-manifest.json', !!runtime);
497
+
498
+ // 4. Agents
499
+ if (runtime && runtime.modules && runtime.modules.agents) {
500
+ for (const agent of runtime.modules.agents) {
501
+ const agentFile = path.join(root, 'agents', 'profiles', `${agent}.md`);
502
+ check(`Agent: ${agent}`, pathExists(agentFile));
503
+ }
504
+ }
505
+
506
+ // 5. Skills
507
+ const skillsRegistry = readJson(path.join(root, 'skills', 'registry.json'));
508
+ check('Skills registry', !!skillsRegistry);
509
+
510
+ if (runtime && runtime.modules && runtime.modules.skills) {
511
+ for (const skill of runtime.modules.skills) {
512
+ const skillFile = path.join(root, 'skills', skill, 'SKILL.md');
513
+ check(`Skill: ${skill}`, pathExists(skillFile));
514
+ }
515
+ }
516
+
517
+ // 6. IDE adapters
518
+ const ideCheckScript = path.join(root, 'scripts', 'integrations', 'check-ide-compat.js');
519
+ if (pathExists(ideCheckScript)) {
520
+ try {
521
+ execFileSync(process.execPath, [ideCheckScript], { encoding: 'utf8', stdio: 'pipe', cwd: root });
522
+ ok('IDE adapters validados (check-ide-compat.js)');
523
+ checks++;
524
+ } catch {
525
+ fail('IDE adapters com problemas (check-ide-compat.js)');
526
+ checks++;
527
+ issues++;
528
+ }
529
+ }
530
+
531
+ // 7. Package.json
532
+ const pkg = readJson(path.join(root, 'package.json'));
533
+ check('package.json existe', !!pkg);
534
+ if (pkg) {
535
+ check('package.json tem scripts gos:*', !!(pkg.scripts && pkg.scripts['gos:update']));
536
+ }
537
+
538
+ // 8. Git remote upstream (allow origin as fallback, especially for CI/Internal dev)
539
+ const remotes = gitCapture(['remote'], { cwd: root });
540
+ const hasUpstream = remotes.includes(UPSTREAM_REMOTE);
541
+ const hasOrigin = remotes.includes('origin');
542
+ check(`Git remote "${UPSTREAM_REMOTE}" configurado`, hasUpstream || hasOrigin);
543
+
544
+ // 9. Local dir (warn instead of fail if in CI)
545
+ const hasLocalDir = pathExists(path.join(root, LOCAL_DIR));
546
+ if (process.env.CI || process.env.GITHUB_ACTIONS) {
547
+ if (hasLocalDir) {
548
+ ok(`Diretorio ${LOCAL_DIR}/ existe`);
549
+ } else {
550
+ ok(`Diretorio ${LOCAL_DIR}/ (ignorado em CI)`);
551
+ }
552
+ checks++;
553
+ } else {
554
+ check(`Diretorio ${LOCAL_DIR}/ existe`, hasLocalDir);
555
+ }
556
+
557
+ // 10. Report
558
+ const updateLog = readJson(path.join(root, LOCAL_DIR, 'update-log.json'));
559
+ const installLogData = readJson(path.join(root, LOCAL_DIR, 'install-log.json'));
560
+
561
+ console.log('');
562
+ console.log(` Versao: ${pkg ? pkg.version || VERSION : VERSION}`);
563
+ console.log(` Inicializado: ${installLogData ? installLogData.initializedAt : 'N/A'}`);
564
+ console.log(` Ultimo update: ${updateLog ? updateLog.lastUpdate : 'N/A'}`);
565
+ console.log(` Node.js: ${process.version}`);
566
+ console.log('');
567
+
568
+ if (issues === 0) {
569
+ ok(`${checks} checks executados. Workspace saudavel.`);
570
+ } else {
571
+ fail(`${issues} problema(s) encontrado(s) em ${checks} checks.`);
572
+ }
573
+
574
+ process.exit(issues > 0 ? 1 : 0);
575
+ }
576
+
577
+ // ---------------------------------------------------------------------------
578
+ // gos version
579
+ // ---------------------------------------------------------------------------
580
+
581
+ function cmdVersion(root) {
582
+ const pkg = readJson(path.join(root, 'package.json'), {});
583
+ const localVersion = pkg.version || VERSION;
584
+
585
+ console.log(`ganbatte-os v${localVersion}`);
586
+
587
+ // Checar se ha commits novos no upstream
588
+ const remotes = gitCapture(['remote'], { cwd: root });
589
+ if (!remotes.includes(UPSTREAM_REMOTE)) {
590
+ info(`Remote "${UPSTREAM_REMOTE}" nao configurado. Nao foi possivel checar atualizacoes.`);
591
+ return;
592
+ }
593
+
594
+ try {
595
+ execFileSync('git', ['fetch', UPSTREAM_REMOTE, UPSTREAM_BRANCH], {
596
+ encoding: 'utf8', stdio: 'pipe', cwd: root
597
+ });
598
+ const behind = gitCapture(
599
+ ['rev-list', '--count', `HEAD..${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}`],
600
+ { cwd: root }
601
+ );
602
+
603
+ if (behind && behind !== '0') {
604
+ console.log(`\n ${behind} commit(s) novo(s) disponivel(is).`);
605
+ console.log(' Atualize com: npm run gos:update\n');
606
+ } else {
607
+ ok('Voce esta na versao mais recente.');
608
+ }
609
+ } catch {
610
+ warn('Nao foi possivel checar atualizacoes (sem conexao?).');
611
+ }
612
+ }
613
+
614
+ // ---------------------------------------------------------------------------
615
+ // Main
616
+ // ---------------------------------------------------------------------------
617
+
618
+ function main() {
619
+ const args = process.argv.slice(2);
620
+ const command = args[0] || 'help';
621
+ const root = getRoot();
622
+
623
+ switch (command) {
624
+ case 'init':
625
+ cmdInit(root, args.slice(1));
626
+ break;
627
+
628
+ case 'install':
629
+ cmdInstall(args.slice(1));
630
+ break;
631
+
632
+ case 'update':
633
+ cmdUpdate(root, args.slice(1));
634
+ break;
635
+
636
+ case 'doctor':
637
+ cmdDoctor(root);
638
+ break;
639
+
640
+ case 'version':
641
+ case '-v':
642
+ case '--version':
643
+ cmdVersion(root);
644
+ break;
645
+
646
+ case 'help':
647
+ case '-h':
648
+ case '--help':
649
+ console.log(`
650
+ ganbatte-os CLI v${VERSION}
651
+
652
+ Comandos:
653
+ gos install Instalar G-OS no diretorio atual (via npx ou global)
654
+ gos init Setup pos-clone (remote, dirs, IDEs)
655
+ gos update Atualizar do upstream/main
656
+ gos doctor Validar integridade do workspace
657
+ gos version Mostrar versao e checar atualizacoes
658
+ gos help Exibir esta ajuda
659
+
660
+ Flags:
661
+ --force Sobrescrever arquivos existentes (install/init)
662
+ --no-stash Nao fazer stash automatico (update)
663
+
664
+ Exemplos:
665
+ npx ganbatte-os install
666
+ node scripts/cli/gos-cli.js init
667
+ npm run gos:update
668
+ npm run gos:doctor
669
+ `);
670
+ break;
671
+
672
+ default:
673
+ fail(`Comando desconhecido: ${command}`);
674
+ info('Rode: node scripts/cli/gos-cli.js help');
675
+ process.exit(1);
676
+ }
677
+ }
678
+
679
+ main();