@aksp/opencrew 1.12.0 → 1.14.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/CHANGELOG.md +57 -0
- package/README.md +25 -3
- package/package.json +1 -1
- package/templates/AGENTS.md +3 -5
- package/templates/_opencrew/.opencrew-version +1 -1
- package/templates/_opencrew/core/formato-da-crew.md +1 -0
- package/templates/_opencrew/core/prompts/build.prompt.md +2 -0
- package/templates/_opencrew/core/prompts/repair.prompt.md +4 -1
- package/templates/_opencrew/core/runner/contrato-de-saida.md +33 -0
- package/templates/_opencrew/core/runner/escritorio.md +37 -0
- package/templates/_opencrew/core/runner/fim-da-execucao.md +99 -0
- package/templates/_opencrew/core/runner/fontes-pendentes.md +21 -0
- package/templates/_opencrew/core/runner/memoria.md +58 -0
- package/templates/_opencrew/core/runner/retomar.md +51 -0
- package/templates/_opencrew/core/runner/selecao-de-agentes.md +79 -0
- package/templates/_opencrew/core/runner/tarefas-do-agente.md +34 -0
- package/templates/_opencrew/core/runner.pipeline.md +52 -364
- package/templates/_opencrew/core/scripts/caminho/argumentos.mjs +7 -4
- package/templates/_opencrew/core/scripts/caminho/crew.mjs +20 -0
- package/templates/_opencrew/core/scripts/caminho/disco.mjs +4 -3
- package/templates/_opencrew/core/scripts/caminho.mjs +62 -29
- package/templates/_opencrew/core/scripts/conserto/achados.mjs +2 -0
- package/templates/_opencrew/core/scripts/conserto/aplicar.mjs +2 -1
- package/templates/_opencrew/core/scripts/conserto/argumentos.mjs +2 -1
- package/templates/_opencrew/core/scripts/conserto/crew.mjs +4 -3
- package/templates/_opencrew/core/scripts/conserto/historico.mjs +102 -0
- package/templates/_opencrew/core/scripts/conserto.mjs +9 -7
- package/templates/_opencrew/core/scripts/entrega/leiame.mjs +4 -2
- package/templates/_opencrew/core/scripts/entregar.mjs +2 -0
- package/templates/_opencrew/core/scripts/estado/arquivo.mjs +17 -10
- package/templates/_opencrew/core/scripts/execucao/argumentos.mjs +62 -0
- package/templates/_opencrew/core/scripts/execucao/historico.mjs +76 -0
- package/templates/_opencrew/core/scripts/execucao/registro.mjs +115 -0
- package/templates/_opencrew/core/scripts/execucao/retomar.mjs +123 -0
- package/templates/_opencrew/core/scripts/execucao.mjs +123 -0
|
@@ -24,6 +24,7 @@ included), digits, space and `. _ - / \ : ( )`. With any other character (`$`, b
|
|
|
24
24
|
|
|
25
25
|
## Initialization
|
|
26
26
|
|
|
27
|
+
**Resuming** — only on `/opencrew retomar {name}`: before any step below, read `_opencrew/core/runner/retomar.md` completely and follow it — it asks the user first, then says when to do this Initialization, with no step 5b (no new folder: the run goes on with its `run_id`).
|
|
27
28
|
Before starting execution:
|
|
28
29
|
|
|
29
30
|
1. You have already loaded:
|
|
@@ -35,77 +36,21 @@ Before starting execution:
|
|
|
35
36
|
|
|
36
37
|
1a. **Escritório toggle** — the optional live view is off unless `preferences.md` turns it on (see "Escritório" below).
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
> |---|---|---|
|
|
45
|
-
> | `## Estilo de Escrita` | `memories.md` | Writing style rules accumulated per crew |
|
|
46
|
-
> | `## Design Visual` | `memories.md` | Visual design preferences per crew |
|
|
47
|
-
> | `## Estrutura de Conteúdo` | `memories.md` | Content structure rules per crew |
|
|
48
|
-
> | `## Proibições Explícitas` | `memories.md` | User bans and hard blocks per crew |
|
|
49
|
-
> | `## Técnico (específico do crew)` | `memories.md` | Technical crew-specific settings |
|
|
50
|
-
> | `Data \| Run ID \| Tema \| Output \| Score \| Resultado` | `runs.md` | Run history table columns |
|
|
51
|
-
>
|
|
52
|
-
> When adding new structural sections to `memories.md` or `runs.md`, keep headers in PT-BR
|
|
53
|
-
> unless the user base expands beyond PT-BR — at that point, discuss a migration strategy
|
|
54
|
-
> (e.g. i18n key mapping) rather than mixing languages in a single file.
|
|
55
|
-
|
|
56
|
-
1b. **Memory format migration** — After loading `memories.md`, check whether it uses the new format: it does when it has the `## Estilo de Escrita` section header (read the file with the read tool — no command).
|
|
57
|
-
- If it has the header → proceed normally.
|
|
58
|
-
- If it does not (or the file is empty / does not exist) → migrate before proceeding:
|
|
59
|
-
a0. If the file exists and is not empty, FIRST copy it to `crews/{name}/_memory/memories.md.bak`
|
|
60
|
-
(never lose what the crew learned), then tell the user in one line:
|
|
61
|
-
"Atualizei o formato da memória da crew; a versão anterior está em `memories.md.bak`."
|
|
62
|
-
Move every rule you can recognize from the old file into the matching new section.
|
|
63
|
-
a. Write `crews/{name}/_memory/memories.md` with the new sections format:
|
|
64
|
-
```markdown
|
|
65
|
-
# Crew Memory: {crew-name}
|
|
66
|
-
|
|
67
|
-
## Estilo de Escrita
|
|
68
|
-
|
|
69
|
-
## Design Visual
|
|
70
|
-
|
|
71
|
-
## Estrutura de Conteúdo
|
|
72
|
-
|
|
73
|
-
## Proibições Explícitas
|
|
74
|
-
|
|
75
|
-
## Técnico (específico do crew)
|
|
76
|
-
```
|
|
77
|
-
(Use the crew's display name for `{crew-name}`, and the crew code for `{name}` in file paths — they refer to the same crew.)
|
|
78
|
-
b. Check if `crews/{name}/_memory/runs.md` exists (read tool — no command).
|
|
79
|
-
If it does not exist, create it with:
|
|
80
|
-
```markdown
|
|
81
|
-
# Run History: {crew-name}
|
|
82
|
-
|
|
83
|
-
| Data | Run ID | Tema | Output | Score | Resultado |
|
|
84
|
-
|------|--------|------|--------|-------|-----------|
|
|
85
|
-
```
|
|
86
|
-
- Do not pause execution for this migration (the one-line notice above is enough).
|
|
39
|
+
1b. **Memory format** — check, with the read tool (no command), whether `memories.md` has the
|
|
40
|
+
`## Estilo de Escrita` section header. It has → proceed. It does not, or the file is empty or does not
|
|
41
|
+
exist → read `_opencrew/core/runner/memoria.md` completely and follow it before proceeding (it migrates
|
|
42
|
+
the file, with a `.bak` copy, without pausing the run). The section headers of `memories.md` (`## Estilo de
|
|
43
|
+
Escrita`, `## Design Visual`, `## Estrutura de Conteúdo`, `## Proibições Explícitas`, `## Técnico (específico do
|
|
44
|
+
crew)`) and the columns of `runs.md` are fixed PT-BR, whatever the user's language: never translate them.
|
|
87
45
|
|
|
88
46
|
1c. **Source check** — before loading the project sources (1d), run:
|
|
89
47
|
```bash
|
|
90
48
|
node _opencrew/core/scripts/conferir-fontes.mjs --crew "crews/{name}"
|
|
91
49
|
```
|
|
92
|
-
If the last line is `FONTES:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{resumo do relatório}
|
|
97
|
-
|
|
98
|
-
1. Corrigir os caminhos sugeridos (troco nos arquivos da crew e guardo .bak)
|
|
99
|
-
2. Seguir assim mesmo
|
|
100
|
-
3. Parar
|
|
101
|
-
```
|
|
102
|
-
On 1, run the same command with `--corrigir`, show the new result and re-read `crew.yaml` and
|
|
103
|
-
any agent file already loaded (it may have changed them); 1d then loads the sources from the
|
|
104
|
-
corrected paths. If the new result still ends in `FONTES:PENDENTE`, ask again with options 2 and
|
|
105
|
-
3 only. Alerts — not portable (absolute paths) or "não conferido" (a network path or a site
|
|
106
|
-
address: the script never accesses the network) — are mentioned once, without stopping. If the
|
|
107
|
-
script did not run (no Node, an error, or no `FONTES:` status line), tell the user "⚠️ A
|
|
108
|
-
conferência de fontes não rodou: {motivo}" and continue; the final approval repeats the warning.
|
|
50
|
+
If the last line is `FONTES:OK`, go on: an alert in the report (an absolute path, a network path or a
|
|
51
|
+
site address) is mentioned once, without stopping. Otherwise (`FONTES:PENDENTE`, or the script did not
|
|
52
|
+
run): read `_opencrew/core/runner/fontes-pendentes.md` completely and follow it — never continue
|
|
53
|
+
silently with a missing source.
|
|
109
54
|
|
|
110
55
|
1d. **Project sources (`fontes:`)** — if `crew.yaml` has a `fontes:` list (files or folders of
|
|
111
56
|
the user's project, paths relative to the project root), read them now: a file in full up to
|
|
@@ -128,82 +73,10 @@ Before starting execution:
|
|
|
128
73
|
- Read the crew's tier for the run header: `crew.tier` in `crew.yaml` (older crews: `tier` loose at the top level).
|
|
129
74
|
- A subagent step with no `model_tier` → `powerful` at dispatch.
|
|
130
75
|
|
|
131
|
-
4b. **Pre-Execution Agent Selection** —
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
When active, in this order:
|
|
137
|
-
|
|
138
|
-
a. **Capture the task** — Determine the user's request for this run:
|
|
139
|
-
- If the run was invoked with a description (e.g. `/opencrew run {name} {description}`),
|
|
140
|
-
use that text as the task.
|
|
141
|
-
- Otherwise ask: `📝 What is the task for this run? Reply in one line.`
|
|
142
|
-
Wait for the user's reply before continuing.
|
|
143
|
-
|
|
144
|
-
b. **Analyze against the decision matrix** — Scan the task text (case-insensitive,
|
|
145
|
-
PT-BR and EN keywords) for the signals below. Start with ALL agents suggested as
|
|
146
|
-
SELECTED (`required`). For each matching signal, find the affected agent(s) in
|
|
147
|
-
`crew-party.csv` by matching the role terms against the agent's `id` and `title`
|
|
148
|
-
(and `displayName` if ambiguous), then apply the suggested status:
|
|
149
|
-
|
|
150
|
-
| Signal in the task | Role terms to match (id / title) | Suggested status |
|
|
151
|
-
|--------------------|----------------------------------|------------------|
|
|
152
|
-
| "já pesquisei", "com base em", "fontes que tenho", "material pronto", "baseado nas fontes", "research already done" | researcher, pesquisad, research | optional |
|
|
153
|
-
| "revise", "melhore", "corrija", "refine", "edite" (sem criar do zero), "improve this draft" | copywriter, redator, writer, criador | optional |
|
|
154
|
-
| "só texto", "sem imagem", "sem visual", "sem arte", "no image" | designer, design, visual | skip |
|
|
155
|
-
| "já revisei", "já foi aprovado", "aprovado por terceiros", "revisão feita", "already reviewed" | reviewer, revisor | optional |
|
|
156
|
-
| "quero só revisar este texto", "apenas revisar", "review only" | researcher AND copywriter | skip |
|
|
157
|
-
| "tenho o conteúdo pronto", "forneço o documento", "docs em anexo", "segue o material", "here is the content" | copywriter, writer, creator | optional |
|
|
158
|
-
|
|
159
|
-
Resolution rules:
|
|
160
|
-
- `optional` = agent stays selected but may be unchecked.
|
|
161
|
-
- `skip` = agent is suggested deselected.
|
|
162
|
-
- Conflicting signals on the same agent → the more restrictive wins (`skip` > `optional`).
|
|
163
|
-
- Never suggest skipping an agent whose output is the run's final deliverable unless the
|
|
164
|
-
signal is explicit.
|
|
165
|
-
- No signal matches → suggest keeping all agents (no change).
|
|
166
|
-
|
|
167
|
-
c. **Present the selection** — IDE-neutral numbered multi-select. List every agent from
|
|
168
|
-
`crew-party.csv` in party order:
|
|
169
|
-
```
|
|
170
|
-
🧑🤝🧑 Which agents should work on this task?
|
|
171
|
-
|
|
172
|
-
Suggested selection:
|
|
173
|
-
1. [x] {icon} {displayName} ({id}) — {title}
|
|
174
|
-
2. [x] {icon} {displayName} ({id}) — {title}
|
|
175
|
-
3. [ ] {icon} {displayName} ({id}) — {title}
|
|
176
|
-
...
|
|
177
|
-
[x] = suggested selected · [ ] = suggested deselected
|
|
178
|
-
|
|
179
|
-
Reply with the numbers of the agents you want to INCLUDE, separated by commas.
|
|
180
|
-
Example: "1, 2" · Reply "all" to run everyone.
|
|
181
|
-
```
|
|
182
|
-
Wait for the user's reply. Parse it into `selected_agents`. At least one agent must
|
|
183
|
-
be selected — if the user replies with none, repeat the prompt once.
|
|
184
|
-
|
|
185
|
-
d. **Dependency warnings** — Using `crew.yaml → agent_dependencies`
|
|
186
|
-
(e.g. `copywriter: [researcher]` = copywriter consumes researcher's output):
|
|
187
|
-
for every dependency `dependent → required_agent`, if `dependent` is selected but
|
|
188
|
-
`required_agent` is NOT, warn:
|
|
189
|
-
```
|
|
190
|
-
⚠️ {dependent} normally depends on {required_agent}'s output, which you deselected.
|
|
191
|
-
|
|
192
|
-
1. Re-select {required_agent} (recommended)
|
|
193
|
-
2. Keep going without it — I will supply the input myself
|
|
194
|
-
3. Deselect {dependent} too
|
|
195
|
-
```
|
|
196
|
-
Wait for the user's choice and apply it. If they pick option 2, set
|
|
197
|
-
`missing_dependency = true` in working memory (the existing Pre-Step Input
|
|
198
|
-
Validation recovery — "Skip step and continue / Abort" — then handles any
|
|
199
|
-
downstream gap).
|
|
200
|
-
|
|
201
|
-
e. **Build the filtered step list** — Set `skipped_agents = all party agents − selected_agents`.
|
|
202
|
-
Build `filtered_steps` by walking `pipeline.yaml` in order, keeping a step when:
|
|
203
|
-
- its frontmatter has NO `agent:` field (checkpoints / generic steps), OR
|
|
204
|
-
- its `agent:` value is in `selected_agents`.
|
|
205
|
-
Store `selected_agents`, `skipped_agents`, and `filtered_steps` in working memory for
|
|
206
|
-
the per-step loop (steps 5 and 6 below reflect them).
|
|
76
|
+
4b. **Pre-Execution Agent Selection** — ONLY if `crew.yaml` declares an `agent_dependencies:` field (even an
|
|
77
|
+
empty map `{}`): read `_opencrew/core/runner/selecao-de-agentes.md` completely and follow it now; it
|
|
78
|
+
leaves `selected_agents`, `skipped_agents`, `filtered_steps` and `missing_dependency` in working memory.
|
|
79
|
+
If the field is absent, read nothing: run ALL agents, with no selection step.
|
|
207
80
|
|
|
208
81
|
5. Inform the user that the crew is starting:
|
|
209
82
|
```
|
|
@@ -218,7 +91,7 @@ Before starting execution:
|
|
|
218
91
|
When the selection step was skipped (no `agent_dependencies:` in crew.yaml), this is
|
|
219
92
|
identical to today: all agents listed, no Skipped line.
|
|
220
93
|
5b. **Initialize run folder**: the script names the run — never build the date or the time yourself:
|
|
221
|
-
- Run the `pasta` command (see "Output Path Transformation" below). It creates the folder of this run and answers `CAMINHO:OK crews/{name}/output/{run_id}`
|
|
94
|
+
- Run the `pasta` command (see "Output Path Transformation" below). It creates the folder of this run and its record, and answers `CAMINHO:OK crews/{name}/output/{run_id}`
|
|
222
95
|
- The `run_id` is the last segment of that path: `YYYY-MM-DD-HHmmss` from the computer's clock (e.g. `2026-03-03-143022`; `-2`, `-3` when that folder already exists)
|
|
223
96
|
- The date of this run, wherever one is asked below, is the first 10 characters of the `run_id`
|
|
224
97
|
- Never create a folder by command yourself
|
|
@@ -227,39 +100,11 @@ Before starting execution:
|
|
|
227
100
|
|
|
228
101
|
## Escritório (optional live view)
|
|
229
102
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
| Moment | Command |
|
|
236
|
-
|---|---|
|
|
237
|
-
| Start of the run (Initialization, step 6) | `node _opencrew/core/scripts/estado.mjs "{name}" iniciar --passos {N}` |
|
|
238
|
-
| Right after `iniciar`, once per deselected agent | `node _opencrew/core/scripts/estado.mjs "{name}" pular --agente {id}` |
|
|
239
|
-
| Before each step, each time it starts | `node _opencrew/core/scripts/estado.mjs "{name}" passo --n {K} --agente {id} --rotulo "{rótulo}" --mensagem "{frase}"` |
|
|
240
|
-
| Before asking the question of a checkpoint (instead of `passo`) | `node _opencrew/core/scripts/estado.mjs "{name}" checkpoint --n {K} --agente {id} --rotulo "{rótulo}"` |
|
|
241
|
-
| End of the run (After Pipeline Completion) | `node _opencrew/core/scripts/estado.mjs "{name}" concluir` |
|
|
242
|
-
| Run aborted after `iniciar`, by the user or by an error | `node _opencrew/core/scripts/estado.mjs "{name}" falhar --motivo "{motivo}"` |
|
|
243
|
-
|
|
244
|
-
- **One at a time** — Run these commands one at a time, waiting for the `ESTADO:` line of each
|
|
245
|
-
before the next — never in parallel or in the background (each one reads and rewrites the same file).
|
|
246
|
-
- **Values** — `{name}`: the crew code. `{N}`: how many steps will run, checkpoints included (a
|
|
247
|
-
deselected agent's steps do not count). `{K}`: the step's position among them, from 1. `{id}`: the agent's `id` column in
|
|
248
|
-
`crew-party.csv`; a step or checkpoint with no `agent:` goes without `--agente`
|
|
249
|
-
(the table shows the full form). `{rótulo}`: the step's name, in
|
|
250
|
-
a few words. `--mensagem` goes only when the agent changed since the last `passo` (so never on the first
|
|
251
|
-
one): one sentence on what the previous agent delivered — never look at the next step. `{motivo}`: why the run stopped.
|
|
252
|
-
- **Text on the command line** — `--rotulo`, `--mensagem` and `--motivo` go between double quotes,
|
|
253
|
-
on one line, starting with a letter or a digit, with only letters (accents included), digits,
|
|
254
|
-
spaces and `. , : ; - ( ) / ?`. Drop every other sign (quotes of any kind, `$`, backtick, `\`,
|
|
255
|
-
`%`, `!`, emoji). If no text is left, omit the option. Write them in the user's language.
|
|
256
|
-
- **After `iniciar`**, when it answers `ESTADO:OK`, show the user once:
|
|
257
|
-
`Escritório ligado. Se a página não estiver aberta, rode em outro terminal: node _opencrew/core/scripts/escritorio.mjs`
|
|
258
|
-
- **The Escritório never stops the run.** A command that fails, does not run or answers
|
|
259
|
-
`ESTADO:IGNORADO`: go on, do not repeat that event, ask nothing, and tell the user once per run,
|
|
260
|
-
in one line: `O escritório não foi atualizado nesta execução; o trabalho segue normalmente.` With
|
|
261
|
-
the reason "escritório desligado", say nothing and stop calling the script for the rest of this run.
|
|
262
|
-
- The script is the only writer: never read, write or describe `crews/{name}/state.json` yourself.
|
|
103
|
+
Only when the already-loaded `preferences.md` has `Dashboard: enabled` (written `- **Dashboard:** enabled`
|
|
104
|
+
or plain `Dashboard: enabled`, any letter case): read `_opencrew/core/runner/escritorio.md` completely,
|
|
105
|
+
once, and follow it at each moment it names (start of the run, each step, each checkpoint, end, abort).
|
|
106
|
+
With the Dashboard off, read nothing and run none of its commands. Either way: never read, write or
|
|
107
|
+
describe `crews/{name}/state.json` yourself, and a failure there never stops the run.
|
|
263
108
|
|
|
264
109
|
## Execution Rules
|
|
265
110
|
|
|
@@ -408,36 +253,9 @@ when passing prior agents' outputs as context:
|
|
|
408
253
|
|
|
409
254
|
### Task-Based Agent Execution
|
|
410
255
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
- Each entry is a relative path to a task file (e.g., `tasks/analyze-source.md`)
|
|
415
|
-
- Tasks execute in the order listed
|
|
416
|
-
|
|
417
|
-
2. **For each task in sequence**:
|
|
418
|
-
a. Read the task file from the agent's directory (e.g., `crews/{crew-name}/agents/{agent}/tasks/{task}.md`)
|
|
419
|
-
b. Construct the execution prompt:
|
|
420
|
-
- Agent persona + principles (from agent.md — fixed across all tasks)
|
|
421
|
-
- Task description and process (from task file)
|
|
422
|
-
- Task output format (from task file)
|
|
423
|
-
- Task quality criteria and veto conditions (from task file)
|
|
424
|
-
- Input: For the first task, use the step's input. For subsequent tasks, use the previous task's output.
|
|
425
|
-
c. Execute the task (inline or subagent, matching the step's execution mode)
|
|
426
|
-
d. Collect the task output
|
|
427
|
-
e. Check task veto conditions (same enforcement as step veto conditions below)
|
|
428
|
-
|
|
429
|
-
3. **Final output**: The output of the LAST task in the chain becomes the step's output
|
|
430
|
-
- Resolve the `outputFile` path with the `saida` command (Output Path Transformation) before saving — this applies regardless of whether the step runs as `execution: inline` or `execution: subagent`
|
|
431
|
-
- Save to the **transformed** outputFile path
|
|
432
|
-
- This is what the next step (or checkpoint) receives
|
|
433
|
-
|
|
434
|
-
4. **Progress reporting**: For inline execution, announce each task:
|
|
435
|
-
```
|
|
436
|
-
{icon} {Agent Name} — Task {N}/{total}: {task name}...
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
5. **Backward compatibility**: If the agent's frontmatter does NOT contain a `tasks:` field,
|
|
440
|
-
execute the agent monolithically as before (current behavior unchanged).
|
|
256
|
+
Only when the agent's `.agent.md` frontmatter contains a `tasks:` field: read
|
|
257
|
+
`_opencrew/core/runner/tarefas-do-agente.md` completely and follow it for that step. Without the field,
|
|
258
|
+
execute the agent as a whole, as always.
|
|
441
259
|
|
|
442
260
|
### Output Path Transformation
|
|
443
261
|
|
|
@@ -448,10 +266,10 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
|
|
|
448
266
|
|
|
449
267
|
| Moment | Command |
|
|
450
268
|
|---|---|
|
|
451
|
-
| Start of the run (Initialization, step 5b) | `node _opencrew/core/scripts/caminho.mjs "{name}" pasta` (no `--run`: the script creates the `run_id`) |
|
|
269
|
+
| Start of the run (Initialization, step 5b) | `node _opencrew/core/scripts/caminho.mjs "{name}" pasta --tema "{tema}" --passos {N}` (no `--run`: the script creates the `run_id`) |
|
|
452
270
|
| Before a step, for its `inputFile` | `node _opencrew/core/scripts/caminho.mjs "{name}" entrada --run "{run_id}" --arquivo "{inputFile}"` |
|
|
453
271
|
| Before a step writes, for the first `outputFile` of each group | `node _opencrew/core/scripts/caminho.mjs "{name}" saida --run "{run_id}" --arquivo "{outputFile}"` |
|
|
454
|
-
| After a step wrote, for each output file | `node _opencrew/core/scripts/caminho.mjs "{name}" conferir --arquivo "{path}"` |
|
|
272
|
+
| After a step wrote, for each output file | `node _opencrew/core/scripts/caminho.mjs "{name}" conferir --arquivo "{path}" --passo {step}` |
|
|
455
273
|
|
|
456
274
|
- **Values** — `{name}`: the crew code. `{inputFile}` / `{outputFile}`: the path as the step
|
|
457
275
|
declares it (raw, without the run_id). `{path}`: the path `saida` returned. The safe-name rule
|
|
@@ -480,6 +298,20 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
|
|
|
480
298
|
this way skips its gate and is listed at the final approval:
|
|
481
299
|
`{arquivo} — não verificado: a conferência de caminhos não rodou`.
|
|
482
300
|
|
|
301
|
+
### Run record (registro da execução)
|
|
302
|
+
|
|
303
|
+
The scripts keep the record of the run on disk (`crews/{name}/output/{run_id}/execucao.json`): `/opencrew retomar` and the history (`runs.md`) are read from it. `pasta` and `conferir` feed it; you add one command at three moments:
|
|
304
|
+
|
|
305
|
+
| Moment | Command |
|
|
306
|
+
|---|---|
|
|
307
|
+
| A checkpoint was answered and its answer saved | `node _opencrew/core/scripts/execucao.mjs "{name}" marcar --run "{run_id}" --passo {step} --evento checkpoint --resultado {resultado} --nota "{nota}"` |
|
|
308
|
+
| The reviewer gave the verdict (each cycle) | `node _opencrew/core/scripts/execucao.mjs "{name}" marcar --run "{run_id}" --passo {step} --evento revisao --resultado {resultado} --nota "{nota}"` |
|
|
309
|
+
| End of the run, and whenever it is aborted | `node _opencrew/core/scripts/execucao.mjs "{name}" fechar --run "{run_id}" --resultado {resultado} --saida "{saída}"` |
|
|
310
|
+
|
|
311
|
+
- **Values** — `{step}`: the step's number in `pipeline.yaml` (`step:`; without it, its position, from 1) — the same in `conferir --passo`. `{resultado}`: checkpoint → `aprovado` (the user judged something the crew produced and accepted it as it is), `corrigido` (the answer asked for any change) or `pulado` (no judgement: the checkpoint only collected an answer — a topic, a choice — or was skipped); revisao → `aprovado` or `rejeitado`; fechar → `aprovado`, `publicado` (an irreversible step published or sent), `rejeitado` (the review rejected at the last cycle and the user aborted) or `abortado`. `{nota}`: the correction asked or the reason of the rejection — no `--nota` on an approval. `{tema}`: the topic of this run, in a few words; when only a checkpoint reveals it, start with no `--tema` and add `--tema "{tema}"` to that checkpoint's `marcar`. `{N}`: how many steps will run, checkpoints included. `{saída}`: what was produced ("Carrossel 9 slides").
|
|
312
|
+
- **Text on the command line** (`{tema}`, `{nota}`, `{saída}`) — one line between double quotes, only letters (accents included), digits, spaces and `. , : ; - ( ) / ?`; drop every other sign, and omit the option when no text is left.
|
|
313
|
+
- The scripts are the only writers: never read, write or describe `execucao.json` yourself, and never write `runs.md`. A warning `Não consegui gravar o registro desta execução`, or one of these commands not running, never stops the run: tell the user once and go on.
|
|
314
|
+
|
|
483
315
|
### For each pipeline step:
|
|
484
316
|
|
|
485
317
|
0. **Agent deselection check** — Read the step's `agent:` frontmatter field.
|
|
@@ -535,7 +367,7 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
|
|
|
535
367
|
- Proceed to Post-Step Output Validation (below) before advancing.
|
|
536
368
|
|
|
537
369
|
#### If `execution: inline`
|
|
538
|
-
- Switch to the agent's persona (read from party CSV)
|
|
370
|
+
- Switch to the agent's persona (read from party CSV); an agent with `tasks:` runs them as `Task-Based Agent Execution` says
|
|
539
371
|
- Announce: `{icon} {Agent Name} is working...`
|
|
540
372
|
- Follow the step instructions
|
|
541
373
|
- Present output directly in the conversation
|
|
@@ -548,6 +380,7 @@ root the one-line command of each moment and read the last line (`CAMINHO:OK {pa
|
|
|
548
380
|
- **Always include the file path** of any generated content the user needs to review. Example: "Review the content at `crews/{name}/output/{run_id}/v2/content.md` and let me know if it looks good." (the path the script returned)
|
|
549
381
|
- Wait for user input before proceeding
|
|
550
382
|
- Save the user's choice/response for the next step
|
|
383
|
+
- Record the answer with the `marcar` command (`--evento checkpoint`, see "Run record") — last thing of the checkpoint, after the memory and the `outputFile` below are written
|
|
551
384
|
- **Correction → memory, right away**: if the answer corrects something (tone, audience, a term,
|
|
552
385
|
a fact, a format), write it to `crews/{name}/_memory/memories.md` in the matching section
|
|
553
386
|
**before the next step** (antes do próximo passo) — not only at the end of the run, which may
|
|
@@ -603,35 +436,9 @@ After a step produces output (subagent or inline) and BEFORE Veto Condition Enfo
|
|
|
603
436
|
|
|
604
437
|
### Output Contract Validation
|
|
605
438
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
1. **Required sections check**: If `output_contract.required_sections` is defined, add
|
|
610
|
-
`--secoes {min_sections}` to the same `conferir` command: the file needs at least that many
|
|
611
|
-
lines starting with `## `.
|
|
612
|
-
|
|
613
|
-
2. **TL;DR check**: If the output contract requires a TL;DR section, add `--tldr` to the same
|
|
614
|
-
`conferir` command.
|
|
615
|
-
|
|
616
|
-
3. **If a check fails** (the last line is `CAMINHO:REPROVADO {motivo}`, with a motivo other than
|
|
617
|
-
`arquivo ausente ou vazio`; the script reports the first one):
|
|
618
|
-
- Present to user: "⚠️ Output from {Agent Name} is incomplete: {motivo}"
|
|
619
|
-
- Options as numbered list:
|
|
620
|
-
1. Accept anyway and continue
|
|
621
|
-
2. Retry step (re-execute the agent)
|
|
622
|
-
3. Abort pipeline
|
|
623
|
-
|
|
624
|
-
4. **If no `output_contract` is defined**, skip this validation entirely (backward compatible).
|
|
625
|
-
|
|
626
|
-
Example `output_contract` in step frontmatter:
|
|
627
|
-
```yaml
|
|
628
|
-
output_contract:
|
|
629
|
-
required_sections:
|
|
630
|
-
- "Fontes Pesquisadas"
|
|
631
|
-
- "Principais Descobertas"
|
|
632
|
-
- "TL;DR"
|
|
633
|
-
min_sections: 3
|
|
634
|
-
```
|
|
439
|
+
Only when the step's frontmatter declares an `output_contract:` field: read
|
|
440
|
+
`_opencrew/core/runner/contrato-de-saida.md` completely and follow it — it adds `--secoes` and `--tldr`
|
|
441
|
+
to the same `conferir` call of the Post-Step Output Validation. Without the field, skip this validation.
|
|
635
442
|
|
|
636
443
|
### Veto Condition Enforcement
|
|
637
444
|
|
|
@@ -679,7 +486,7 @@ When a step has `on_reject: {step-id}` (a review step):
|
|
|
679
486
|
final approval below collects the missing data from the user.
|
|
680
487
|
3. Track the review cycle count: a **cycle** is one pass of the reviewer. The maximum is
|
|
681
488
|
`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
|
|
489
|
+
step frontmatter or its `pipeline.yaml` entry); without it, the one in `crew.yaml`; absent or invalid in both: 3. After each verdict — once the review file passed `conferir` — run `marcar` (`--evento revisao`, see "Run record"). On every rejection, with or
|
|
683
490
|
without a block, send the reviewer's feedback to the writer and go back to the referenced step.
|
|
684
491
|
4. If the last allowed pass also rejects, stop; the status of the last report picks the message, as
|
|
685
492
|
in item 2 — `VERIFICACAO:BLOQUEADA`: the blocks; any other status: the reviewer's feedback, also
|
|
@@ -706,23 +513,6 @@ When a step has `on_reject: {step-id}` (a review step):
|
|
|
706
513
|
and write it into the text before approving. If the user does not have it, do not insist and
|
|
707
514
|
never invent: keep the `[PREENCHER]`, say `Sem problema: deixo [PREENCHER: {o que falta}] no texto. Na entrega você escolhe entre preencher depois e entregar assim mesmo, com ressalva.` and go on.
|
|
708
515
|
|
|
709
|
-
### Step Execution Order (Summary)
|
|
710
|
-
|
|
711
|
-
For reference, the complete execution order for each pipeline step is:
|
|
712
|
-
|
|
713
|
-
```
|
|
714
|
-
0. Agent deselection check (skip step if its agent was deselected)
|
|
715
|
-
0b. Escritório command (passo or checkpoint) — only if it is on
|
|
716
|
-
0c. Entrega (delivery script) — only before the first step that publishes or sends
|
|
717
|
-
1. Pre-Step Input Validation (script gate: `entrada`)
|
|
718
|
-
2. Read step file
|
|
719
|
-
3. Check execution mode and execute (subagent / inline / checkpoint)
|
|
720
|
-
4. Post-Step Output Validation (script gate: `conferir`)
|
|
721
|
-
5. Veto Condition Enforcement
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
Steps 1 and 4 are binary script gates. If either fails, the pipeline does NOT advance — the user is consulted.
|
|
725
|
-
|
|
726
516
|
### Entrega
|
|
727
517
|
|
|
728
518
|
One script turns the approved files into `crews/{name}/output/{run_id}/entrega/` (a folder per channel, text ready to paste, a `LEIA-ME.md`) and copies what is ready to the folder of the project the user chose. Read `_opencrew/core/prompts/entrega.prompt.md` and follow it: how to build `{lista}`, when to add `--vai-publicar`, what to do with `ENTREGA:OK`, `ENTREGA:COM_RESSALVA` and `ENTREGA:INCOMPLETA`, the question about the folder of the project that keeps a copy (asked once per crew) and what to do with a script that did not run.
|
|
@@ -737,112 +527,10 @@ One script turns the approved files into `crews/{name}/output/{run_id}/entrega/`
|
|
|
737
527
|
1. **Entrega** — if the delivery has not run in this run, run it now (see "Entrega" above).
|
|
738
528
|
1b. **Escritório** — if it is on, run `concluir` (see "Escritório" above).
|
|
739
529
|
|
|
740
|
-
2. **
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
Read `crews/{name}/_memory/memories.md` in full. Then identify candidates from this run: **only explicit user feedback** — approvals with comments, rejections with reasons, direct requests ("prefiro X", "não quero Y"). Never infer preferences.
|
|
745
|
-
|
|
746
|
-
For each candidate:
|
|
747
|
-
- If an equivalent memory already exists and is compatible → skip (no duplicate)
|
|
748
|
-
- If an equivalent memory exists but contradicts the new item → replace with the newer version
|
|
749
|
-
- If no equivalent exists → add to the correct semantic section:
|
|
750
|
-
- Writing style choices → `## Estilo de Escrita`
|
|
751
|
-
- Visual/design preferences → `## Design Visual`
|
|
752
|
-
- Content structure choices → `## Estrutura de Conteúdo`
|
|
753
|
-
- Explicit rejections or prohibitions → `## Proibições Explícitas`, in the canonical form
|
|
754
|
-
(`- Nunca usar "termo"` or `- Nunca usar "termo" → usar "outro"`)
|
|
755
|
-
- Crew-specific technical patterns → `## Técnico (específico do crew)`
|
|
756
|
-
|
|
757
|
-
**Never write to `memories.md`:**
|
|
758
|
-
- Runner inferences ("usuário parece preferir X")
|
|
759
|
-
- Run scores, review grades, output file paths, topics from past runs
|
|
760
|
-
|
|
761
|
-
**Technical routing:** For any technical learning (bugs, workarounds, API behavior):
|
|
762
|
-
- If it affects any crew (Playwright bugs, OS rendering quirks, API limits) → write to `_opencrew/best-practices.local/{format}.md` instead of `memories.md` (copy the core file there first if the local one does not exist yet — the core folder is replaced by every `update`; the local one is never touched)
|
|
763
|
-
- If it is specific to this crew's output type or toolchain → add to `## Técnico (específico do crew)` following the dedup rules above
|
|
764
|
-
|
|
765
|
-
After applying all candidates, write the updated `memories.md`.
|
|
766
|
-
|
|
767
|
-
If no candidates are found (the run had no explicit user feedback), skip writing `memories.md` entirely — do not write an unmodified copy. Always proceed to step 2b regardless.
|
|
768
|
-
|
|
769
|
-
### 2b. Prepend to `runs.md` (reverse-chronological log — newest run first)
|
|
770
|
-
|
|
771
|
-
If `crews/{name}/_memory/runs.md` does not exist, create it first with:
|
|
772
|
-
```markdown
|
|
773
|
-
# Run History: {crew-name}
|
|
774
|
-
|
|
775
|
-
| Data | Run ID | Tema | Output | Score | Resultado |
|
|
776
|
-
|------|--------|------|--------|-------|-----------|
|
|
777
|
-
```
|
|
778
|
-
Then proceed to prepend the new row.
|
|
779
|
-
|
|
780
|
-
Read `crews/{name}/_memory/runs.md`. Prepend one new row to the table (immediately after the header row), with:
|
|
781
|
-
- `Data`: the date of this run (the first 10 characters of the `run_id`)
|
|
782
|
-
- `Run ID`: the `run_id` for this execution
|
|
783
|
-
- `Tema`: the topic or user request from this run (1 sentence max)
|
|
784
|
-
- `Output`: brief description of what was generated (e.g., "Carrossel 9 slides", "Thread 7 posts")
|
|
785
|
-
- `Score`: `{approved}/{total}` agent outputs approved without corrections (e.g., `4/5`)
|
|
786
|
-
- `Resultado`: one of — `Aprovado` / `Rejeitado` / `Publicado` / `Abortado`
|
|
787
|
-
|
|
788
|
-
No other data.
|
|
789
|
-
|
|
790
|
-
The `Score` column tracks how many agent outputs were approved by the user without corrections in this run. Count only explicit checkpoint approvals (not "skip" or "continue"). Format: `{approved}/{total checkpoints}` (e.g., `4/5` means 4 of 5 agent outputs were approved as-is).
|
|
791
|
-
|
|
792
|
-
### 2c. Post-Run Reflection (pattern detection)
|
|
793
|
-
|
|
794
|
-
After updating `memories.md` and `runs.md`, run a reflection pass. This is a lightweight analysis — not a full agent execution, just pattern matching on the run's feedback and past memory.
|
|
795
|
-
|
|
796
|
-
1. **Collect this run's corrections**: From checkpoint responses, gather every user rejection or correction. A correction is:
|
|
797
|
-
- A rejected output with a reason ("tom muito informal", "cor não combina", "fonte sem data")
|
|
798
|
-
- A modification request during checkpoint ("muda o título para X", "usa azul em vez de verde")
|
|
799
|
-
|
|
800
|
-
2. **Look for recurrence**: Compare each correction against past runs recorded in `memories.md`:
|
|
801
|
-
- Search `memories.md` for similar patterns (same category, same agent, same type of correction)
|
|
802
|
-
- Count: how many past runs have a correction matching this pattern?
|
|
803
|
-
- A "match" means the same agent + same type of error (e.g., "redator + tom informal", "designer + cores saturadas")
|
|
804
|
-
|
|
805
|
-
3. **Promote to Regra de Ouro**: If the SAME pattern appears in **3 or more runs** (including this one):
|
|
806
|
-
a. Add a new entry under `## Regras de Ouro` in `memories.md`:
|
|
807
|
-
```markdown
|
|
808
|
-
## Regras de Ouro (promovidas após 3+ ocorrências)
|
|
809
|
-
|
|
810
|
-
- **{Agent role}**: SEMPRE {correct behavior}. {Why — grounded in user feedback}.
|
|
811
|
-
(Runs: #{run1}, #{run2}, #{run3})
|
|
812
|
-
```
|
|
813
|
-
Example:
|
|
814
|
-
```markdown
|
|
815
|
-
- **Redator**: SEMPRE verificar se o CTA contém link rastreável antes de finalizar.
|
|
816
|
-
(Runs: #2026-08-01-143022, #2026-08-05-091530, #2026-08-10-160845)
|
|
817
|
-
```
|
|
818
|
-
b. Remove the individual entries from their original sections (`## Estilo de Escrita`, `## Design Visual`, etc.) — the Regra de Ouro replaces them.
|
|
819
|
-
c. Display to the user:
|
|
820
|
-
```
|
|
821
|
-
💡 Regra de Ouro detectada:
|
|
822
|
-
"{correct behavior}" aconteceu 3 vezes.
|
|
823
|
-
Vou aplicar automaticamente a partir de agora.
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
4. **Mark improvement**: If a previously recurring error did NOT happen this run:
|
|
827
|
-
- Add a `✅` marker to the Regra de Ouro entry: `✅ **Redator**: SEMPRE ...`
|
|
828
|
-
- This tracks that the crew is improving — the rule is working.
|
|
829
|
-
|
|
830
|
-
5. **Bail out early**: If this run had zero corrections (all checkpoints approved), skip the entire reflection — nothing to learn.
|
|
831
|
-
|
|
832
|
-
6. **Reflection budget**: Maximum 30 seconds of analysis. If the crew has a long history (>20 past runs), sample the most recent 10 runs for pattern matching. This is a quick scan, not an exhaustive audit.
|
|
833
|
-
|
|
834
|
-
3. Present completion summary:
|
|
835
|
-
```
|
|
836
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
837
|
-
✅ Pipeline complete!
|
|
838
|
-
📁 Delivery: crews/{name}/output/{run_id}/entrega/ — start with LEIA-ME.md
|
|
839
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
840
|
-
|
|
841
|
-
What would you like to do?
|
|
842
|
-
● Run again (new topic)
|
|
843
|
-
○ Edit this content
|
|
844
|
-
○ Back to menu
|
|
845
|
-
```
|
|
530
|
+
2. **Close the run** — read `_opencrew/core/runner/fim-da-execucao.md` completely and follow it, in its
|
|
531
|
+
order: update `memories.md`, close the run with the `fechar` command (the script writes the line of `runs.md`), the post-run reflection and the completion
|
|
532
|
+
summary with the final menu. Never skip it, and never write the memory or the history from what you
|
|
533
|
+
remember of it.
|
|
846
534
|
|
|
847
535
|
## Error Handling
|
|
848
536
|
|
|
@@ -853,7 +541,7 @@ One script turns the approved files into `crews/{name}/output/{run_id}/entrega/`
|
|
|
853
541
|
- If a step file is missing, inform the user and suggest running `/opencrew edit {crew}` to fix.
|
|
854
542
|
- If company.md is empty, stop and redirect to onboarding.
|
|
855
543
|
- Never continue past a checkpoint without user input.
|
|
856
|
-
- When the run is aborted: if the Escritório is on, run `falhar` (see "Escritório" above).
|
|
544
|
+
- When the run is aborted (by the user, by an error, or rejected at the last review cycle): run `fechar` with `abortado` or `rejeitado` (see "Run record") and, if the Escritório is on, run `falhar` (see "Escritório" above). A run that just stopped (the conversation ended) stays open: `/opencrew retomar` finds it.
|
|
857
545
|
|
|
858
546
|
## Pipeline State
|
|
859
547
|
|
|
@@ -868,4 +556,4 @@ Track pipeline state in memory during execution:
|
|
|
868
556
|
- filtered_steps — the ordered steps that will actually run this execution
|
|
869
557
|
- missing_dependency — true if the user knowingly ran with a broken dependency
|
|
870
558
|
|
|
871
|
-
This state
|
|
559
|
+
This state lives in memory; what `/opencrew retomar` needs is on disk, in the run record (see "Run record").
|
|
@@ -6,15 +6,16 @@ import { ACOES } from './nucleo.mjs';
|
|
|
6
6
|
export const USO = 'Uso: node _opencrew/core/scripts/caminho.mjs <crew> <ação> --run <id> [opções]';
|
|
7
7
|
|
|
8
8
|
const LISTA = ACOES.join(', ');
|
|
9
|
-
const OPCAO = /^--(run|arquivo|secoes|tldr)(?:=(.*))?$/s;
|
|
10
|
-
|
|
9
|
+
const OPCAO = /^--(run|arquivo|secoes|tldr|tema|passos|passo)(?:=(.*))?$/s;
|
|
10
|
+
/** O nome de uma execução: letras, dígitos, ponto, sublinhado e hífen (nunca só pontos). */
|
|
11
|
+
export const RUN = /^(?!\.+$)[A-Za-z0-9._-]+$/;
|
|
11
12
|
const INTEIRO = /^[1-9]\d{0,8}$/;
|
|
12
13
|
|
|
13
14
|
/** Texto que veio da linha de comando e volta numa mensagem: uma linha só, até 200 caracteres. */
|
|
14
15
|
export const limpar = (valor) => String(valor).replace(/\s+/g, ' ').trim().slice(0, 200);
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
* `argv` → `{ crew, acao, run, arquivo, secoes, tldr }`. Os dois primeiros argumentos soltos são
|
|
18
|
+
* `argv` → `{ crew, acao, run, arquivo, secoes, tldr, tema, passos, passo }`. Os dois primeiros argumentos soltos são
|
|
18
19
|
* a crew e a ação. Opção vale como `--nome valor` e `--nome=valor`; `--tldr` não leva valor.
|
|
19
20
|
* Opção ausente fica `undefined`.
|
|
20
21
|
*/
|
|
@@ -37,7 +38,7 @@ export function lerArgs(argv) {
|
|
|
37
38
|
* caminho já resolvido: é a única ação que não precisa de `--run`.
|
|
38
39
|
* @returns {string|null} o motivo em PT-BR, ou `null`
|
|
39
40
|
*/
|
|
40
|
-
export function erroDeArgumentos({ crew, acao, run, arquivo, secoes }) {
|
|
41
|
+
export function erroDeArgumentos({ crew, acao, run, arquivo, secoes, passos, passo }) {
|
|
41
42
|
if (!crew) return 'Falta o nome da crew.';
|
|
42
43
|
if (!acao) return `Falta a ação. Ações: ${LISTA}.`;
|
|
43
44
|
if (!ACOES.includes(acao)) return `Ação desconhecida: ${limpar(acao)}. Ações: ${LISTA}.`;
|
|
@@ -47,5 +48,7 @@ export function erroDeArgumentos({ crew, acao, run, arquivo, secoes }) {
|
|
|
47
48
|
if (run !== undefined && !RUN.test(run)) return 'O --run só aceita letras, dígitos, ponto, sublinhado e hífen.';
|
|
48
49
|
if (acao !== 'pasta' && !arquivo) return MSG.faltaOpcao('--arquivo');
|
|
49
50
|
if (secoes !== undefined && !INTEIRO.test(secoes)) return 'O --secoes é um número inteiro a partir de 1.';
|
|
51
|
+
if (passos !== undefined && !INTEIRO.test(passos)) return 'O --passos é um número inteiro a partir de 1.';
|
|
52
|
+
if (passo !== undefined && !INTEIRO.test(passo)) return 'O --passo é um número inteiro a partir de 1.';
|
|
50
53
|
return null;
|
|
51
54
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Onde fica a crew de um comando (`caminho.mjs`, `execucao.mjs`): uma pasta direta de `crews/`.
|
|
2
|
+
// Spec: fase-r3-runner-em-uso-real.md, §3 (repositório do OpenCrew).
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { MSG, dentroDoProjeto } from '../comum.mjs';
|
|
5
|
+
import { limpar } from './argumentos.mjs';
|
|
6
|
+
import { ehPasta } from './disco.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} raiz a pasta do projeto · @param {string} escrito o nome da crew (`crews/<nome>` também vale)
|
|
10
|
+
* @returns {{ erro: string } | { crew: string }} o erro de uso, ou o nome da pasta da crew
|
|
11
|
+
*/
|
|
12
|
+
export function acharCrew(raiz, escrito) {
|
|
13
|
+
if (!ehPasta(path.join(raiz, '_opencrew'))) return { erro: MSG.semRaiz };
|
|
14
|
+
const base = path.resolve(raiz, 'crews');
|
|
15
|
+
const nome = escrito.replace(/^crews[\\/]+/, '');
|
|
16
|
+
if (!dentroDoProjeto(base, nome)) return { erro: MSG.foraDoProjeto(limpar(escrito)) };
|
|
17
|
+
const pasta = path.resolve(base, nome);
|
|
18
|
+
if (path.dirname(pasta) !== base || !ehPasta(pasta)) return { erro: MSG.crewNaoEncontrada(limpar(escrito)) };
|
|
19
|
+
return { crew: path.basename(pasta) };
|
|
20
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// O que o `caminho.mjs` faz no disco: lê nomes de pastas, confere se um arquivo tem conteúdo, lê
|
|
2
|
-
// um arquivo e cria pastas. Nunca cria, altera nem apaga arquivo
|
|
2
|
+
// um arquivo e cria pastas. Nunca cria, altera nem apaga arquivo (o registro da execução é gravado
|
|
3
|
+
// por `execucao/registro.mjs`).
|
|
3
4
|
// Spec: fase-r3-runner-em-uso-real.md, regra 6 (repositório do OpenCrew).
|
|
4
5
|
import { mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
5
6
|
|
|
@@ -32,5 +33,5 @@ export function temConteudo(arquivo) {
|
|
|
32
33
|
|
|
33
34
|
export const lerTexto = (arquivo) => readFileSync(arquivo, 'utf8');
|
|
34
35
|
|
|
35
|
-
/** Cria a pasta com as pastas-mãe; pasta que já existe não é erro. */
|
|
36
|
-
export const criarPasta = (pasta) =>
|
|
36
|
+
/** Cria a pasta com as pastas-mãe; pasta que já existe não é erro. @returns {boolean} criou alguma pasta? */
|
|
37
|
+
export const criarPasta = (pasta) => mkdirSync(pasta, { recursive: true }) !== undefined;
|