@aksp/opencrew 1.6.3 → 1.7.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.
- package/CHANGELOG.md +86 -0
- package/README.md +50 -5
- package/package.json +1 -1
- package/templates/AGENTS.md +20 -6
- package/templates/_opencrew/.opencrew-version +1 -1
- package/templates/_opencrew/core/architect.agent.yaml +1 -1
- package/templates/_opencrew/core/escritorio/animacao.js +64 -0
- package/templates/_opencrew/core/escritorio/app.js +137 -0
- package/templates/_opencrew/core/escritorio/cena.js +132 -0
- package/templates/_opencrew/core/escritorio/demo.js +79 -0
- package/templates/_opencrew/core/escritorio/escala.js +27 -0
- package/templates/_opencrew/core/escritorio/index.html +166 -0
- package/templates/_opencrew/core/escritorio/modelo-agentes.js +93 -0
- package/templates/_opencrew/core/escritorio/modelo-estado.js +71 -0
- package/templates/_opencrew/core/escritorio/modelo-mesas.js +81 -0
- package/templates/_opencrew/core/escritorio/modelo-pagina.js +95 -0
- package/templates/_opencrew/core/escritorio/modelo-textos.js +65 -0
- package/templates/_opencrew/core/escritorio/modelo-visao.js +91 -0
- package/templates/_opencrew/core/escritorio/modelo.js +29 -0
- package/templates/_opencrew/core/escritorio/painel.js +120 -0
- package/templates/_opencrew/core/escritorio/quadro.js +106 -0
- package/templates/_opencrew/core/escritorio/rota.js +62 -0
- package/templates/_opencrew/core/escritorio/rotulos.js +78 -0
- package/templates/_opencrew/core/escritorio/sprites-mesa.js +122 -0
- package/templates/_opencrew/core/escritorio/sprites-sala.js +92 -0
- package/templates/_opencrew/core/escritorio/sprites.js +187 -0
- package/templates/_opencrew/core/prompts/build.prompt.md +3 -3
- package/templates/_opencrew/core/prompts/discovery.prompt.md +1 -1
- package/templates/_opencrew/core/prompts/repair.prompt.md +7 -12
- package/templates/_opencrew/core/runner.pipeline.md +124 -223
- package/templates/_opencrew/core/scripts/caminho/argumentos.mjs +49 -0
- package/templates/_opencrew/core/scripts/caminho/disco.mjs +36 -0
- package/templates/_opencrew/core/scripts/caminho/nucleo.mjs +61 -0
- package/templates/_opencrew/core/scripts/caminho.mjs +124 -0
- package/templates/_opencrew/core/scripts/escritorio/leitura.mjs +31 -0
- package/templates/_opencrew/core/scripts/escritorio/porta.mjs +98 -0
- package/templates/_opencrew/core/scripts/escritorio/projeto.mjs +29 -0
- package/templates/_opencrew/core/scripts/escritorio/servidor.mjs +78 -0
- package/templates/_opencrew/core/scripts/escritorio.mjs +117 -0
- package/templates/_opencrew/core/scripts/estado/argumentos.mjs +61 -0
- package/templates/_opencrew/core/scripts/estado/arquivo.mjs +53 -0
- package/templates/_opencrew/core/scripts/estado/decisao.mjs +56 -0
- package/templates/_opencrew/core/scripts/estado/elenco.mjs +58 -0
- package/templates/_opencrew/core/scripts/estado/nucleo.mjs +113 -0
- package/templates/_opencrew/core/scripts/estado/preferencia.mjs +24 -0
- package/templates/_opencrew/core/scripts/estado.mjs +96 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// A mesa de cada agente e o que muda nela, em matrizes de pixels: o tampo com os pés, o monitor
|
|
2
|
+
// com as telas de cada status e os sinais que aparecem sobre a cabeça do boneco (✓, "!" e "?"
|
|
3
|
+
// são desenhos, não texto). Quem diz onde cada desenho vai é `cena.js`.
|
|
4
|
+
// Spec: fase-e1-escritorio-ao-vivo.md, regras 16, 18 e 19 (repositório do OpenCrew).
|
|
5
|
+
import { CORES, matriz } from './sprites.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A mesa vista de cima e de frente: o tampo (com teclado, papel e caneca), a borda, a saia com a
|
|
9
|
+
* gaveta e os pés. Tem a largura do retângulo da mesa no modelo e `MESA_ACIMA` linhas a mais.
|
|
10
|
+
*/
|
|
11
|
+
export const MESA = matriz({
|
|
12
|
+
o: CORES.tinta, t: CORES.madeiraLuz, T: CORES.madeira, F: CORES.madeiraMedia, D: CORES.madeiraEscura, x: CORES.junta,
|
|
13
|
+
k: CORES.cinzaEscuro, K: CORES.cinzaClaro, w: CORES.branco, g: CORES.cinzaClaro, c: CORES.ceu, f: CORES.madeiraEscura,
|
|
14
|
+
}, [
|
|
15
|
+
'.oooooooooooooooooooooooooooooooooooooooooo.',
|
|
16
|
+
'otttttttttttttttkkkkkkkkkkkkttttttttttttttto',
|
|
17
|
+
'oTTTTTTTTTTTTTTTkKKKKKKKKKKkTTTTwwwwwwTcccTo',
|
|
18
|
+
'oTTTTTTTTTTTTTTTkkkkkkkkkkkkTTTTwggggwTcfcTo',
|
|
19
|
+
'oTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTwwwwwwTcccTo',
|
|
20
|
+
'oTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTwgggwwTTTTTo',
|
|
21
|
+
'oTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTwwwwwwTTTTTo',
|
|
22
|
+
'oFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFo',
|
|
23
|
+
'oooooooooooooooooooooooooooooooooooooooooooo',
|
|
24
|
+
'.oDDDDDDDDDDDDDDDDDDFFFFDDDDDDDDDDDDDDDDDDo.',
|
|
25
|
+
'.oDDooooooooooooooooooooooooooooooooooooDDo.',
|
|
26
|
+
'.oDDoxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxoDDo.',
|
|
27
|
+
'.oDDoxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxoDDo.',
|
|
28
|
+
'.oDDo..................................oDDo.',
|
|
29
|
+
'.oooo..................................oooo.',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Quantas linhas do desenho da mesa ficam acima do retângulo do tampo: é o fundo do tampo, que
|
|
34
|
+
* cobre as pernas de quem está sentado atrás dele.
|
|
35
|
+
*/
|
|
36
|
+
export const MESA_ACIMA = 4;
|
|
37
|
+
|
|
38
|
+
/** O monitor, de frente para quem olha, com a tela apagada; a base pousa no fundo do tampo. */
|
|
39
|
+
export const MONITOR = matriz({ o: CORES.tinta, g: CORES.cinzaEscuro, k: CORES.telaApagada, G: CORES.cinzaClaro }, [
|
|
40
|
+
'oooooooooooo',
|
|
41
|
+
'oggggggggggo',
|
|
42
|
+
'ogkkkkkkkkgo',
|
|
43
|
+
'ogkkkkkkkkgo',
|
|
44
|
+
'ogkkkkkkkkgo',
|
|
45
|
+
'ogkkkkkkkkgo',
|
|
46
|
+
'ogkkkkkkkkgo',
|
|
47
|
+
'oggggggggggo',
|
|
48
|
+
'oooooooooooo',
|
|
49
|
+
'....oGGo....',
|
|
50
|
+
'..oGGGGGGo..',
|
|
51
|
+
'..oooooooo..',
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
/** Onde o monitor fica, a partir do canto do retângulo da mesa; e a tela, a partir do canto do monitor. */
|
|
55
|
+
export const MONITOR_EM = Object.freeze({ x: 1, y: -13 });
|
|
56
|
+
export const TELA_EM = Object.freeze({ x: 2, y: 2 });
|
|
57
|
+
|
|
58
|
+
const CODIGO = ['vlllllvv', 'vvvvvvvv', 'vlllvllv', 'vvvvvvvv'];
|
|
59
|
+
const LINHAS_DA_TELA = [0, 1, 2, 3, 4];
|
|
60
|
+
|
|
61
|
+
/** O monitor aceso, uma tela por fase (0 a 3): as linhas de código sobem um pixel a cada fase. */
|
|
62
|
+
export const TELAS_ACESAS = Object.freeze([0, 1, 2, 3].map((fase) => matriz(
|
|
63
|
+
{ v: CORES.telaAcesa, l: CORES.verde },
|
|
64
|
+
LINHAS_DA_TELA.map((linha) => CODIGO[(linha + fase) % CODIGO.length]),
|
|
65
|
+
)));
|
|
66
|
+
|
|
67
|
+
/** Âmbar, com o sinal de pausa: está esperando o usuário. */
|
|
68
|
+
export const TELA_AMBAR = matriz({ y: CORES.ambar, o: CORES.tinta }, [
|
|
69
|
+
'yyyyyyyy',
|
|
70
|
+
'yyoyyoyy',
|
|
71
|
+
'yyoyyoyy',
|
|
72
|
+
'yyoyyoyy',
|
|
73
|
+
'yyyyyyyy',
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
/** Vermelha, com um xis: falhou. */
|
|
77
|
+
export const TELA_VERMELHA = matriz({ r: CORES.vermelho, o: CORES.tinta }, [
|
|
78
|
+
'rrrrrrrr',
|
|
79
|
+
'rrorrorr',
|
|
80
|
+
'rrroorrr',
|
|
81
|
+
'rrorrorr',
|
|
82
|
+
'rrrrrrrr',
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
/** Sobre a cabeça de quem concluiu. */
|
|
86
|
+
export const SINAL_FEITO = matriz({ o: CORES.tinta, g: CORES.verde }, [
|
|
87
|
+
'......ooo',
|
|
88
|
+
'.....oogo',
|
|
89
|
+
'ooo.ooggo',
|
|
90
|
+
'ogoooggoo',
|
|
91
|
+
'oggoggoo.',
|
|
92
|
+
'oogggoo..',
|
|
93
|
+
'.oogoo...',
|
|
94
|
+
'..ooo....',
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
/** Sobre a cabeça de quem falhou. */
|
|
98
|
+
export const SINAL_FALHA = matriz({ o: CORES.tinta, r: CORES.vermelho }, [
|
|
99
|
+
'oooo',
|
|
100
|
+
'orro',
|
|
101
|
+
'orro',
|
|
102
|
+
'orro',
|
|
103
|
+
'orro',
|
|
104
|
+
'oooo',
|
|
105
|
+
'orro',
|
|
106
|
+
'oooo',
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
/** Sobre a cabeça de quem trabalhava e está sem sinal. */
|
|
110
|
+
export const SINAL_DUVIDA = matriz({ o: CORES.tinta, w: CORES.branco }, [
|
|
111
|
+
'.oooo.',
|
|
112
|
+
'oowwoo',
|
|
113
|
+
'owoowo',
|
|
114
|
+
'ooowoo',
|
|
115
|
+
'.owoo.',
|
|
116
|
+
'.ooo..',
|
|
117
|
+
'.owo..',
|
|
118
|
+
'.ooo..',
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
/** A sombra no chão de quem está em pé, fora da mesa. */
|
|
122
|
+
export const SOMBRA = matriz({ x: CORES.junta }, ['.xxxxxxxx.']);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// A sala do escritório, em matrizes de pixels: a parede do fundo, o piso em ladrilho de dois tons
|
|
2
|
+
// e o que enfeita a parede (janela, relógio, planta). Quem diz onde cada desenho vai é `cena.js`.
|
|
3
|
+
// Spec: fase-e1-escritorio-ao-vivo.md, regra 16 (repositório do OpenCrew).
|
|
4
|
+
import { CORES, matriz } from './sprites.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A parede, numa faixa de 8 px que se repete de lado a lado: sanca de madeira, papel de parede
|
|
8
|
+
* listrado e lambri. A altura é a da parede no modelo (`TOPO`).
|
|
9
|
+
*/
|
|
10
|
+
export const PAREDE = matriz({ m: CORES.madeiraMedia, d: CORES.madeiraEscura, p: CORES.parede, P: CORES.paredeSombra, h: CORES.madeiraLuz }, [
|
|
11
|
+
'mmmmmmmm',
|
|
12
|
+
'dddddddd',
|
|
13
|
+
'PPPPPPPP',
|
|
14
|
+
'pppppppP',
|
|
15
|
+
'pppppppP',
|
|
16
|
+
'pppppppP',
|
|
17
|
+
'pppppppP',
|
|
18
|
+
'pppppppP',
|
|
19
|
+
'pppppppP',
|
|
20
|
+
'pppppppP',
|
|
21
|
+
'pppppppP',
|
|
22
|
+
'pppppppP',
|
|
23
|
+
'pppppppP',
|
|
24
|
+
'pppppppP',
|
|
25
|
+
'hhhhhhhh',
|
|
26
|
+
'mmmmmmmm',
|
|
27
|
+
'mmmmmmmm',
|
|
28
|
+
'dddddddd',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
const LADRILHO_LINHAS = Object.freeze([
|
|
32
|
+
'jjjjjjjjjjjjjjjj',
|
|
33
|
+
'jaaaaaaaaaaaaaaa',
|
|
34
|
+
'jaaaaaaaaaaaaaaa',
|
|
35
|
+
'jaaaaaaaaaaaaaaa',
|
|
36
|
+
'jaaaaaaaaaaaaaaa',
|
|
37
|
+
'jaaaaaaaaaaaaaaa',
|
|
38
|
+
'jaaaaaaaaaaaaaaa',
|
|
39
|
+
'jaaaaaaaaaaaaaaa',
|
|
40
|
+
'jaaaaaaaaaaaaaaa',
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
/** O ladrilho do piso, com a junta em cima e à esquerda; o claro e o escuro se alternam em xadrez. */
|
|
44
|
+
export const LADRILHO = matriz({ j: CORES.junta, a: CORES.pisoClaro }, LADRILHO_LINHAS);
|
|
45
|
+
export const LADRILHO_ESCURO = matriz({ j: CORES.junta, a: CORES.pisoEscuro }, LADRILHO_LINHAS);
|
|
46
|
+
|
|
47
|
+
/** Janela de duas folhas: um reflexo no vidro da esquerda, uma nuvem no da direita. */
|
|
48
|
+
export const JANELA = matriz({ o: CORES.tinta, w: CORES.branco, b: CORES.ceu, B: CORES.ceuClaro }, [
|
|
49
|
+
'oooooooooooooooooooooooo',
|
|
50
|
+
'owwwwwwwwwwwwwwwwwwwwwwo',
|
|
51
|
+
'owbbbbbBBbbwwbbbbbbbbbwo',
|
|
52
|
+
'owbbbbBBbbbwwbbbbwwbbbwo',
|
|
53
|
+
'owbbbBBbbbbwwbbwwwwwbbwo',
|
|
54
|
+
'owbbBBbbbbbwwbbbbbbbbbwo',
|
|
55
|
+
'owbBBbbbbbbwwbbbbbbbbbwo',
|
|
56
|
+
'owbbbbbbbbbwwbbbbbbbbbwo',
|
|
57
|
+
'owwwwwwwwwwwwwwwwwwwwwwo',
|
|
58
|
+
'oooooooooooooooooooooooo',
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
/** Relógio de parede, parado nas três horas: nada na sala se mexe sem um agente trabalhando. */
|
|
62
|
+
export const RELOGIO = matriz({ o: CORES.tinta, w: CORES.branco }, [
|
|
63
|
+
'..ooooo..',
|
|
64
|
+
'.owwwwwo.',
|
|
65
|
+
'owwwowwwo',
|
|
66
|
+
'owwwowwwo',
|
|
67
|
+
'owwwooowo',
|
|
68
|
+
'owwwwwwwo',
|
|
69
|
+
'owwwwwwwo',
|
|
70
|
+
'.owwwwwo.',
|
|
71
|
+
'..ooooo..',
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
/** Planta em vaso de barro, para o chão junto à parede. */
|
|
75
|
+
export const PLANTA = matriz({ o: CORES.tinta, g: CORES.folha, G: CORES.folhaEscura, t: CORES.madeiraEscura, v: CORES.madeiraMedia, V: CORES.madeiraEscura }, [
|
|
76
|
+
'...ooooo...',
|
|
77
|
+
'..oggggGo..',
|
|
78
|
+
'.oggGggggo.',
|
|
79
|
+
'oggggggGggo',
|
|
80
|
+
'ogGggggggGo',
|
|
81
|
+
'oggggGggggo',
|
|
82
|
+
'.ogGgggGgo.',
|
|
83
|
+
'..oggggGo..',
|
|
84
|
+
'...oGGGo...',
|
|
85
|
+
'....oto....',
|
|
86
|
+
'..ooooooo..',
|
|
87
|
+
'..ovvvvvo..',
|
|
88
|
+
'..ovvvvVo..',
|
|
89
|
+
'...ovvVo...',
|
|
90
|
+
'...ovvVo...',
|
|
91
|
+
'...ooooo...',
|
|
92
|
+
]);
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Os desenhos do escritório são matrizes de pixels escritas como texto: uma string por linha, uma
|
|
2
|
+
// letra por pixel e uma paleta (letra → cor). Nenhuma imagem entra no pacote.
|
|
3
|
+
// Este módulo traz as cores fixas de toda a cena, o molde do boneco de 16×16 com as trocas de
|
|
4
|
+
// linha de cada pose, e a conta que transforma uma matriz nos retângulos que a cena preenche.
|
|
5
|
+
// Os irmãos `sprites-sala.js` e `sprites-mesa.js` trazem a sala e os móveis.
|
|
6
|
+
// Spec: fase-e1-escritorio-ao-vivo.md, regra 16 (repositório do OpenCrew).
|
|
7
|
+
|
|
8
|
+
/** As cores fixas da cena. A camisa, o cabelo e a pele de cada boneco vêm do modelo. */
|
|
9
|
+
export const CORES = Object.freeze({
|
|
10
|
+
tinta: '#1a1c2c',
|
|
11
|
+
branco: '#f4f4ee',
|
|
12
|
+
cinzaClaro: '#c3c8d4',
|
|
13
|
+
cinzaEscuro: '#4a5266',
|
|
14
|
+
pisoClaro: '#9aa5b8',
|
|
15
|
+
pisoEscuro: '#8d98ad',
|
|
16
|
+
junta: '#808ba1',
|
|
17
|
+
parede: '#ead9b5',
|
|
18
|
+
paredeSombra: '#d6c196',
|
|
19
|
+
madeiraLuz: '#dba76a',
|
|
20
|
+
madeira: '#c58a52',
|
|
21
|
+
madeiraMedia: '#a0683f',
|
|
22
|
+
madeiraEscura: '#6f4630',
|
|
23
|
+
ceu: '#7ec4e0',
|
|
24
|
+
ceuClaro: '#bfe6f0',
|
|
25
|
+
folha: '#4c9a52',
|
|
26
|
+
folhaEscura: '#2f6b40',
|
|
27
|
+
telaApagada: '#232838',
|
|
28
|
+
telaAcesa: '#123f4a',
|
|
29
|
+
verde: '#5fd47a',
|
|
30
|
+
ambar: '#f4a73b',
|
|
31
|
+
vermelho: '#e0564c',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Uma matriz de pixels: `linhas` do mesmo tamanho e a `paleta` com a cor de cada letra. O ponto
|
|
36
|
+
* é sempre o pixel vazio.
|
|
37
|
+
*/
|
|
38
|
+
export function matriz(paleta, linhas) {
|
|
39
|
+
return Object.freeze({ paleta: Object.freeze({ '.': null, ...paleta }), linhas: Object.freeze(linhas) });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* O molde do boneco: 16×16, de frente, parado. Na paleta, `cabelo`, `pele`, `camisa` e as duas
|
|
44
|
+
* sombras são fendas que `coresDoBoneco` troca pelas cores de cada agente.
|
|
45
|
+
*/
|
|
46
|
+
export const MOLDE = matriz({
|
|
47
|
+
o: CORES.tinta, h: 'cabelo', s: 'pele', S: 'pele-sombra', c: 'camisa', C: 'camisa-sombra',
|
|
48
|
+
p: CORES.cinzaEscuro, P: CORES.telaApagada, b: CORES.madeiraEscura, w: CORES.branco, g: CORES.cinzaClaro,
|
|
49
|
+
}, [
|
|
50
|
+
'....oooooooo....',
|
|
51
|
+
'...ohhhhhhhho...',
|
|
52
|
+
'..ohhhhhhhhhho..',
|
|
53
|
+
'..ohhhhhhhhhho..',
|
|
54
|
+
'..ohhsssssshho..',
|
|
55
|
+
'..ohsssssssSho..',
|
|
56
|
+
'..ossossssosSo..',
|
|
57
|
+
'..osssssssssSo..',
|
|
58
|
+
'...oSSSSSSSSo...',
|
|
59
|
+
'..oCccccccccCo..',
|
|
60
|
+
'..oCccccccccCo..',
|
|
61
|
+
'..osccccccccso..',
|
|
62
|
+
'...oCCCCCCCCo...',
|
|
63
|
+
'....oppppppo....',
|
|
64
|
+
'....oppoopPo....',
|
|
65
|
+
'...obbboobbbo...',
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* As poses são o molde com linhas trocadas: cada troca diz o número da linha e o texto novo.
|
|
70
|
+
* `digitar` e `andar` têm dois quadros; `mao` é o braço levantado de quem espera; `festa`, os
|
|
71
|
+
* dois braços para cima de quem comemora; `papel` é o braço com o papel, que se soma às pernas
|
|
72
|
+
* de quem anda.
|
|
73
|
+
*/
|
|
74
|
+
export const TROCAS = Object.freeze({
|
|
75
|
+
'digitar-a': { 11: '..oCccccccccso..', 12: '...ossCCCCCCo...' },
|
|
76
|
+
'digitar-b': { 11: '..osccccccccCo..', 12: '...oCCCCCCsso...' },
|
|
77
|
+
'andar-a': { 14: '....oppoobbo....', 15: '...obbbo.oo.....' },
|
|
78
|
+
'andar-b': { 14: '....obboopPo....', 15: '.....oo.obbbo...' },
|
|
79
|
+
mao: {
|
|
80
|
+
0: '....oooooooo.oo.',
|
|
81
|
+
1: '...ohhhhhhhhosso',
|
|
82
|
+
2: '..ohhhhhhhhhhoso',
|
|
83
|
+
3: '..ohhhhhhhhhhoso',
|
|
84
|
+
4: '..ohhsssssshhoCo',
|
|
85
|
+
5: '..ohsssssssShoCo',
|
|
86
|
+
6: '..ossossssosSoCo',
|
|
87
|
+
7: '..osssssssssSoCo',
|
|
88
|
+
8: '...oSSSSSSSSoCCo',
|
|
89
|
+
9: '..oCcccccccccCo.',
|
|
90
|
+
11: '..osccccccccCo..',
|
|
91
|
+
},
|
|
92
|
+
festa: {
|
|
93
|
+
0: '.oo.oooooooo.oo.',
|
|
94
|
+
1: 'ossohhhhhhhhosso',
|
|
95
|
+
2: 'osohhhhhhhhhhoso',
|
|
96
|
+
3: 'osohhhhhhhhhhoso',
|
|
97
|
+
4: 'oCohhsssssshhoCo',
|
|
98
|
+
5: 'oCohsssssssShoCo',
|
|
99
|
+
6: 'oCossossssosSoCo',
|
|
100
|
+
7: 'oCosssssssssSoCo',
|
|
101
|
+
8: 'oCCoSSSSSSSSoCCo',
|
|
102
|
+
9: '.oCccccccccccCo.',
|
|
103
|
+
11: '..oCccccccccCo..',
|
|
104
|
+
},
|
|
105
|
+
papel: {
|
|
106
|
+
8: '...oSSSSSSSSooo.',
|
|
107
|
+
9: '..oCccccccccCwwo',
|
|
108
|
+
10: '..oCccccccccCwgo',
|
|
109
|
+
11: '..osccccccccswwo',
|
|
110
|
+
12: '...oCCCCCCCCoooo',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const virar = (linha) => [...linha].reverse().join('');
|
|
115
|
+
const POSTAS = new Map();
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* As 16 linhas do boneco numa pose. A mesma pose devolve sempre a mesma lista.
|
|
119
|
+
* @param {string} pose uma das poses de `quadro` (`parado` é o molde)
|
|
120
|
+
* @param {{ papel?: boolean, festa?: boolean, espelhado?: boolean }} [o] `papel`: leva o papel ·
|
|
121
|
+
* `festa`: os dois braços para cima, no lugar da pose · `espelhado`: virado para a esquerda
|
|
122
|
+
*/
|
|
123
|
+
export function linhasDoBoneco(pose, { papel = false, festa = false, espelhado = false } = {}) {
|
|
124
|
+
const chave = `${pose}|${papel}|${festa}|${espelhado}`;
|
|
125
|
+
if (!POSTAS.has(chave)) {
|
|
126
|
+
const trocas = { ...(festa ? TROCAS.festa : TROCAS[pose]), ...(papel ? TROCAS.papel : null) };
|
|
127
|
+
const linhas = MOLDE.linhas.map((linha, i) => trocas[i] ?? linha);
|
|
128
|
+
POSTAS.set(chave, espelhado ? linhas.map(virar) : linhas);
|
|
129
|
+
}
|
|
130
|
+
return POSTAS.get(chave);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A cor um quarto mais escura: a sombra que dá volume à pele e à camisa. */
|
|
134
|
+
export function sombra(cor) {
|
|
135
|
+
const canal = (inicio) => Math.round(parseInt(cor.slice(inicio, inicio + 2), 16) * 0.75).toString(16).padStart(2, '0');
|
|
136
|
+
return `#${canal(1)}${canal(3)}${canal(5)}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const PALETAS = new Map();
|
|
140
|
+
|
|
141
|
+
/** A paleta do molde com as cores de um agente (`{ camisa, cabelo, pele }`, em `#rrggbb`). */
|
|
142
|
+
export function coresDoBoneco({ camisa, cabelo, pele }) {
|
|
143
|
+
const chave = `${camisa}|${cabelo}|${pele}`;
|
|
144
|
+
if (!PALETAS.has(chave)) {
|
|
145
|
+
const fendas = { cabelo, pele, 'pele-sombra': sombra(pele), camisa, 'camisa-sombra': sombra(camisa) };
|
|
146
|
+
PALETAS.set(chave, Object.fromEntries(Object.entries(MOLDE.paleta).map(([letra, cor]) => [letra, fendas[cor] ?? cor])));
|
|
147
|
+
}
|
|
148
|
+
return PALETAS.get(chave);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Os trechos de uma linha: `[x, largura, letra]` de cada sequência da mesma letra, sem os vazios. */
|
|
152
|
+
function trechos(linha) {
|
|
153
|
+
return [...linha.matchAll(/([^.])\1*/g)].map((achado) => [achado.index, achado[0].length, achado[1]]);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const guardar = (lista, item) => {
|
|
157
|
+
lista.push(item);
|
|
158
|
+
return item;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/** Trechos iguais em linhas seguidas viram um retângulo só: a cena preenche menos vezes. */
|
|
162
|
+
function juntar(linhas) {
|
|
163
|
+
const todos = [];
|
|
164
|
+
let acima = new Map();
|
|
165
|
+
linhas.forEach((linha, y) => {
|
|
166
|
+
const nesta = new Map();
|
|
167
|
+
for (const [x, largura, letra] of trechos(linha)) {
|
|
168
|
+
const chave = `${x}:${largura}:${letra}`;
|
|
169
|
+
const retangulo = acima.get(chave) ?? guardar(todos, [x, y, largura, 0, letra]);
|
|
170
|
+
retangulo[3] += 1;
|
|
171
|
+
nesta.set(chave, retangulo);
|
|
172
|
+
}
|
|
173
|
+
acima = nesta;
|
|
174
|
+
});
|
|
175
|
+
return todos;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const RETANGULOS = new WeakMap();
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Os retângulos que desenham uma matriz: `[x, y, largura, altura, letra]`, a partir do canto
|
|
182
|
+
* superior esquerdo dela. A conta é feita uma vez por lista de linhas.
|
|
183
|
+
*/
|
|
184
|
+
export function retangulos(linhas) {
|
|
185
|
+
if (!RETANGULOS.has(linhas)) RETANGULOS.set(linhas, juntar(linhas));
|
|
186
|
+
return RETANGULOS.get(linhas);
|
|
187
|
+
}
|
|
@@ -131,9 +131,9 @@ Generate these files. Use the Write tool for all file creation — never use Bas
|
|
|
131
131
|
- **`displayName` is REQUIRED and MUST be byte-for-byte identical to the agent's
|
|
132
132
|
`name:` frontmatter field in its `.agent.md`** (the mandatory two-word "FirstName
|
|
133
133
|
LastName" persona name). The Pipeline Runner reads `displayName` — NOT `title` — to
|
|
134
|
-
render the agent's name in
|
|
135
|
-
|
|
136
|
-
of the persona name, the crew renders with functions but no names.
|
|
134
|
+
render the agent's name in "🤖 {name} is working…" announcements, and the Escritório
|
|
135
|
+
(the optional live view) shows the same column. If `displayName` is missing, empty, or set
|
|
136
|
+
to the role/title instead of the persona name, the crew renders with functions but no names.
|
|
137
137
|
- `id` = the `path` basename with `./agents/` and `.agent.md` stripped
|
|
138
138
|
(e.g. `./agents/researcher.agent.md` → `researcher`).
|
|
139
139
|
- `title` = the agent's `title:` frontmatter (the role/function label). This is a
|
|
@@ -305,7 +305,7 @@ target_formats: # content crews only; empty list for others
|
|
|
305
305
|
|
|
306
306
|
The `crew_code` must be a short, URL-safe slug derived from the crew's purpose (e.g., `content-calendar`, `competitor-tracker`, `lead-notify`).
|
|
307
307
|
|
|
308
|
-
**CRITICAL — Name uniqueness:** The `crew_code` MUST NEVER match any existing folder name in `crews/`. Before finalizing,
|
|
308
|
+
**CRITICAL — Name uniqueness:** The `crew_code` MUST NEVER match any existing folder name in `crews/`. Before finalizing, list the existing folders of `crews/` with the IDE's folder-listing tool (no shell command); if `crews/` does not exist yet, there are none. If the slug you derive matches an existing folder, append a numeric suffix (`-2`, `-3`, etc.) until it is unique. Never reuse an existing crew folder name — doing so would overwrite another crew's files.
|
|
309
309
|
|
|
310
310
|
---
|
|
311
311
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Repair — Fix Crew Agent Names / Manifest
|
|
2
2
|
|
|
3
3
|
You are the opencrew Repair agent. Your job is to fix an **already-created** crew whose
|
|
4
|
-
agents show their function/role but not their persona names (e.g. the
|
|
5
|
-
Pipeline Runner
|
|
4
|
+
agents show their function/role but not their persona names (e.g. the Escritório and the
|
|
5
|
+
Pipeline Runner show "Pesquisador" instead of "Pedro Pesquisa").
|
|
6
6
|
|
|
7
7
|
This is a known defect in crews built by older versions: the `crew-party.csv` manifest was
|
|
8
8
|
generated without a `displayName` column (or with the role/title in it instead of the
|
|
@@ -13,10 +13,9 @@ re-run the Build phase.
|
|
|
13
13
|
|
|
14
14
|
## Scope
|
|
15
15
|
|
|
16
|
-
You may ONLY touch files under `crews/{code}/`:
|
|
16
|
+
You may ONLY touch these files under `crews/{code}/`:
|
|
17
17
|
- `crews/{code}/crew-party.csv`
|
|
18
18
|
- `crews/{code}/agents/*.agent.md` (only in the fallback case — see Step 4)
|
|
19
|
-
- `crews/{code}/state.json` (only if it exists)
|
|
20
19
|
|
|
21
20
|
Never modify `_opencrew/`, `templates/`, or any other crew. Use the Write tool for all file
|
|
22
21
|
writes (never Bash `mkdir`).
|
|
@@ -77,13 +76,7 @@ existed and must be generated now, following the **Agent Naming Convention** fro
|
|
|
77
76
|
Only do this for agents that are actually broken. Agents that already have a valid two-word
|
|
78
77
|
`name:` are left untouched (only the CSV is rewritten to carry it).
|
|
79
78
|
|
|
80
|
-
## Step 5:
|
|
81
|
-
|
|
82
|
-
If `crews/{code}/state.json` exists, update each agent entry's `name` field to the repaired
|
|
83
|
-
`displayName`. Do not change any other field. If the file does not exist, skip — the
|
|
84
|
-
Pipeline Runner recreates it from the CSV on the next run.
|
|
85
|
-
|
|
86
|
-
## Step 6: Report
|
|
79
|
+
## Step 5: Report
|
|
87
80
|
|
|
88
81
|
Present a summary table of what changed:
|
|
89
82
|
|
|
@@ -96,11 +89,13 @@ Crew "{name}" repaired.
|
|
|
96
89
|
| copywriter | Guilherme | ✍️ Guilherme Gancho | generated |
|
|
97
90
|
|
|
98
91
|
crew-party.csv: rewritten with displayName column
|
|
99
|
-
state.json: {updated | not present}
|
|
100
92
|
|
|
101
93
|
Run it: /opencrew run {code}
|
|
102
94
|
```
|
|
103
95
|
|
|
96
|
+
The Escritório (the optional live view) takes the names from the CSV when the next run starts:
|
|
97
|
+
there is nothing else to refresh.
|
|
98
|
+
|
|
104
99
|
If nothing was broken (CSV already had a valid `displayName` for every agent), say so
|
|
105
100
|
plainly instead of inventing changes: "This crew's manifest is already correct — no repair
|
|
106
101
|
needed."
|