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.
Files changed (85) hide show
  1. package/README.md +12 -1
  2. package/THIRD-PARTY-NOTICES.md +6 -0
  3. package/package.json +5 -2
  4. package/skills-registry.yaml +18 -6
  5. package/src/bmm-skills/1-analysis/wizz-agent-analyst/customize.toml +1 -1
  6. package/src/bmm-skills/1-analysis/wizz-set-feature/SKILL.md +34 -12
  7. package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/customize.toml +1 -1
  8. package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/customize.toml +1 -1
  9. package/src/bmm-skills/3-solutioning/wizz-agent-architect/customize.toml +1 -1
  10. package/src/bmm-skills/4-implementation/wizz-agent-dev/customize.toml +1 -1
  11. package/src/bmm-skills/module.yaml +10 -0
  12. package/src/core-skills/_shared/handoff-protocol.md +10 -0
  13. package/src/modules/wizz/_shared/encerramento.md +4 -0
  14. package/src/modules/wizz/_shared/organizacao.md +58 -0
  15. package/src/modules/wizz/_shared/video-pipeline.md +1 -0
  16. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +9 -1
  17. package/src/modules/wizz/agents/wizz-maestro/customize.toml +8 -2
  18. package/src/skills-lib/wizz-inicio-de-projeto/SKILL.md +11 -0
  19. package/src/skills-lib/wizz-router/SKILL.md +3 -1
  20. package/src/skills-lib/wizz-router/references/routing-table-flat.md +1 -0
  21. package/src/skills-lib/wizz-video-styles/SKILL.md +66 -0
  22. package/src/skills-lib/wizz-video-styles/assets/audio/CREDITS.md +54 -0
  23. package/src/skills-lib/wizz-video-styles/assets/audio/LIBRARIES.md +31 -0
  24. package/src/skills-lib/wizz-video-styles/assets/audio/kit.json +182 -0
  25. package/src/skills-lib/wizz-video-styles/assets/audio/music/acoustic-lifestyle.mp3 +0 -0
  26. package/src/skills-lib/wizz-video-styles/assets/audio/music/cinematic-tense.mp3 +0 -0
  27. package/src/skills-lib/wizz-video-styles/assets/audio/music/classical-light.mp3 +0 -0
  28. package/src/skills-lib/wizz-video-styles/assets/audio/music/corporate-light.mp3 +0 -0
  29. package/src/skills-lib/wizz-video-styles/assets/audio/music/lofi-chill.mp3 +0 -0
  30. package/src/skills-lib/wizz-video-styles/assets/audio/music/meme-beat.mp3 +0 -0
  31. package/src/skills-lib/wizz-video-styles/assets/audio/music/piano-editorial.mp3 +0 -0
  32. package/src/skills-lib/wizz-video-styles/assets/audio/music/tech-pulse.mp3 +0 -0
  33. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/boom-impact.mp3 +0 -0
  34. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/click-mouse.mp3 +0 -0
  35. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/ding-notify.mp3 +0 -0
  36. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/glitch-short.mp3 +0 -0
  37. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/ka-ching.mp3 +0 -0
  38. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/pop-bubble.mp3 +0 -0
  39. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/record-scratch.mp3 +0 -0
  40. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/riser-short.mp3 +0 -0
  41. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/swoosh-text.mp3 +0 -0
  42. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/typing-short.mp3 +0 -0
  43. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/whoosh-fast.mp3 +0 -0
  44. package/src/skills-lib/wizz-video-styles/assets/audio/sfx/whoosh-soft.mp3 +0 -0
  45. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/EditorialReel.tsx +111 -0
  46. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/README.md +77 -0
  47. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/captions.tsx +56 -0
  48. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/example-words.json +285 -0
  49. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/primitives.tsx +241 -0
  50. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/scenes.tsx +113 -0
  51. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/theme.ts +68 -0
  52. package/src/skills-lib/wizz-video-styles/assets/remotion/editorial/timeline.ts +65 -0
  53. package/src/skills-lib/wizz-video-styles/data/recipes.json +341 -0
  54. package/src/skills-lib/wizz-video-styles/data/references.json +3397 -0
  55. package/src/skills-lib/wizz-video-styles/data/styles.json +726 -0
  56. package/src/skills-lib/wizz-video-styles/references/audio.md +54 -0
  57. package/src/skills-lib/wizz-video-styles/references/measured-patterns.md +38 -0
  58. package/src/skills-lib/wizz-video-styles/references/research-method.md +33 -0
  59. package/src/skills-lib/wizz-video-styles/references/style-picker.md +51 -0
  60. package/src/skills-lib/wizz-video-styles/references/styles/camera-no-setup.md +60 -0
  61. package/src/skills-lib/wizz-video-styles/references/styles/desafio-numero.md +60 -0
  62. package/src/skills-lib/wizz-video-styles/references/styles/esquete.md +57 -0
  63. package/src/skills-lib/wizz-video-styles/references/styles/experimento.md +56 -0
  64. package/src/skills-lib/wizz-video-styles/references/styles/explicador-animado.md +62 -0
  65. package/src/skills-lib/wizz-video-styles/references/styles/macro-asmr.md +61 -0
  66. package/src/skills-lib/wizz-video-styles/references/styles/meme-rapido.md +65 -0
  67. package/src/skills-lib/wizz-video-styles/references/styles/motion-editorial.md +69 -0
  68. package/src/skills-lib/wizz-video-styles/references/styles/podcast-clip.md +61 -0
  69. package/src/skills-lib/wizz-video-styles/references/styles/pov-vlog.md +57 -0
  70. package/src/skills-lib/wizz-video-styles/references/styles/quadro-branco.md +60 -0
  71. package/src/skills-lib/wizz-video-styles/references/styles/talking-head-cards.md +62 -0
  72. package/src/skills-lib/wizz-video-styles/references/styles/talking-head-legenda.md +62 -0
  73. package/src/skills-lib/wizz-video-styles/references/styles/tour.md +59 -0
  74. package/src/skills-lib/wizz-video-styles/scripts/analyze.sh +66 -0
  75. package/src/skills-lib/wizz-video-styles/scripts/build_catalog.py +128 -0
  76. package/tools/hooks/README.md +14 -2
  77. package/tools/hooks/session-rules.js +65 -140
  78. package/tools/hooks/wizz-arrumar.js +418 -0
  79. package/tools/hooks/wizz-artifact-guard.js +160 -0
  80. package/tools/hooks/wizz-feature-lib.js +414 -0
  81. package/tools/hooks/wizz-feature.js +401 -0
  82. package/tools/hooks/wizz-layout-lib.js +152 -0
  83. package/tools/hooks/wizz-router-enforce.js +21 -1
  84. package/tools/installer/core/doctor.js +5 -1
  85. package/tools/installer/core/hooks-settings.js +10 -0
@@ -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; sem feature a linha não é emitida (custo zero). A feature também é o `tema` da memória. |
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 quando não há `_wizz/` nem branch de feature: a linha
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
- // Branches que NUNCA viram feature: são linha principal, não trabalho nomeado.
43
- const TRUNK = new Set(['main', 'master', 'develop', 'dev', 'staging', 'stage', 'prod', 'production', 'trunk', 'default', 'release']);
44
-
45
- // Branch de release/versão não é feature: nomeia um corte do produto, não um trabalho.
46
- const RELEASE_PREFIX = /^(release|rc|v)[/-]/i;
47
-
48
- // Prefixos de convenção que descrevem o TIPO do trabalho, não a feature.
49
- const TYPE_PREFIX = /^(feat|feature|fix|bugfix|hotfix|chore|refactor|docs|test|perf|ci|build|style)[/-]/i;
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
- * Deriva um slug de feature do nome do branch. Branch de tronco e branch sem
104
- * nome útil devolvem '' (nenhuma feature), nunca um slug inventado.
105
- * @param {string} branch
106
- * @returns {string}
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
- * Lê `active_feature` do config do módulo bmm. Parser de 1 chave de propósito:
122
- * o hook não pode depender de uma lib de YAML (roda fora do node_modules do repo).
123
- * @param {string} cwd
124
- * @returns {{slug: string, configPath: string}} slug '' quando ausente/vazio
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 readConfigFeature(cwd) {
127
- const configPath = path.join(cwd, '_wizz', 'bmm', 'config.yaml');
128
- try {
129
- const text = fs.readFileSync(configPath, 'utf8');
130
- const m = /^active_feature:\s*(.*)$/m.exec(text);
131
- if (!m) return { slug: '', configPath };
132
- const value = m[1]
133
- .replace(/#.*$/, '')
134
- .trim()
135
- .replaceAll(/^["']|["']$/g, '');
136
- return { slug: toSlug(value), configPath };
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
- * Acha a raiz do projeto Wizz (a pasta que contém `_wizz/`) subindo do cwd.
144
- * O agente costuma rodar de uma subpasta, então checar só o cwd erraria.
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 a linha de contexto da feature. Devolve '' quando não há feature
165
- * nenhuma. Silêncio custa zero token e é o caso comum fora de projeto Wizz.
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
- const wizzRoot = findWizzRoot(cwd);
171
- const isWizzProject = Boolean(wizzRoot);
172
- const fromConfig = isWizzProject ? readConfigFeature(wizzRoot) : { slug: '', configPath: '' };
173
- const fromBranch = featureFromBranch(readGitBranch(cwd));
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
- const parts = [
181
- `FEATURE ATIVA: ${active}` + (fromBranch ? ' (derivada do branch git).' : ' (do config).'),
182
- 'Use como contexto sem perguntar nada:',
183
- isWizzProject
184
- ? `artefatos de planejamento e implementação vão para as subpastas ${active}/;`
185
- : 'não é projeto Wizz, então não há subpasta de artefato;',
186
- `memória gravada nesta sessão leva tema/feature "${active}".`,
187
- ];
188
-
189
- if (fromBranch && isWizzProject && fromConfig.slug !== fromBranch) {
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
- `O config (_wizz/bmm/config.yaml) ainda diz "${fromConfig.slug || 'vazio'}": grave "${active}" nele na primeira vez que escrever um artefato, e avise em UMA linha.`,
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