wizz-method 2.15.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/THIRD-PARTY-NOTICES.md +6 -0
- package/package.json +5 -2
- package/skills-registry.yaml +18 -6
- package/src/bmm-skills/1-analysis/wizz-agent-analyst/customize.toml +1 -1
- package/src/bmm-skills/1-analysis/wizz-set-feature/SKILL.md +34 -12
- package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/customize.toml +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/customize.toml +1 -1
- package/src/bmm-skills/3-solutioning/wizz-agent-architect/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-agent-dev/customize.toml +1 -1
- package/src/bmm-skills/module.yaml +10 -0
- package/src/core-skills/_shared/handoff-protocol.md +10 -0
- package/src/modules/wizz/_shared/encerramento.md +4 -0
- package/src/modules/wizz/_shared/organizacao.md +58 -0
- package/src/modules/wizz/_shared/video-pipeline.md +1 -0
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +9 -1
- package/src/modules/wizz/agents/wizz-maestro/customize.toml +8 -2
- package/src/skills-lib/wizz-inicio-de-projeto/SKILL.md +11 -0
- package/src/skills-lib/wizz-router/SKILL.md +3 -1
- package/src/skills-lib/wizz-router/references/routing-table-flat.md +1 -0
- package/src/skills-lib/wizz-video-styles/SKILL.md +66 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/CREDITS.md +54 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/LIBRARIES.md +31 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/kit.json +182 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/acoustic-lifestyle.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/cinematic-tense.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/classical-light.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/corporate-light.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/lofi-chill.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/meme-beat.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/piano-editorial.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/music/tech-pulse.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/boom-impact.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/click-mouse.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/ding-notify.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/glitch-short.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/ka-ching.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/pop-bubble.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/record-scratch.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/riser-short.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/swoosh-text.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/typing-short.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/whoosh-fast.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/audio/sfx/whoosh-soft.mp3 +0 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/EditorialReel.tsx +111 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/README.md +77 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/captions.tsx +56 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/example-words.json +285 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/primitives.tsx +241 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/scenes.tsx +113 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/theme.ts +68 -0
- package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/timeline.ts +65 -0
- package/src/skills-lib/wizz-video-styles/data/recipes.json +341 -0
- package/src/skills-lib/wizz-video-styles/data/references.json +3397 -0
- package/src/skills-lib/wizz-video-styles/data/styles.json +726 -0
- package/src/skills-lib/wizz-video-styles/references/audio.md +54 -0
- package/src/skills-lib/wizz-video-styles/references/measured-patterns.md +38 -0
- package/src/skills-lib/wizz-video-styles/references/research-method.md +33 -0
- package/src/skills-lib/wizz-video-styles/references/style-picker.md +51 -0
- package/src/skills-lib/wizz-video-styles/references/styles/camera-no-setup.md +60 -0
- package/src/skills-lib/wizz-video-styles/references/styles/desafio-numero.md +60 -0
- package/src/skills-lib/wizz-video-styles/references/styles/esquete.md +57 -0
- package/src/skills-lib/wizz-video-styles/references/styles/experimento.md +56 -0
- package/src/skills-lib/wizz-video-styles/references/styles/explicador-animado.md +62 -0
- package/src/skills-lib/wizz-video-styles/references/styles/macro-asmr.md +61 -0
- package/src/skills-lib/wizz-video-styles/references/styles/meme-rapido.md +65 -0
- package/src/skills-lib/wizz-video-styles/references/styles/motion-editorial.md +69 -0
- package/src/skills-lib/wizz-video-styles/references/styles/podcast-clip.md +61 -0
- package/src/skills-lib/wizz-video-styles/references/styles/pov-vlog.md +57 -0
- package/src/skills-lib/wizz-video-styles/references/styles/quadro-branco.md +60 -0
- package/src/skills-lib/wizz-video-styles/references/styles/talking-head-cards.md +62 -0
- package/src/skills-lib/wizz-video-styles/references/styles/talking-head-legenda.md +62 -0
- package/src/skills-lib/wizz-video-styles/references/styles/tour.md +59 -0
- package/src/skills-lib/wizz-video-styles/scripts/analyze.sh +66 -0
- package/src/skills-lib/wizz-video-styles/scripts/build_catalog.py +128 -0
- package/tools/hooks/README.md +14 -2
- package/tools/hooks/session-rules.js +65 -140
- package/tools/hooks/wizz-arrumar.js +418 -0
- package/tools/hooks/wizz-artifact-guard.js +160 -0
- package/tools/hooks/wizz-feature-lib.js +414 -0
- package/tools/hooks/wizz-feature.js +401 -0
- package/tools/hooks/wizz-layout-lib.js +152 -0
- package/tools/hooks/wizz-router-enforce.js +21 -1
- package/tools/installer/core/doctor.js +5 -1
- package/tools/installer/core/hooks-settings.js +10 -0
package/tools/hooks/README.md
CHANGED
|
@@ -7,14 +7,26 @@ ela é substituída no próximo sync.
|
|
|
7
7
|
| Hook | Evento | O que faz |
|
|
8
8
|
| ------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
9
|
| `wizz-router-enforce.js` | UserPromptSubmit | Gate `isTrivial()` + injeção curta: em projeto Wizz (`_wizz/`) manda delegar direto ao maestro/agente da área (sem router); fora, manda pro `wizz-router`. |
|
|
10
|
-
| `session-rules.js` | SessionStart | Duas coisas num processo só: injeta as regras de comunicação 1x por sessão (antes era por prompt) e resolve a FEATURE ATIVA sozinho (branch git > `_wizz/bmm/config.yaml` > nada), para ninguém precisar invocar `wizz-set-feature`. Branch de tronco e de release não viram feature
|
|
10
|
+
| `session-rules.js` | SessionStart | Duas coisas num processo só: injeta as regras de comunicação 1x por sessão (antes era por prompt) e resolve a FEATURE ATIVA sozinho (branch git > `_wizz/bmm/config.yaml` > nada), para ninguém precisar invocar `wizz-set-feature`. Branch de tronco e de release não viram feature. Fora de projeto Wizz e sem branch de feature a linha não é emitida (custo zero); dentro de projeto Wizz sem feature sai o lembrete curto "o primeiro pedido nomeado define uma", e sem `layout:` o lembrete de propor um. A feature também é o `tema` da memória. |
|
|
11
11
|
| `security-defensive-context.js` | PreToolUse (Skill) | Metodologia defensiva/escopada ao invocar skills de segurança. Genérico por projeto (v2). |
|
|
12
|
+
| `wizz-artifact-guard.js` | PostToolUse (Write) | Avisa (nunca bloqueia) artefato escrito fora da subpasta da feature ativa, artefato de feature sem feature ativa, frontmatter faltando em `<tipo>-<slug>.md`, e arquivo solto na raiz fora do `layout:`, com o comando que move. Fail-open sem `_wizz/` ou config. |
|
|
12
13
|
| `rtk-rewrite.sh` | PreToolUse (Bash) | Reescreve comandos de shell via `rtk rewrite` (token economy). Fork local do hook gerado pelo instalador upstream do rtk, com 3 patches (auditoria 2026-07-07, C4/RT1; e 2026-09-11, RT-H3): reescrita linha a linha em comando multi-linha (o binário só reescrevia a 1ª linha), timeout interno por linha (`RTK_HOOK_TIMEOUT`, default 3s) que não depende do `timeout`/`gtimeout` do GNU coreutils, e cache do version-guard (`RTK_CACHE_TTL_SECONDS`, default 1h, em `${XDG_CACHE_HOME:-$HOME/.cache}/wizz/rtk-version`) pra não rodar `rtk --version` a cada `Bash` tool call da sessão. Requer `rtk` + `jq` no PATH; fail-open em ambos (e no cache: ilegível/corrompido/expirado recomputa em silêncio). |
|
|
13
14
|
|
|
15
|
+
Arquivos de apoio (copiados junto, NUNCA registrados em settings.json; o doctor cobra a presença):
|
|
16
|
+
|
|
17
|
+
| Arquivo | O que é |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `wizz-feature-lib.js` | Funções puras de feature, git, config, pastas de artefato e frontmatter. Usada por todos os hooks acima. |
|
|
20
|
+
| `wizz-layout-lib.js` | O que pode ficar na raiz e para onde vai o resto (tipos `codigo`, `scripts`, `dados`, `docs`, `midia`, `arquivo`). |
|
|
21
|
+
| `wizz-feature.js` | CLI do ciclo de vida da feature: `resolver`, `definir`, `artefato`, `decidir`, `status`, `verificar`, `encerrar`, `listar`. É o passo verificável que router/maestro rodam antes de despachar. |
|
|
22
|
+
| `wizz-arrumar.js` | CLI de arrumação: `layout [--gravar]`, `planejar`, `aplicar` (manifesto .tsv + referências + testes antes/depois + `desfazer.sh`), `mover`, `desfazer`. |
|
|
23
|
+
|
|
24
|
+
Regra completa em `src/modules/wizz/_shared/organizacao.md` (2026-10-02, caso Spider). `session-rules.js` passou a lembrar "nenhuma feature ativa" e "projeto sem layout" dentro de projeto Wizz, e `wizz-router-enforce.js` acrescenta 1 linha de feature por prompt em projeto Wizz.
|
|
25
|
+
|
|
14
26
|
Removidos em 2026-07 (arquivados em `~/.claude/hooks-archive/`):
|
|
15
27
|
`no-narration-enforce.js` (absorvido pelo session-rules) e `vault-reminder.js`.
|
|
16
28
|
|
|
17
|
-
Testes: `npm run test:hooks` (isTrivial + contexto por modo), `npm run test:feature-context` (resolução da feature ativa: tronco não vira feature, branch ganha do config, silêncio quando não há feature) e `node test/test-rtk-hook.js` (rewrite básico + multi-linha do `rtk-rewrite.sh`, smoke test que exercita o binário `rtk` real quando disponível, e o cache do version-guard: criado na 1ª chamada e reusado na 2ª, TTL expirado força recompute, path do binário mudou invalida, cache corrompido não quebra e se auto-cura).
|
|
29
|
+
Testes: `npm run test:organizacao` (CLIs de feature e arrumação, guard, lembretes nos cenários sem git / main / branch), `npm run eval:feature` (hooks reais + CLI + estado final; `--llm` mede a obediência do modelo), `npm run test:hooks` (isTrivial + contexto por modo), `npm run test:feature-context` (resolução da feature ativa: tronco não vira feature, branch ganha do config, silêncio quando não há feature) e `node test/test-rtk-hook.js` (rewrite básico + multi-linha do `rtk-rewrite.sh`, smoke test que exercita o binário `rtk` real quando disponível, e o cache do version-guard: criado na 1ª chamada e reusado na 2ª, TTL expirado força recompute, path do binário mudou invalida, cache corrompido não quebra e se auto-cura).
|
|
18
30
|
Evals de roteamento: `node evals/routing/run-routing-eval.mjs [--llm]`.
|
|
19
31
|
|
|
20
32
|
Drift repo ↔ global: `npm run sync:check` compara hash de cada hook (e skill) entre o repo e `~/.claude`, sem escrever nada — é lembrete (fail-open), não gate; roda no fim do `npm test`. Achou drift? `npm run sync:global` atualiza `~/.claude`.
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
// 2. Feature ativa: resolve o `active_feature` SOZINHO, sem o usuário
|
|
12
12
|
// precisar invocar `wizz-set-feature` e responder duas perguntas. Ordem:
|
|
13
13
|
// branch git (mais fresco que o config) > `_wizz/bmm/config.yaml` > nada.
|
|
14
|
-
// Custo zero
|
|
15
|
-
// simplesmente não é emitida.
|
|
14
|
+
// Custo zero fora de projeto Wizz sem branch de feature: a linha
|
|
15
|
+
// simplesmente não é emitida. DENTRO de projeto Wizz sem feature sai um
|
|
16
|
+
// lembrete curto ("o primeiro pedido nomeado define uma", 2026-10-02):
|
|
17
|
+
// sem ele, projeto sem git ou na main ficava a vida toda sem feature
|
|
18
|
+
// (caso Spider). Mesmo lembrete para layout de pastas ausente.
|
|
16
19
|
//
|
|
17
20
|
// 3. Teto da auto-memória: o teto de 40 memórias e 8 KB de índice está
|
|
18
21
|
// escrito no CLAUDE.md global desde 2026-08-28, mas nada disparava a
|
|
@@ -39,163 +42,85 @@ const RULES =
|
|
|
39
42
|
'concise communication by default, expand only on request; ' +
|
|
40
43
|
'reply to the user in the language chosen at install (communication_language).';
|
|
41
44
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Normaliza um texto livre para o mesmo slug kebab-case que a skill
|
|
53
|
-
* `wizz-set-feature` grava, para branch e config nunca divergirem por formato.
|
|
54
|
-
* @param {string} raw
|
|
55
|
-
* @returns {string} slug kebab-case, ou '' se não sobrar nada utilizável
|
|
56
|
-
*/
|
|
57
|
-
function toSlug(raw) {
|
|
58
|
-
if (typeof raw !== 'string') return '';
|
|
59
|
-
return raw
|
|
60
|
-
.normalize('NFD')
|
|
61
|
-
.replaceAll(/[\u0300-\u036F]/g, '')
|
|
62
|
-
.toLowerCase()
|
|
63
|
-
.replaceAll(/[^a-z0-9]+/g, '-')
|
|
64
|
-
.replaceAll(/^-+|-+$/g, '')
|
|
65
|
-
.slice(0, 60);
|
|
45
|
+
// Feature, git e config moram em wizz-feature-lib.js (mesma pasta: o installer
|
|
46
|
+
// e o sync:global copiam tools/hooks/ inteiro). Se a lib faltar numa cópia
|
|
47
|
+
// manual parcial, a regra de comunicação continua saindo e a feature cala.
|
|
48
|
+
let lib = null;
|
|
49
|
+
try {
|
|
50
|
+
lib = require('./wizz-feature-lib.js');
|
|
51
|
+
} catch {
|
|
52
|
+
lib = null;
|
|
66
53
|
}
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
* Lê o branch atual sem subprocesso: `.git/HEAD` já traz o ref, e um read de
|
|
70
|
-
* arquivo é mais barato e mais seguro que um `git` no PATH (que pode nem existir).
|
|
71
|
-
* Sobe até 6 níveis para achar o `.git` de um subdiretório do repo.
|
|
72
|
-
* @param {string} cwd
|
|
73
|
-
* @returns {string} nome do branch, ou '' (detached HEAD, sem repo, erro)
|
|
74
|
-
*/
|
|
75
|
-
function readGitBranch(cwd) {
|
|
76
|
-
let dir = cwd;
|
|
77
|
-
for (let i = 0; i < 6; i++) {
|
|
78
|
-
const gitPath = path.join(dir, '.git');
|
|
79
|
-
try {
|
|
80
|
-
const stat = fs.statSync(gitPath);
|
|
81
|
-
let headFile = path.join(gitPath, 'HEAD');
|
|
82
|
-
if (stat.isFile()) {
|
|
83
|
-
// worktree/submódulo: `.git` é um arquivo `gitdir: <caminho>`
|
|
84
|
-
const m = /^gitdir:\s*(.+)$/m.exec(fs.readFileSync(gitPath, 'utf8'));
|
|
85
|
-
if (!m) return '';
|
|
86
|
-
const resolved = path.resolve(dir, m[1].trim());
|
|
87
|
-
headFile = path.join(resolved, 'HEAD');
|
|
88
|
-
}
|
|
89
|
-
const head = fs.readFileSync(headFile, 'utf8').trim();
|
|
90
|
-
const ref = /^ref:\s*refs\/heads\/(.+)$/.exec(head);
|
|
91
|
-
return ref ? ref[1] : ''; // detached HEAD => sem branch => sem feature
|
|
92
|
-
} catch {
|
|
93
|
-
// segue subindo
|
|
94
|
-
}
|
|
95
|
-
const parent = path.dirname(dir);
|
|
96
|
-
if (parent === dir) break;
|
|
97
|
-
dir = parent;
|
|
98
|
-
}
|
|
99
|
-
return '';
|
|
100
|
-
}
|
|
55
|
+
const HOOK_CMD = 'node _wizz/hooks/wizz-feature.js';
|
|
101
56
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*/
|
|
108
|
-
function featureFromBranch(branch) {
|
|
109
|
-
if (!branch) return '';
|
|
110
|
-
if (TRUNK.has(branch.toLowerCase())) return '';
|
|
111
|
-
if (RELEASE_PREFIX.test(branch)) return '';
|
|
112
|
-
const stripped = branch.replace(TYPE_PREFIX, '');
|
|
113
|
-
const slug = toSlug(stripped);
|
|
114
|
-
if (!slug || TRUNK.has(slug)) return '';
|
|
115
|
-
// Branch que é só um número de issue não descreve feature nenhuma.
|
|
116
|
-
if (/^\d+$/.test(slug)) return '';
|
|
117
|
-
return slug;
|
|
118
|
-
}
|
|
57
|
+
const toSlug = (raw) => (lib ? lib.toSlug(raw) : '');
|
|
58
|
+
const readGitBranch = (cwd) => (lib ? lib.readGitBranch(cwd) : '');
|
|
59
|
+
const featureFromBranch = (branch) => (lib ? lib.featureFromBranch(branch) : '');
|
|
60
|
+
const readConfigFeature = (root) => (lib ? lib.readConfigFeature(root) : { slug: '', configPath: '' });
|
|
61
|
+
const findWizzRoot = (cwd) => (lib ? lib.findWizzRoot(cwd) : '');
|
|
119
62
|
|
|
120
63
|
/**
|
|
121
|
-
*
|
|
122
|
-
* o
|
|
123
|
-
*
|
|
124
|
-
* @
|
|
64
|
+
* Lembretes de projeto Wizz que valem mesmo sem feature: nenhuma feature
|
|
65
|
+
* ativa (o primeiro pedido nomeado define uma), layout de pastas ausente e
|
|
66
|
+
* proposta de branch quando `feature_branches: auto`.
|
|
67
|
+
* @param {ReturnType<typeof lib.resolveFeature>} state
|
|
68
|
+
* @returns {string[]}
|
|
125
69
|
*/
|
|
126
|
-
function
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
.
|
|
136
|
-
|
|
137
|
-
} catch {
|
|
138
|
-
return { slug: '', configPath };
|
|
70
|
+
function wizzReminders(state) {
|
|
71
|
+
const out = [];
|
|
72
|
+
if (!state.slug) {
|
|
73
|
+
out.push(
|
|
74
|
+
`NENHUMA FEATURE ATIVA: o primeiro pedido nomeado (feature, lote, tela, bug com escopo) define uma. ` +
|
|
75
|
+
`Antes de despachar, derive o slug do pedido e grave: ${HOOK_CMD} definir <slug>. Sem perguntar; uma linha de confirmação.`,
|
|
76
|
+
);
|
|
77
|
+
} else if (state.featureBranches === 'auto' && state.git.isRepo && state.onTrunk) {
|
|
78
|
+
out.push(
|
|
79
|
+
`feature_branches: auto e você está em ${state.git.branch || 'HEAD solto'}: proponha em UMA linha \`git switch -c feat/${state.slug}\`.`,
|
|
80
|
+
);
|
|
139
81
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
* @param {string} cwd
|
|
146
|
-
* @returns {string} caminho da raiz, ou '' se não for projeto Wizz
|
|
147
|
-
*/
|
|
148
|
-
function findWizzRoot(cwd) {
|
|
149
|
-
let dir = cwd;
|
|
150
|
-
for (let i = 0; i < 6; i++) {
|
|
151
|
-
try {
|
|
152
|
-
if (fs.existsSync(path.join(dir, '_wizz'))) return dir;
|
|
153
|
-
} catch {
|
|
154
|
-
// ignora e segue subindo
|
|
155
|
-
}
|
|
156
|
-
const parent = path.dirname(dir);
|
|
157
|
-
if (parent === dir) break;
|
|
158
|
-
dir = parent;
|
|
82
|
+
if (!state.hasLayout) {
|
|
83
|
+
out.push(
|
|
84
|
+
'PROJETO SEM LAYOUT DE PASTAS: no primeiro pedido, proponha a estrutura por tipo em UMA linha ' +
|
|
85
|
+
'(node _wizz/hooks/wizz-arrumar.js layout) e grave com `layout --gravar`. Arquivo novo nunca nasce solto na raiz.',
|
|
86
|
+
);
|
|
159
87
|
}
|
|
160
|
-
return
|
|
88
|
+
return out;
|
|
161
89
|
}
|
|
162
90
|
|
|
163
91
|
/**
|
|
164
|
-
* Monta
|
|
165
|
-
*
|
|
92
|
+
* Monta o contexto de feature. Fora de projeto Wizz e sem branch de feature
|
|
93
|
+
* devolve '' (silêncio custa zero token). Em projeto Wizz sem feature, sai o
|
|
94
|
+
* lembrete curto: é o que faz a organização acontecer sem o dono pedir.
|
|
166
95
|
* @param {string} cwd
|
|
167
96
|
* @returns {string}
|
|
168
97
|
*/
|
|
169
98
|
function buildFeatureContext(cwd) {
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
// O branch ganha do config: é o que descreve o trabalho de AGORA. O config
|
|
176
|
-
// pode ter ficado numa feature antiga que ninguém lembrou de trocar.
|
|
177
|
-
const active = fromBranch || fromConfig.slug;
|
|
178
|
-
if (!active) return '';
|
|
99
|
+
if (!lib) return '';
|
|
100
|
+
const state = lib.resolveFeature(cwd);
|
|
101
|
+
const fromBranch = state.isWizz ? state.fromBranch : featureFromBranch(readGitBranch(cwd));
|
|
102
|
+
const active = state.isWizz ? state.slug : fromBranch;
|
|
103
|
+
const parts = [];
|
|
179
104
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
105
|
+
if (active) {
|
|
106
|
+
parts.push(
|
|
107
|
+
`FEATURE ATIVA: ${active}` + (fromBranch ? ' (derivada do branch git).' : ' (do config).'),
|
|
108
|
+
'Use como contexto sem perguntar nada:',
|
|
109
|
+
state.isWizz
|
|
110
|
+
? `artefatos de planejamento e implementação vão para as subpastas ${active}/ com nome <tipo>-<slug>.md (${HOOK_CMD} artefato <tipo>);`
|
|
111
|
+
: 'não é projeto Wizz, então não há subpasta de artefato;',
|
|
112
|
+
`memória gravada nesta sessão leva tema/feature "${active}".`,
|
|
113
|
+
);
|
|
114
|
+
if (fromBranch && state.isWizz && state.fromConfig !== fromBranch) {
|
|
115
|
+
parts.push(
|
|
116
|
+
`O config (_wizz/bmm/config.yaml) ainda diz "${state.fromConfig || 'vazio'}": grave "${active}" nele (${HOOK_CMD} definir ${active}) e avise em UMA linha.`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
190
119
|
parts.push(
|
|
191
|
-
|
|
120
|
+
'NÃO peça confirmação de feature. Pedido de OUTRO assunto troca a feature (definir <novo>); continuação mantém. Pergunte só se houver ambiguidade real entre duas features abertas.',
|
|
192
121
|
);
|
|
193
122
|
}
|
|
194
|
-
|
|
195
|
-
parts.push(
|
|
196
|
-
'NÃO peça confirmação de feature. Só invoque a skill wizz-set-feature se o usuário pedir explicitamente para trocar, ou se houver ambiguidade real entre duas features abertas.',
|
|
197
|
-
);
|
|
198
|
-
|
|
123
|
+
if (state.isWizz) parts.push(...wizzReminders(state));
|
|
199
124
|
return parts.join(' ');
|
|
200
125
|
}
|
|
201
126
|
|