ganbatte-os 0.2.5 → 0.2.7

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.
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const ROOT = path.resolve(__dirname, "../../..");
7
+ const STATE_DIR = path.join(ROOT, ".claude", ".hook-state");
8
+
9
+ function readStdin() {
10
+ try {
11
+ return fs.readFileSync(0, "utf8");
12
+ } catch {
13
+ return "";
14
+ }
15
+ }
16
+
17
+ function parsePayload() {
18
+ const raw = readStdin().trim();
19
+ if (!raw) return {};
20
+ try {
21
+ return JSON.parse(raw);
22
+ } catch {
23
+ return {};
24
+ }
25
+ }
26
+
27
+ function getSessionId(payload) {
28
+ return (
29
+ payload.session_id ||
30
+ payload.sessionId ||
31
+ payload.conversation_id ||
32
+ payload.conversationId ||
33
+ "default"
34
+ );
35
+ }
36
+
37
+ function ensureDir(dirPath) {
38
+ fs.mkdirSync(dirPath, { recursive: true });
39
+ }
40
+
41
+ function statePathFor(sessionId) {
42
+ return path.join(STATE_DIR, `${sessionId}.json`);
43
+ }
44
+
45
+ function readState(statePath, sessionId) {
46
+ if (!fs.existsSync(statePath)) {
47
+ return {
48
+ sessionId,
49
+ touchedFiles: [],
50
+ commands: [],
51
+ significantAction: false,
52
+ updatedAt: new Date().toISOString(),
53
+ };
54
+ }
55
+
56
+ try {
57
+ return JSON.parse(fs.readFileSync(statePath, "utf8"));
58
+ } catch {
59
+ return {
60
+ sessionId,
61
+ touchedFiles: [],
62
+ commands: [],
63
+ significantAction: false,
64
+ updatedAt: new Date().toISOString(),
65
+ };
66
+ }
67
+ }
68
+
69
+ function uniquePush(list, value) {
70
+ if (!value || list.includes(value)) return;
71
+ list.push(value);
72
+ }
73
+
74
+ function normalizePath(candidate) {
75
+ if (typeof candidate !== "string" || !candidate.trim()) return null;
76
+ const trimmed = candidate.trim();
77
+ const absolute = path.isAbsolute(trimmed) ? trimmed : path.join(ROOT, trimmed);
78
+ const normalized = path.normalize(absolute);
79
+ if (!normalized.startsWith(ROOT)) return null;
80
+ return path.relative(ROOT, normalized).replace(/\\/g, "/");
81
+ }
82
+
83
+ function collectPaths(payload) {
84
+ const args = payload.args || payload.arguments || {};
85
+ const candidates = [
86
+ args.file_path,
87
+ args.path,
88
+ args.target_file,
89
+ args.new_file_path,
90
+ payload.file_path,
91
+ payload.path,
92
+ ];
93
+
94
+ const result = [];
95
+ for (const candidate of candidates) {
96
+ const normalized = normalizePath(candidate);
97
+ if (normalized) uniquePush(result, normalized);
98
+ }
99
+ return result;
100
+ }
101
+
102
+ function extractCommand(payload) {
103
+ const args = payload.args || payload.arguments || {};
104
+ return (
105
+ args.command ||
106
+ args.cmd ||
107
+ payload.command ||
108
+ payload.cmd ||
109
+ ""
110
+ ).trim();
111
+ }
112
+
113
+ function main() {
114
+ const payload = parsePayload();
115
+ const sessionId = getSessionId(payload);
116
+ const statePath = statePathFor(sessionId);
117
+
118
+ ensureDir(STATE_DIR);
119
+ const state = readState(statePath, sessionId);
120
+
121
+ for (const filePath of collectPaths(payload)) {
122
+ uniquePush(state.touchedFiles, filePath);
123
+ }
124
+
125
+ const toolName = String(payload.tool || payload.tool_name || payload.matcher || "");
126
+ if (/Bash/i.test(toolName)) {
127
+ const command = extractCommand(payload);
128
+ if (command) uniquePush(state.commands, command);
129
+ }
130
+
131
+ if (state.touchedFiles.length > 0 || state.commands.length > 0) {
132
+ state.significantAction = true;
133
+ }
134
+
135
+ state.updatedAt = new Date().toISOString();
136
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
137
+ }
138
+
139
+ try {
140
+ main();
141
+ } catch {
142
+ // observation hook: never block
143
+ }
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const { execFileSync } = require("node:child_process");
6
+
7
+ const ROOT = path.resolve(__dirname, "../../..");
8
+ const STATE_DIR = path.join(ROOT, ".claude", ".hook-state");
9
+
10
+ function readStdin() {
11
+ try {
12
+ return fs.readFileSync(0, "utf8");
13
+ } catch {
14
+ return "";
15
+ }
16
+ }
17
+
18
+ function parsePayload() {
19
+ const raw = readStdin().trim();
20
+ if (!raw) return {};
21
+ try {
22
+ return JSON.parse(raw);
23
+ } catch {
24
+ return {};
25
+ }
26
+ }
27
+
28
+ function getSessionId(payload) {
29
+ return (
30
+ payload.session_id ||
31
+ payload.sessionId ||
32
+ payload.conversation_id ||
33
+ payload.conversationId ||
34
+ "default"
35
+ );
36
+ }
37
+
38
+ function readState(sessionId) {
39
+ const statePath = path.join(STATE_DIR, `${sessionId}.json`);
40
+ if (!fs.existsSync(statePath)) {
41
+ return { statePath, state: null };
42
+ }
43
+ try {
44
+ return {
45
+ statePath,
46
+ state: JSON.parse(fs.readFileSync(statePath, "utf8")),
47
+ };
48
+ } catch {
49
+ return { statePath, state: null };
50
+ }
51
+ }
52
+
53
+ function safeUnlink(filePath) {
54
+ try {
55
+ fs.unlinkSync(filePath);
56
+ } catch {
57
+ // ignore cleanup issues
58
+ }
59
+ }
60
+
61
+ function runNpm(args, options = {}) {
62
+ const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
63
+ return execFileSync(npmCmd, args, {
64
+ cwd: ROOT,
65
+ encoding: "utf8",
66
+ stdio: ["pipe", "pipe", "pipe"],
67
+ timeout: options.timeout || 120000,
68
+ });
69
+ }
70
+
71
+ function getGitStatusMap(paths) {
72
+ const map = new Map();
73
+ if (!Array.isArray(paths) || paths.length === 0) return map;
74
+
75
+ try {
76
+ const output = execFileSync("git", ["status", "--porcelain", "--", ...paths], {
77
+ cwd: ROOT,
78
+ encoding: "utf8",
79
+ stdio: ["pipe", "pipe", "pipe"],
80
+ timeout: 15000,
81
+ });
82
+
83
+ for (const line of output.split(/\r?\n/)) {
84
+ if (!line.trim()) continue;
85
+ const status = line.slice(0, 2);
86
+ const filePath = line.slice(3).trim().replace(/\\/g, "/");
87
+ map.set(filePath, status);
88
+ }
89
+ } catch {
90
+ // ignore git issues
91
+ }
92
+
93
+ return map;
94
+ }
95
+
96
+ function anyPathMatches(paths, matcher) {
97
+ return paths.some((filePath) => matcher.test(filePath));
98
+ }
99
+
100
+ function anyCreatedOrRemoved(statusMap, matcher) {
101
+ for (const [filePath, status] of statusMap.entries()) {
102
+ if (!matcher.test(filePath)) continue;
103
+ if (status.includes("A") || status.includes("D") || status.includes("R") || status === "??") {
104
+ return true;
105
+ }
106
+ }
107
+ return false;
108
+ }
109
+
110
+ function main() {
111
+ const payload = parsePayload();
112
+ const sessionId = getSessionId(payload);
113
+ const { statePath, state } = readState(sessionId);
114
+
115
+ if (!state || !state.significantAction) {
116
+ safeUnlink(statePath);
117
+ return;
118
+ }
119
+
120
+ const touchedFiles = Array.isArray(state.touchedFiles) ? state.touchedFiles : [];
121
+ const statusMap = getGitStatusMap(touchedFiles);
122
+ const summary = [];
123
+ const syncMatcher = /^(\.gos|\.claude|data|README\.md|CLAUDE\.md|AGENTS\.md|GEMINI\.md)/;
124
+
125
+ if (anyPathMatches(touchedFiles, syncMatcher)) {
126
+ try {
127
+ runNpm(["run", "sync:ides"], { timeout: 180000 });
128
+ summary.push("sync:ides OK");
129
+
130
+ if (anyCreatedOrRemoved(statusMap, /^(\.gos|\.claude)\//)) {
131
+ runNpm(["run", "doctor"], { timeout: 180000 });
132
+ summary.push("doctor OK");
133
+ }
134
+ } catch (error) {
135
+ const message = error.stderr || error.stdout || error.message || "falha no sync";
136
+ summary.push(`sync:ides falhou (${String(message).split(/\r?\n/)[0]})`);
137
+ }
138
+ }
139
+
140
+ safeUnlink(statePath);
141
+
142
+ if (summary.length > 0) {
143
+ process.stdout.write(`${summary.join("; ")}\n`);
144
+ }
145
+ }
146
+
147
+ try {
148
+ main();
149
+ } catch {
150
+ // observation hook: never block
151
+ }
package/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  # ganbatte-os
2
- # ganbatte-os
3
2
 
4
3
  Framework operacional para design-to-code, squads de entrega e sprint sync com ClickUp.
5
4
 
@@ -9,134 +8,72 @@ Framework operacional para design-to-code, squads de entrega e sprint sync com C
9
8
  [![NPM Home](https://img.shields.io/badge/NPM-Registry-red)](https://www.npmjs.com/package/ganbatte-os)
10
9
  ![Node >= 18](https://img.shields.io/badge/Node.js-%3E%3D18-green)
11
10
 
12
- O ganbatte-os organiza agentes de IA, skills e squads num workspace pronto para uso. Ele conecta Figma, ClickUp e 7 IDEs diferentes para acelerar a entrega de projetos de software. Baseado no framework .a8z-OS.
11
+ O **ganbatte-os** organiza agentes de IA, skills e squads num workspace pronto para uso. Ele orquestra o ciclo completo de desenvolvimento conectando Figma, ClickUp e as principais IDEs de IA (Claude Code, Gemini, Cursor, etc). Baseado nos padrões do framework `.a8z-OS`.
13
12
 
14
13
  ## Quick Start
15
14
 
16
15
  ### 1. Instalação (Recomendado)
17
- Para criar um novo workspace ganbatte-os em qualquer diretório:
16
+ Para transformar qualquer diretório em um workspace ganbatte-os:
18
17
 
19
18
  ```bash
20
19
  mkdir meu-projeto && cd meu-projeto
21
20
  npx ganbatte-os install
22
21
  ```
23
22
 
24
- Ou via clone tradicional:
25
-
26
- ```bash
27
- git clone https://github.com/adrianomorais-ganbatte/ganbatte-os.git .
28
- node scripts/cli/ganbatte-os-cli.js init
29
- ```
23
+ > [!TIP]
24
+ > Durante o desenvolvimento ou para usar a versão mais recente, você pode instalar diretamente do GitHub:
25
+ > `npx adrianomorais-ganbatte/g-os#main install`
30
26
 
31
- ### 2. Comandos Disponíveis
32
- Apos a instalação, você terá acesso aos comandos via `npm run`:
27
+ ### 2. Pós-Instalação
28
+ Após rodar o install, o framework criará uma estrutura limpa na sua raiz:
29
+ - `.gos/` — O núcleo do framework (Agentes, Skills, Scripts).
30
+ - `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` — Instruções para as IDEs.
31
+ - `packages/` — Onde você deve colocar o código do seu aplicativo.
33
32
 
34
- - `npm run ganbatte-os:doctor` — Validar integridade do workspace
35
- - `npm run ganbatte-os:update` Buscar atualizações do framework
36
- - `npm run ganbatte-os:version` — Mostrar versão instalada
33
+ ### 3. Comandos do Workspace
34
+ A partir da raiz do seu projeto, você pode gerenciar o framework:
37
35
 
38
- ## Funcionalidades
36
+ - `npm run gos:doctor` — Valida se o framework está íntegro e as IDEs configuradas.
37
+ - `npm run gos:update` — Sincroniza seu workspace com as últimas melhorias da Ganbatte.
38
+ - `npm run sync:ides` — Regenera os adapters para Claude, Gemini, Cursor e outras.
39
39
 
40
- - **Design-to-Code**: Pipeline automatizado para converter frames do Figma em código.
41
- - **Squads de Entrega**: Agentes pré-configurados para SM, PO, Dev e QA.
42
- - **Integração ClickUp**: Sincronização automática de tarefas e status.
43
- - **Suporte Multi-IDE**: Configurações otimizadas para Claude Code, Gemini, Cursor e outras.
40
+ ## Estrutura do Workspace
44
41
 
45
- ## Estrutura do Projeto
42
+ O `ganbatte-os` utiliza uma estrutura **encapsulada** para manter seu projeto limpo e organizado:
46
43
 
47
44
  ```text
48
- ├── agents/ # Perfis e instruções dos agentes
49
- ├── skills/ # Catálogo de funcionalidades reutilizáveis
50
- ├── squads/ # Definições de times de agentes
51
- ├── scripts/ # CLI e utilitários de sistema
52
- ├── manifests/ # Configurações de runtime e instalação
53
- └── packages/ # Seus projetos e código-fonte
45
+ ├── .gos/ # Core do Framework (Somente leitura para usuários)
46
+ ├── agents/ # Perfis e instruções dos agentes IA
47
+ ├── skills/ # Catálogo de ferramentas (ex: design-to-code)
48
+ ├── scripts/ # Engine do CLI e integração de IDEs
49
+ │ └── prompts/ # Prompts canônicos para os agentes
50
+ ├── .gos-local/ # Dados locais (logs, queues, worktrees) - ignorado no git
51
+ ├── packages/ # Seu código-fonte e projetos vivem aqui
52
+ ├── AGENTS.md # Entrypoint de agentes para o framework
53
+ ├── CLAUDE.md # Instruções específicas para Claude Code
54
+ └── GEMINI.md # Instruções específicas para Google Gemini
54
55
  ```
55
56
 
56
- ## Contribuição
57
-
58
- Este é um projeto interno da **Ganbatte**. Para sugestões ou bugs, abra uma issue no repositório.
59
-
60
- ---
61
- © 2026 Ganbatte. Todos os direitos reservados.
62
-
63
- ## Agentes
64
-
65
- | Nome | Foco |
66
- |------|------|
67
- | ux-design-expert | Design de interfaces e UX |
68
- | architect | Arquitetura de software |
69
- | dev | Desenvolvimento full-stack |
70
- | sm | Scrum Master e facilitacao |
71
- | po | Product Owner e priorizacao |
72
- | devops | Infraestrutura e CI/CD |
73
- | squad-creator | Montagem de squads |
57
+ ## Funcionalidades Principais
74
58
 
75
- ## Skills
59
+ - **Design-to-Code**: Pipeline automatizado para converter frames do Figma em componentes React/Next.js de alta fidelidade.
60
+ - **Squads de Entrega**: Agentes especializados (SM, PO, Dev, QA) que trabalham de forma coordenada.
61
+ - **Sincronização ClickUp**: Conecta seu workspace diretamente ao ClickUp para automação de status e tarefas.
62
+ - **Multi-IDE Multi-Tenant**: Configurações automáticas para as melhores ferramentas de IA do mercado.
76
63
 
77
- | Nome | Foco |
78
- |------|------|
79
- | design-to-code | Figma para codigo React |
80
- | figma-implement-design | Implementacao de designs Figma |
81
- | figma-make-analyzer | Analise de output do Figma Make |
82
- | make-code-triage | Triagem de codigo gerado |
83
- | make-version-diff | Diff entre versoes de componentes |
84
- | component-dedup | Deduplicacao de componentes |
85
- | frontend-dev | Desenvolvimento frontend |
86
- | react-best-practices | Boas praticas React/Next.js |
87
- | react-doctor | Diagnostico de problemas React |
88
- | sprint-planner | Planejamento de sprints |
89
- | clickup | Integracao ClickUp API |
90
- | plan-to-tasks | Conversao de planos em tasks |
91
- | agent-teams | Orquestracao multi-agente |
92
-
93
- ## Squads
64
+ ## Agentes Disponíveis
94
65
 
95
66
  | Nome | Foco |
96
67
  |------|------|
97
- | design-delivery | Entrega de design-to-code |
98
- | design-squad | Squad de design |
99
- | sprint-planning | Planejamento e sync de sprints |
100
-
101
- ## IDEs suportadas
102
-
103
- Claude Code, Codex (VS Code), Gemini, OpenCode, Antigravity, Cursor, KiloCode
104
-
105
- Cada IDE recebe adapters finos que apontam para os arquivos canonicos em `agents/` e `skills/`.
106
-
107
- ## Estrutura
68
+ | **ux-design-expert** | Design de interfaces, tokens e design systems. |
69
+ | **architect** | Definição de stack, padrões técnicos e revisões de código. |
70
+ | **dev** | Implementação de features, hooks e refinamentos visuais. |
71
+ | **sm / po** | Gestão de sprint, priorização de backlog e sync com stakeholders. |
72
+ | **squad-creator** | Orquestração de times multi-agentes para tarefas complexas. |
108
73
 
109
- ```
110
- g-os/
111
- agents/profiles/ Perfis de agentes IA
112
- skills/ Skills plugaveis (cada uma com SKILL.md)
113
- squads/ Definicoes de squads e workflows
114
- scripts/
115
- cli/ CLI gos-cli.js
116
- tools/ Ferramentas (clickup.js, etc)
117
- integrations/ Sync e validacao de IDEs
118
- manifests/ Manifestos de runtime e instalacao
119
- packages/ Seus projetos aqui
120
- docs/ Documentacao
121
- integrations/ Command maps por IDE
122
- templates/ Templates reutilizaveis
123
- prompts/ Prompts canonicos
124
- ```
125
-
126
- ## Scripts
74
+ ## Licença
127
75
 
128
- | Script | O que faz |
129
- |--------|-----------|
130
- | `npx g-os install` | Instalação via NPX no diretório atual |
131
- | `npm run gos:init` | Setup pos-clone |
132
- | `npm run gos:update` | Atualizar do upstream |
133
- | `npm run gos:doctor` | Validar integridade |
134
- | `npm run gos:version` | Ver versao e checar updates |
135
- | `npm run clickup` | CLI ClickUp API |
136
- | `npm run sync:ides` | Sincronizar IDE adapters |
137
- | `npm run check:ides` | Validar IDE adapters |
138
- | `npm run doctor` | Validacao completa |
76
+ Este é um projeto interno da **Ganbatte**. Distribuído sob licença [MIT](LICENSE).
139
77
 
140
- ## Licenca
141
-
142
- [MIT](LICENSE)
78
+ ---
79
+ © 2026 Ganbatte. Todos os direitos reservados.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ganbatte-os",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Framework operacional para design-to-code, squads de entrega e sprint sync com ClickUp.",
5
5
  "bin": {
6
6
  "ganbatte-os": ".gos/scripts/cli/gos-cli.js",