@aksp/opencrew 1.10.0 → 1.11.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.
@@ -107,10 +107,10 @@ Present the three tiers with concrete trade-offs:
107
107
  | Aspect | ⚡ Express | 🎯 Standard | 🔬 Full |
108
108
  |--------|-----------|-------------|---------|
109
109
  | Agent count | 2-3 | 3-5 | 5-7 |
110
- | Reviewer | Writer self-reviews | 1 dedicated reviewer | Reviewer + cross-review |
110
+ | Reviewer | The writer does the review step (no reviewer agent) | 1 dedicated reviewer | Reviewer + cross-review |
111
111
  | Sherlock | Never | Only if user provided URLs | Always (social + web + trends) |
112
112
  | Checkpoints | Final approval only | Research focus + content approval + final | All checkpoints + angle selection |
113
- | model_tier per step | All `fast` | Mix (research=fast, create=powerful) | All `powerful` |
113
+ | model_tier (subagent steps only) | `fast` | Mix (research=fast, create=powerful) | `powerful` |
114
114
  | Cross-review | None | None | Reviewer + second reviewer cross-check |
115
115
  | On-reject loops | 1 max | 2 max | 3 max |
116
116
 
@@ -219,7 +219,7 @@ Para {crew purpose}, sugiro este time:
219
219
  - Simple crews (1 format, 1 platform): 2-3 roles
220
220
  - Medium crews (content + review): 3-4 roles
221
221
  - Complex crews (multi-platform, multi-format): 4-6 roles
222
- - **Every crew needs a reviewer** — mandatory quality gate
222
+ - **Every crew needs a review step** — mandatory quality gate (Express: done by the writer; Standard and Full: by a reviewer role)
223
223
  - **Allow editing** — after presenting roles, ask:
224
224
  > "Quer adicionar, remover ou modificar algum papel? Ou o time está bom?"
225
225
 
@@ -229,7 +229,7 @@ Never suggest fewer than 2 roles. The minimum viable crew has:
229
229
  - One creator/executor (the person who produces the output)
230
230
  - One reviewer (the person who checks quality before delivery)
231
231
 
232
- For very simple tasks, these two roles can be the same person with a self-review step — but the user must explicitly approve this simplification.
232
+ In the Express tier these two roles are the same agent: the writer also does the review step. The step still exists (with `on_reject`), so the automatic checker runs before it.
233
233
 
234
234
  ---
235
235
 
@@ -365,7 +365,7 @@ execution: inline
365
365
  skills: []
366
366
  ---
367
367
  ```
368
- The Build phase copies the base agent from `_opencrew/agents/copywriter.agent.md` and the local file only needs to specify what's DIFFERENT — a different tone, specific output examples for this crew, or additional anti-patterns. The runner merges: base first, local overrides on top.
368
+ The Build phase copies the base agent from `_opencrew/agents/copywriter.agent.md` and the local file only needs to specify what's DIFFERENT — a different tone, specific output examples for this crew, or additional anti-patterns. The Build phase does the merge (base first, local overrides on top) and writes a complete file; the Pipeline Runner never merges.
369
369
 
370
370
  ### Design Philosophy
371
371
 
@@ -382,7 +382,7 @@ Design the crew with appropriate agents:
382
382
  - Follow the deep `.agent.md` format with full sections: Persona (Role, Identity, Communication Style), Principles, Operational Framework, Voice Guidance, Output Examples, Anti-Patterns, Quality Criteria, Integration
383
383
  - Design each agent from scratch, informed by the relevant best-practices files read in Phase A
384
384
  - Each agent has exactly one clear responsibility
385
- - Every crew needs a reviewer agent for quality control
385
+ - Every crew needs a review step for quality control (a reviewer agent in Standard and Full)
386
386
  - YAGNI — never create agents that aren't strictly necessary
387
387
 
388
388
  ### Agent Naming Convention (MANDATORY — never skip)
@@ -428,8 +428,7 @@ The name should make someone smile — it's a pun tying a common name to the pro
428
428
 
429
429
  ### Agent Composition Rules
430
430
 
431
- - One clear responsibility per agent; reviewer agent mandatory; YAGNI strictly applied
432
- - Research/data steps → `execution: subagent`; creative/writing steps → `execution: inline`
431
+ - One clear responsibility per agent; review step mandatory (reviewer agent in Standard and Full); YAGNI strictly applied
433
432
  - Content crews must include `pipeline/data/tone-of-voice.md` and instruct the writer to ask tone before producing
434
433
  - Every agent uses `.agent.md` format with all sections: Persona, Principles, Operational Framework, Voice Guidance, Output Examples, Anti-Patterns, Quality Criteria, Integration
435
434
 
@@ -441,9 +440,9 @@ The name should make someone smile — it's a pun tying a common name to the pro
441
440
 
442
441
  - **Research/data-gathering steps** → `execution: subagent` (runs in background via Task tool)
443
442
  - **Creative/writing steps** → `execution: inline` (runs in the main conversation)
444
- - Always include reviewer agent before final output
445
443
  - Add checkpoints at every user decision point
446
- - Include `on_reject` loops from reviewer back to writer
444
+ - The files the Build phase will write follow `_opencrew/core/formato-da-crew.md` (fields of `crew.yaml`, of `pipeline.yaml` and of each step): design nothing that format cannot hold
445
+ - Always include a review step before final output (see the tier table for who does it), with `on_reject`: the number of the first writing step
447
446
  - A step whose result is a document to print, sign or file (minutes, official letter, statement, contract, formal report) gets `format: documento-oficial`, in any kind of crew: the writer follows that guide, and the text becomes a Word document in the delivery of the run (or with `/opencrew documento <arquivo>`)
448
447
 
449
448
  ### Research Focus Checkpoint (MANDATORY for crews with a researcher)
@@ -603,6 +602,7 @@ crew:
603
602
  code: "{code}"
604
603
  name: "{Crew Name}"
605
604
  description: "{one-line description}"
605
+ icon: "{emoji}"
606
606
  tier: "express" | "standard" | "full"
607
607
 
608
608
  agents:
@@ -656,7 +656,7 @@ pipeline:
656
656
  - step: 2
657
657
  name: "checkpoint-name"
658
658
  type: "checkpoint"
659
- output_file: "{path}" # optional, for research focus checkpoints
659
+ output_file: "{path}" # optional, when the next step needs the user's answer
660
660
 
661
661
  investigation: # only if investigation ran
662
662
  enriched: true
@@ -80,12 +80,15 @@ After the user answers Step 1, classify their intent into one of the following d
80
80
 
81
81
  | Domain | Signals in the user's answer |
82
82
  |---|---|
83
+ | `document` | minutes (ata), official letter (ofício), contract, proposal, bylaws (estatuto), legal opinion (parecer), formal report, statement: a text to print, sign or file |
83
84
  | `content` | posts, articles, videos, captions, social media, campaigns, copy, newsletter, creative, reels, threads |
84
85
  | `research` | data, analysis, reports, competitor, market, insights, scraping, summarizing, monitoring |
85
86
  | `automation` | workflows, triggers, scheduling, notifications, integrations, pipelines, bots, recurring tasks |
86
87
  | `analysis` | metrics, dashboards, KPIs, performance, trends, tracking, visualization |
87
88
  | `mixed` | answer spans two or more domains above |
88
89
 
90
+ When the request is a text to print, sign or file, the domain is `document` even if the words also fit `content` or `research`.
91
+
89
92
  Save the detected domain as `domain`.
90
93
 
91
94
  ---
@@ -99,6 +102,13 @@ Based on the detected domain, ask the most relevant contextual question first. W
99
102
  2. What platforms or formats? (wait for answer — do not list formats yet, that comes in Step 6)
100
103
  3. What tone or personality should the content have? (multiple choice: professional / casual / educational / entertaining / other)
101
104
 
105
+ **If domain = `document`:**
106
+ 1. Which documents should the crew produce? (open-ended: ata, ofício, contrato, proposta…)
107
+ 2. Who signs each document, and who receives it? (open-ended)
108
+ 3. Does the organization have letterhead (logo, header lines, footer) that these documents must carry? (yes / no / not sure — the letterhead itself is set up later, the first time a Word document is generated; here you only record the answer)
109
+
110
+ The project sources question below matters most here: ask which files of the project rule the text (bylaws, previous minutes, price table, contract template).
111
+
102
112
  **If domain = `research`:**
103
113
  1. What sources will the crew draw from? (multiple choice: public websites / internal documents / social media / databases / other)
104
114
  2. What is the output format? (multiple choice: summary report / structured data / slide deck / raw export / other)
@@ -143,7 +153,9 @@ Do NOT ask the user about tools. Instead:
143
153
 
144
154
  ### Step 5 — Investigation (optional)
145
155
 
146
- Offer the investigation option to the user. The investigation is powerful but consumes tokens and time — make the trade-off clear:
156
+ **If domain = `document`, skip this step entirely** (set `investigation.enabled: false`): a document crew follows the project's own sources, not reference profiles.
157
+
158
+ For every other domain, offer the investigation option to the user. The investigation is powerful but consumes tokens and time — make the trade-off clear:
147
159
 
148
160
  > "Want to investigate reference profiles before building the crew? The investigation analyzes real content from profiles you admire to extract patterns, hooks, and styles. It uses extra tokens and takes a few minutes, but can significantly improve the final quality."
149
161
  >
@@ -194,7 +206,8 @@ Set `investigation.enabled: false` and continue.
194
206
 
195
207
  ### Step 6 — Target Formats (content crews ONLY)
196
208
 
197
- Skip this step entirely for non-content domains.
209
+ If domain = `document`, do not ask: save `target_formats: ["documento-oficial"]`. When the crew also produces a short piece for a channel (a WhatsApp notice, an e-mail to the members), add that format id to the list — pick it from the filenames of `_opencrew/core/best-practices/` — and go on.
210
+ Skip this step entirely for the other non-content domains.
198
211
 
199
212
  If domain = `content`, ask:
200
213
  > "Para quais formatos/plataformas esse crew vai produzir conteúdo?"
@@ -254,7 +267,7 @@ project_sources: # relative to the project root; becomes `fo
254
267
  - path: "{e.g. Memoria/01_Decisoes.md}"
255
268
  purpose: "{what the crew uses it for}"
256
269
  purpose: "{user's description from Step 1}"
257
- domain: "{content | research | automation | analysis | mixed}"
270
+ domain: "{document | content | research | automation | analysis | mixed}"
258
271
  # When a template was used (Step 0), these fields are populated from discovery.template.yaml:
259
272
  domains: [] # list of domain tags from template (e.g., [content-marketing, seo])
260
273
  tier: "standard" # from template or preferences Default Tier
@@ -272,6 +285,11 @@ company:
272
285
  language: "{user's preferred language}"
273
286
 
274
287
  context:
288
+ # For document crews:
289
+ documents: "{answer from Step 3}"
290
+ signer: "{who signs}"
291
+ recipients: "{who receives}"
292
+ letterhead: "{yes | no | not sure}"
275
293
  # For content crews:
276
294
  audience: "{answer from Step 3}"
277
295
  platforms: "{answer from Step 3}"
@@ -299,7 +317,7 @@ investigation:
299
317
  platform: "{instagram | youtube | twitter | linkedin}"
300
318
  investigation_mode: "{single_post | profile_1 | profile_3}"
301
319
 
302
- target_formats: # content crews only; empty list for others
320
+ target_formats: # content and document crews; empty list for others
303
321
  - "{format-id}"
304
322
  ```
305
323
 
@@ -317,7 +335,7 @@ The `crew_code` must be a short, URL-safe slug derived from the crew's purpose (
317
335
  - **NEVER ask more than 8 questions total** — respect the user's time
318
336
  - **NEVER ask about tools** — auto-detect from installed skills and include in the summary
319
337
  - **NEVER ask about performance mode** — crews are always built lean and agile
320
- - **Investigation is always offered** — Step 5 presents the option for all domains, not just content
338
+ - **Investigation is offered to every domain except `document`** — Step 5 presents the option; a document crew skips it
321
339
  - **Target formats are content-only** — Step 6 is skipped entirely for non-content crews
322
340
  - **One question at a time** — never combine two questions in one message, even if they feel related
323
341
  - **Domain detection is silent** — do not announce "I detected your domain is X"; just use the classification internally
@@ -1,114 +1,105 @@
1
- # Repair — Fix Crew Agent Names / Manifest
1
+ # Repair — bring an existing crew up to date (conserto)
2
2
 
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 Escritório and the
5
- Pipeline Runner show "Pesquisador" instead of "Pedro Pesquisa").
3
+ You are the opencrew Repair agent. A crew built by an older version misses what later versions
4
+ added: the format of each text, the project sources, bans the checker can enforce, the persona
5
+ names. Your job is to show the user what is missing in **one crew that already exists** and fix
6
+ one point at a time, each with the user's yes.
6
7
 
7
- This is a known defect in crews built by older versions: the `crew-party.csv` manifest was
8
- generated without a `displayName` column (or with the role/title in it instead of the
9
- persona name), while the correct two-word names already live in each agent's `.agent.md`
10
- `name:` frontmatter. This repair is **deterministic** — you pull names from the `.agent.md`
11
- files and rewrite the manifest. You do NOT re-generate agent personas, re-run research, or
12
- re-run the Build phase.
8
+ **You never write inside `crews/` yourself.** Every change is one command of the script below,
9
+ which keeps a `.bak` copy of the file before changing it. You do not re-run Discovery, Design or
10
+ Build, and you do not rewrite the crew into a new layout: older shapes of `crew.yaml` and
11
+ `pipeline.yaml` still work (see `_opencrew/core/formato-da-crew.md`).
13
12
 
14
- ## Scope
15
-
16
- You may ONLY touch these files under `crews/{code}/`:
17
- - `crews/{code}/crew-party.csv`
18
- - `crews/{code}/agents/*.agent.md` (only in the fallback case — see Step 4)
19
-
20
- Never modify `_opencrew/`, `templates/`, or any other crew. Use the Write tool for all file
21
- writes (never Bash `mkdir`).
22
-
23
- ---
13
+ Speak to the user in their language (`_opencrew/_memory/preferences.md`). The script answers in
14
+ fixed PT-BR: when the user's language is another one, translate what you show.
24
15
 
25
16
  ## Step 1: Identify the crew
26
17
 
27
- - If the user passed a crew code (`/opencrew repair <name>`), use it.
28
- - Otherwise, list the directories under `crews/` and ask which crew to repair.
29
- - If exactly 1 crew exists, offer it plus a "Cancel" option.
30
- - If 0 crews exist, tell the user there is nothing to repair and stop.
31
-
32
- Verify `crews/{code}/crew.yaml` and `crews/{code}/agents/` exist. If not, report and stop.
18
+ - If the user passed a crew (`/opencrew repair <name>`), use it.
19
+ - Otherwise list the crews and ask which one. **A folder under `crews/` without a `crew.yaml` is
20
+ not a crew** (the template folders installed with the product): leave it out of the list.
21
+ - Exactly 1 crew: offer it plus a "Cancelar" option.
22
+ - 0 crews: say there is nothing to repair and stop.
33
23
 
34
- ## Step 2: Read the source of truth (the agent files)
24
+ ## Step 2: Diagnose
35
25
 
36
- For EACH `crews/{code}/agents/*.agent.md`, read the YAML frontmatter and extract:
37
- - `id` (or derive it from the filename: `researcher.agent.md` → `researcher`)
38
- - `name` — the persona name (expected: two words, "FirstName LastName")
39
- - `title` — the role/function label
40
- - `icon` — the emoji
41
- - `execution` — `inline` or `subagent`
42
-
43
- Also read the current `crews/{code}/crew-party.csv` (if present) to preserve any
44
- `execution`/`title` values that are correct there but missing from a `.agent.md`.
45
-
46
- ## Step 3: Rebuild `crew-party.csv`
47
-
48
- Write `crews/{code}/crew-party.csv` with the canonical header and one row per agent:
26
+ From the project root, with the crew folder between double quotes:
49
27
 
50
28
  ```
51
- id,displayName,title,icon,path,execution
29
+ node _opencrew/core/scripts/conserto.mjs --crew "crews/{code}"
52
30
  ```
53
31
 
54
- - `displayName` = the agent's `name:` from its `.agent.md` (the two-word persona name).
55
- - `title` = the agent's `title:`.
56
- - `icon` = the agent's `icon:`.
57
- - `path` = `./agents/{id}.agent.md`.
58
- - `execution` = the agent's `execution:` (default `inline` if absent).
59
- - Quote any field containing a space or comma with double quotes.
60
- - Preserve the original agent order (match the previous CSV order if it existed).
32
+ It only reads. Its last line is the status:
61
33
 
62
- ## Step 4: Fallback — agent whose `.agent.md` name is itself broken
34
+ - `CONSERTO:OK` — say "A crew {nome} está em dia: não há o que consertar." and stop.
35
+ - `CONSERTO:PENDENTE` — one block per finding, each starting with `[código]`. Go to Step 3.
36
+ - `CONSERTO:ERRO`, or the script did not run (no Node, an error) — show the user the message as
37
+ it came and stop. Do not repair by hand.
63
38
 
64
- If an agent's `.agent.md` `name:` is empty or has only ONE word, the persona name never
65
- existed and must be generated now, following the **Agent Naming Convention** from
66
- `_opencrew/core/prompts/design.prompt.md`:
39
+ Open with: "Olhei a crew {nome}. Encontrei {n} ponto(s) para consertar. Vou mostrar um por vez;
40
+ nada é gravado sem o seu sim, e cada arquivo alterado ganha uma cópia `.bak`."
67
41
 
68
- 1. Read the user's Output Language from `_opencrew/_memory/preferences.md`.
69
- 2. Generate a two-word name: "FirstName LastName" — both words start with the SAME letter
70
- (alliteration); the first name is common in the user's language; the last name is a
71
- playful reference to the agent's function (from its `title:`). Each agent in the crew
72
- must use a DIFFERENT initial letter.
73
- 3. Update BOTH the `.agent.md` `name:` frontmatter AND the `# {Name}` heading in that file.
74
- 4. Use the new name as the `displayName` in the rebuilt CSV.
42
+ ## Step 3: One finding at a time
75
43
 
76
- Only do this for agents that are actually broken. Agents that already have a valid two-word
77
- `name:` are left untouched (only the CSV is rewritten to carry it).
44
+ Take the findings in the order the script printed them. For each: say what it is, ask the
45
+ question, wait for the answer, and only then run the command. Never group two findings in one
46
+ question. A "não" leaves the point as it is: go on to the next one.
78
47
 
79
- ## Step 5: Report
48
+ The script's output is for you. To the user, say each point in plain words: do not show the
49
+ codes between brackets, the `--aplicar` lines or the `CONSERTO:` status line.
80
50
 
81
- Present a summary table of what changed:
51
+ | Finding | What you say and ask | Command after the yes |
52
+ |---|---|---|
53
+ | `nome-de-agente` | The agent has no two-word persona name. Propose one by the Agent Naming Convention of `_opencrew/core/prompts/design.prompt.md` (two words with the same initial, a different initial for each agent of the crew), keeping the first name the agent already has, and ask: "O agente {id} está sem nome de pessoa. Proponho {Nome Sobrenome}. Posso gravar?" | `--aplicar "nome:{id}={Nome Sobrenome}"`; the names reach the list of the crew with `manifesto`, below — when `manifesto` is not among the findings, run it right after this one |
54
+ | `manifesto` | "O arquivo de nomes da crew está incompleto; por isso aparece a função no lugar do nome. Posso refazer a partir dos arquivos dos agentes?" | `--aplicar "manifesto"` |
55
+ | `formato` | Read each listed step and propose one format per step, among the files of `_opencrew/core/best-practices/` (and `_opencrew/best-practices.local/`). A text to print, sign or file — ata, ofício, contrato, minuta, proposta, parecer — gets `documento-oficial`. Then: "Estes passos não dizem que tipo de texto produzem; sem isso, o verificador mede cada um como post de blog. Minha proposta: {passo → formato}. Posso gravar assim?" | one `--aplicar "formato:{passo}={formato}"` per step |
56
+ | `fontes` | "Esta crew não registra os arquivos do projeto que ela deve ler antes de escrever. Quais arquivos ou pastas ela precisa conhecer? (Pode responder 'nenhum'.)" Confirm that each one exists (search the project when only a name was given) and ask what the crew uses it for | one `--aplicar "fonte:{caminho}={para que}"` per file or folder, the path relative to the project root |
57
+ | `proibicao` | For each listed item: "Esta proibição não tem um trecho entre aspas, então o verificador não consegue barrar: «{item}». Qual trecho exato devo barrar? Se for uma regra de conteúdo, e não uma palavra ou expressão, responda 'revisão humana': ela fica para o revisor." The excerpt must be words of the item itself | `--aplicar "proibicao:{n}={trecho}"` or `--aplicar "proibicao:{n}=revisao-humana"` |
58
+ | `irreversivel` | For each listed step: "O passo {n} é feito por um agente que tem uma ferramenta de publicar ou enviar ({skill}). Este passo publica ou envia alguma coisa para fora do projeto? Se sim, marco o passo para que ele nunca seja repetido sozinho." | `--aplicar "irreversivel:{n}"` only for a yes |
59
+ | `sem-revisao` | "Esta crew não tem passo de revisão: nada é conferido antes de chegar a você. Isso se resolve editando a crew: /opencrew edit {nome}." | none |
60
+ | `sem-aprovacao-final` | "Depois da revisão não há um ponto de aprovação seu. Isso se resolve editando a crew: /opencrew edit {nome}." | none |
61
+ | `publica-antes` | "O passo {n} publica ou envia antes da revisão e da sua aprovação final. Enquanto estiver assim, o que sai não passou pela revisão. Isso se resolve editando a crew: /opencrew edit {nome}." | none |
62
+ | `passo-faltando` | Show the lines the script printed and say that it is solved by editing the crew: `/opencrew edit {nome}` | none |
82
63
 
64
+ The command is always the same line, with the item between double quotes:
65
+
66
+ ```
67
+ node _opencrew/core/scripts/conserto.mjs --crew "crews/{code}" --aplicar "{item}"
83
68
  ```
84
- Crew "{name}" repaired.
85
69
 
86
- | Agent id | Before | After | Source |
87
- |-------------|---------------|------------------|---------------|
88
- | researcher | (role only) | 🔎 Pedro Pesquisa | .agent.md |
89
- | copywriter | Guilherme | ✍️ Guilherme Gancho | generated |
70
+ Several items of the same finding may go in one call (`--aplicar "…" --aplicar "…"`). The last
71
+ line must be `CONSERTO:APLICADO`. With `CONSERTO:ERRO` nothing was written: read the reason to the
72
+ user, correct the item and ask again — do not write the file yourself.
90
73
 
91
- crew-party.csv: rewritten with displayName column
74
+ ## Step 4: Project paths
92
75
 
93
- Run it: /opencrew run {code}
76
+ After the findings, run the sources check:
77
+
78
+ ```
79
+ node _opencrew/core/scripts/conferir-fontes.mjs --crew "crews/{code}"
94
80
  ```
95
81
 
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.
82
+ When it lists a path with a suggestion (`Sugestão: …` — an absolute path left in a step, or a
83
+ file that moved), show the user each path and its suggestion and ask: "Posso corrigir estes
84
+ caminhos nos arquivos da crew?" After a yes, run the same command ending with `--corrigir`: the
85
+ script rewrites only those paths and keeps a copy of each file it changes. A missing file with
86
+ no suggestion is the user's to solve: say which one.
87
+
88
+ ## Step 5: Report
89
+
90
+ Run the diagnosis of Step 2 once more and close with what really happened:
98
91
 
99
- If nothing was broken (CSV already had a valid `displayName` for every agent), say so
100
- plainly instead of inventing changes: "This crew's manifest is already correct — no repair
101
- needed."
92
+ "Pronto: {k} conserto(s) gravado(s). Cópias do que mudou: {lista de .bak}. Ficou pendente:
93
+ {lista ou 'nada'}." — `{k}` is the number of points the user said yes to and the script wrote.
102
94
 
103
- ---
95
+ Then: `Run it: /opencrew run {code}`.
104
96
 
105
97
  ## Rules
106
98
 
107
- - **DO** pull names from `.agent.md` `name:` — that is the source of truth.
108
- - **DO** rewrite the whole `crew-party.csv` with the canonical header.
109
- - **DO** limit persona generation to agents whose own `.agent.md` name is missing/one-word.
110
- - **DO NOT** re-run Discovery, Design, Build, research, or investigations.
111
- - **DO NOT** modify agent personas, principles, or any section other than the `name:` line
112
- and `# {Name}` heading (and only in the fallback case).
113
- - **DO NOT** touch any file outside `crews/{code}/`.
114
- - **DO NOT** fabricate a summary — report only what you actually changed.
99
+ - **DO** run the diagnosis before and after; report only what the script printed.
100
+ - **DO** ask before every `--aplicar`, one finding at a time.
101
+ - **DO NOT** create, edit or delete any file under `crews/` with your own tools — not even to
102
+ "finish" a repair the script refused.
103
+ - **DO NOT** reorder, renumber, add or remove steps here: that is `/opencrew edit`.
104
+ - **DO NOT** touch `_opencrew/` or any other crew.
105
+ - **DO NOT** delete the `.bak` copies: they belong to the user.
@@ -114,7 +114,7 @@ Before starting execution:
114
114
  briefing, the research or your own assumptions, the sources take precedence over them
115
115
  (as fontes valem sobre o briefing e a pesquisa) — and say so when it matters.
116
116
 
117
- 2. Read `crews/{name}/pipeline/pipeline.yaml` for the pipeline definition
117
+ 2. Read `crews/{name}/pipeline/pipeline.yaml` for the pipeline definition. The format of the crew files — where each field lives and the older shapes that still count — is in `_opencrew/core/formato-da-crew.md`; read it when a field is not where you expect.
118
118
  3. **Resolve skills**: Read `crew.yaml` → `skills` section. For each non-native skill (anything other than web_search, web_fetch):
119
119
  a. Verify `skills/{skill}/SKILL.md` exists
120
120
  - If missing → ask user: "Skill '{skill}' is not installed. Install now? (y/n)"
@@ -124,13 +124,9 @@ Before starting execution:
124
124
  c. If type: mcp, verify MCP is configured in `.claude/settings.local.json`
125
125
  - If missing → **ERROR**: "Skill '{skill}' MCP not configured. Reinstall the skill."
126
126
  All skills must resolve successfully before the pipeline starts (fail fast).
127
- 4. **Model tiers**: Individual steps declare their own `model_tier` in their frontmatter (`fast` or `powerful`), set by the Architect at crew creation time based on the crew's tier (Express/Standard/Full).
128
- - Read `crew.yaml` → `crew.tier` field to understand the crew's depth level:
129
- - `express`: all steps use `model_tier: fast` by default
130
- - `standard`: mixed — research/data steps use `fast`, creative/review steps use `powerful`
131
- - `full`: all steps use `model_tier: powerful` by default
132
- - If a step has its own `model_tier` in frontmatter → step-level override takes priority over crew-level default.
133
- - If neither crew tier nor step model_tier is set → default to `powerful` at dispatch.
127
+ 4. **Model tiers**: a `subagent` step declares its own `model_tier` (`fast` or `powerful`), set at crew creation by the crew's tier; inline steps carry none.
128
+ - Read the crew's tier for the run header: `crew.tier` in `crew.yaml` (older crews: `tier` loose at the top level).
129
+ - A subagent step with no `model_tier` → `powerful` at dispatch.
134
130
 
135
131
  4b. **Pre-Execution Agent Selection** — Decide which agents actually run for this task.
136
132
  Run this step ONLY if `crew.yaml` declares an `agent_dependencies:` field (even an
@@ -563,7 +559,7 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
563
559
  Atualizo o perfil da empresa?" — change `company.md` only after a yes.
564
560
  - **If the step frontmatter contains `outputFile`**: after collecting the user's full response,
565
561
  insert only the run_id in the `outputFile` path (item 1 of the rule in Output Path Transformation — no version folder, no `saida` command), then write the response to that path using the Write tool (it creates the folder) before moving to the next step. Checkpoint files are user input captures, not versioned output: they live in the group itself, where `entrada` finds them.
566
- Use this format:
562
+ For the checkpoint that precedes the researcher, use this format:
567
563
  ```
568
564
  # Research Focus
569
565
 
@@ -571,7 +567,8 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
571
567
  **Time Range:** {selected time range label, e.g., "Últimos 7 dias"}
572
568
  **Date:** {today's date in YYYY-MM-DD format}
573
569
  ```
574
- This file is the `inputFile` for the researcher step that follows.
570
+ For any other checkpoint: `# {the checkpoint's title}`, the user's answer as given (the option chosen and every comment), and `**Date:** {today, YYYY-MM-DD}`.
571
+ This file is the `inputFile` of the step that follows.
575
572
 
576
573
  ### Post-Step Output Validation
577
574
 
@@ -681,8 +678,8 @@ When a step has `on_reject: {step-id}` (a review step):
681
678
  (real data only the user has): do NOT reject for them — the reviewer judges the rest, and the
682
679
  final approval below collects the missing data from the user.
683
680
  3. Track the review cycle count: a **cycle** is one pass of the reviewer. The maximum is
684
- `max_review_cycles`, an integer from 1 declared where the step declares `on_reject` (the step
685
- frontmatter or its `pipeline.yaml` entry); absent or invalid: 3. On every rejection, with or
681
+ `max_review_cycles`, an integer from 1: the one declared where the step declares `on_reject` (the
682
+ step frontmatter or its `pipeline.yaml` entry); without it, the one in `crew.yaml`; absent or invalid in both: 3. On every rejection, with or
686
683
  without a block, send the reviewer's feedback to the writer and go back to the referenced step.
687
684
  4. If the last allowed pass also rejects, stop; the status of the last report picks the message, as
688
685
  in item 2 — `VERIFICACAO:BLOQUEADA`: the blocks; any other status: the reviewer's feedback, also
@@ -0,0 +1,158 @@
1
+ // O diagnóstico do conserto: o que falta numa crew para as melhorias do runtime valerem nela.
2
+ // Cada achado tem um código e as linhas, em PT-BR fixo, que o usuário lê. Só leitura.
3
+ // Spec: fase-u4a-conserto-de-crews.md, §4 e regras 5, 6 e 9 (repositório do OpenCrew).
4
+ import path from 'node:path';
5
+ import { lerFrontmatter, semBom } from '../verificar/leitura.mjs';
6
+ import { itensDeProibicao } from '../verificar/proibicoes.mjs';
7
+ import { idDoAgente, lerBruto, listaDe } from './crew.mjs';
8
+ import { lerCsv } from './edicoes.mjs';
9
+
10
+ const EXPORTACAO = new Set(['pdf', 'csv', 'formatted-post']);
11
+ const plural = (n, um, varios) => (n === 1 ? um : varios);
12
+ const editar = (crew) => `Resolve-se editando a crew: /opencrew edit ${crew.nome}`;
13
+ const irreversivel = (passo) => passo.dados.side_effects === 'irreversible';
14
+ const revisoes = (crew) => crew.passos.filter((p) => p.revisao);
15
+
16
+ function manifesto(crew) {
17
+ if (!crew.agentes.length) return null;
18
+ const { colunas, linhas } = lerCsv(crew.csv);
19
+ const semNome = (l) => !l.displayName || l.displayName.toLowerCase() === (l.title ?? '').toLowerCase();
20
+ if (crew.csv !== null && colunas.includes('displayName') && !linhas.some(semNome)) return null;
21
+ return ['O arquivo de nomes da crew (crew-party.csv) está incompleto: aparece a função no lugar do nome.', 'Para consertar: --aplicar "manifesto"'];
22
+ }
23
+
24
+ function nomeDeAgente(crew) {
25
+ const semNome = crew.agentes.filter((a) => String(a.dados.name ?? '').trim().split(/\s+/).filter(Boolean).length < 2);
26
+ if (!semNome.length) return null;
27
+ const n = semNome.length;
28
+ return [
29
+ `${n} ${plural(n, 'agente', 'agentes')} sem nome de duas palavras.`,
30
+ ...semNome.map((a) => `${a.id} (name: "${a.dados.name ?? ''}")`),
31
+ 'Para consertar: --aplicar "nome:<agente>=<Nome Sobrenome>" e depois --aplicar "manifesto"',
32
+ ];
33
+ }
34
+
35
+ /** Os passos que o verificador mede: do passo de `on_reject` até o anterior à revisão (regra 6). */
36
+ function medidos(crew) {
37
+ const dentro = new Set();
38
+ for (const revisao of revisoes(crew)) {
39
+ const de = crew.passos.findIndex((p) => p.numero === revisao.volta);
40
+ const ate = crew.passos.indexOf(revisao);
41
+ if (de >= 0) crew.passos.slice(de, ate).forEach((p) => dentro.add(p));
42
+ }
43
+ return crew.passos.filter((p) => dentro.has(p) && p.arquivo && !p.checkpoint && !p.revisao);
44
+ }
45
+
46
+ const semFormato = (passo) => !passo.dados.format || EXPORTACAO.has(String(passo.dados.format));
47
+ const saidaDe = (passo) => path.posix.basename(String(passo.dados.outputFile ?? passo.citado).replace(/\\/g, '/'));
48
+
49
+ function formato(crew) {
50
+ const passos = medidos(crew).filter(semFormato);
51
+ if (!passos.length) return null;
52
+ const n = passos.length;
53
+ return [
54
+ `${n} ${plural(n, 'passo que a revisão confere não diz', 'passos que a revisão confere não dizem')} o formato do texto.`,
55
+ `Sem o formato, o verificador mede ${plural(n, 'esse texto', 'cada um')} como post de blog.`,
56
+ `Passos: ${passos.map((p) => `${p.numero} (${saidaDe(p)})`).join(', ')}`,
57
+ 'Para consertar: --aplicar "formato:<passo>=<formato>"',
58
+ ];
59
+ }
60
+
61
+ function fontes(crew) {
62
+ const linhas = semBom(crew.yaml ?? '').split(/\r?\n/);
63
+ const inicio = linhas.findIndex((l) => /^fontes\s*:/.test(l));
64
+ const fim = linhas.findIndex((l, i) => i > inicio && /^[^\s#-]/.test(l));
65
+ const daLista = inicio < 0 ? [] : linhas.slice(inicio + 1, fim < 0 ? linhas.length : fim);
66
+ if (daLista.some((l) => /^\s*(?:-\s*)?caminho\s*:\s*\S/.test(l))) return null;
67
+ return [
68
+ 'A crew não registra os arquivos do projeto que ela precisa ler.',
69
+ 'Sem isso, ela escreve sem conhecer o que o projeto já decidiu.',
70
+ 'Para consertar: --aplicar "fonte:<caminho>=<para que>" (um por arquivo ou pasta)',
71
+ ];
72
+ }
73
+
74
+ function proibicao(crew) {
75
+ const pendentes = itensDeProibicao(semBom(crew.memoria ?? '')).filter((i) => i.pendente);
76
+ if (!pendentes.length) return null;
77
+ const n = pendentes.length;
78
+ return [
79
+ `${n} ${plural(n, 'proibição', 'proibições')} sem trecho entre aspas: o verificador não consegue barrar.`,
80
+ ...pendentes.map((i) => `${i.n}. ${i.texto}`),
81
+ 'Para consertar: --aplicar "proibicao:<n>=<trecho>" ou --aplicar "proibicao:<n>=revisao-humana"',
82
+ ];
83
+ }
84
+
85
+ /** A skill instalada no projeto declara `side_effects: irreversible`? (regra 9) */
86
+ function publica(raiz, skill) {
87
+ const texto = lerBruto(path.join(raiz, 'skills', skill, 'SKILL.md'));
88
+ return texto !== null && lerFrontmatter(semBom(texto))?.side_effects === 'irreversible';
89
+ }
90
+
91
+ function semMarca(crew) {
92
+ const doPasso = (passo) => {
93
+ const agente = crew.agentes.find((a) => a.id === idDoAgente(passo));
94
+ const skills = [...listaDe(agente?.bruto, 'skills'), ...listaDe(passo.bruto, 'skills_needed')];
95
+ const skill = skills.find((s) => /^[A-Za-z0-9._-]+$/.test(s) && publica(crew.raiz, s));
96
+ return skill ? `Passo ${passo.numero} — agente ${agente?.id ?? idDoAgente(passo)}, skill ${skill}` : null;
97
+ };
98
+ const linhas = crew.passos.filter((p) => p.arquivo && !p.checkpoint && !irreversivel(p)).map(doPasso).filter(Boolean);
99
+ if (!linhas.length) return null;
100
+ const n = linhas.length;
101
+ return [
102
+ `${n} ${plural(n, 'passo', 'passos')} de agente que tem ferramenta de publicar ou enviar, sem a marca de passo irreversível.`,
103
+ ...linhas,
104
+ 'Se o passo publica ou envia: --aplicar "irreversivel:<passo>"',
105
+ ];
106
+ }
107
+
108
+ function semRevisao(crew) {
109
+ if (revisoes(crew).length || !crew.passos.length) return null;
110
+ return ['A crew não tem passo de revisão: nada é conferido antes de chegar a você.', editar(crew)];
111
+ }
112
+
113
+ /** Posição da última revisão e do primeiro checkpoint depois dela (-1 quando não há). */
114
+ function fecho(crew) {
115
+ const revisao = crew.passos.indexOf(revisoes(crew).at(-1));
116
+ const aprovacao = crew.passos.findIndex((p, i) => i > revisao && p.checkpoint);
117
+ return { revisao, aprovacao };
118
+ }
119
+
120
+ function semAprovacaoFinal(crew) {
121
+ const { revisao, aprovacao } = fecho(crew);
122
+ if (revisao < 0 || aprovacao >= 0) return null;
123
+ return ['Depois da revisão não há um ponto de aprovação seu.', editar(crew)];
124
+ }
125
+
126
+ function publicaAntes(crew) {
127
+ const { revisao, aprovacao } = fecho(crew);
128
+ if (revisao < 0) return null;
129
+ const limite = aprovacao >= 0 ? aprovacao : revisao;
130
+ const cedo = crew.passos.filter((p, i) => i < limite && irreversivel(p)).map((p) => p.numero);
131
+ if (!cedo.length) return null;
132
+ const quem = cedo.length === 1 ? `O passo ${cedo[0]} publica ou envia` : `Os passos ${cedo.join(', ')} publicam ou enviam`;
133
+ return [`${quem} antes da revisão e da sua aprovação final.`, 'Enquanto estiver assim, o que sai não passou pela revisão.', editar(crew)];
134
+ }
135
+
136
+ function passoFaltando(crew) {
137
+ const semArquivo = crew.passos.filter((p) => !p.arquivo).map((p) => `O passo ${p.numero} cita ${p.citado || 'um arquivo sem nome'}, que não existe.`);
138
+ const existe = (numero) => crew.passos.some((p) => p.numero === numero);
139
+ const semAlvo = revisoes(crew).filter((p) => !existe(p.volta)).map((p) => `O passo ${p.numero} manda voltar ao passo ${p.volta ?? p.dados.on_reject}, que não existe.`);
140
+ const linhas = [...semArquivo, ...semAlvo];
141
+ return linhas.length ? ['A sequência de passos cita o que não existe.', ...linhas, editar(crew)] : null;
142
+ }
143
+
144
+ // A ordem em que os achados aparecem (§4 da spec).
145
+ const CONFERENCIAS = [
146
+ ['nome-de-agente', nomeDeAgente], ['manifesto', manifesto], ['formato', formato], ['fontes', fontes],
147
+ ['proibicao', proibicao], ['irreversivel', semMarca], ['sem-revisao', semRevisao],
148
+ ['sem-aprovacao-final', semAprovacaoFinal], ['publica-antes', publicaAntes], ['passo-faltando', passoFaltando],
149
+ ];
150
+
151
+ /**
152
+ * Os achados de uma crew, na ordem da spec.
153
+ * @param {object} crew o que `lerCrew` devolveu
154
+ * @returns {Array<{ codigo: string, linhas: string[] }>} a primeira linha é o título do achado
155
+ */
156
+ export function diagnosticar(crew) {
157
+ return CONFERENCIAS.map(([codigo, conferir]) => ({ codigo, linhas: conferir(crew) })).filter((a) => a.linhas);
158
+ }