@jaimevalasek/aioson 1.21.5 → 1.21.6

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 (50) hide show
  1. package/docs/en/1-understand/ecosystem-map.md +2 -2
  2. package/docs/en/1-understand/glossary.md +1 -1
  3. package/docs/en/2-start/initial-decisions.md +1 -1
  4. package/docs/en/3-recipes/README.md +1 -1
  5. package/docs/en/3-recipes/full-feature-with-sheldon.md +2 -2
  6. package/docs/en/5-reference/cli-reference.md +5 -5
  7. package/docs/en/README.md +1 -1
  8. package/docs/pt/1-entender/glossario.md +1 -1
  9. package/docs/pt/1-entender/mapa-do-ecossistema.md +2 -2
  10. package/docs/pt/2-comecar/decisoes-iniciais.md +1 -1
  11. package/docs/pt/3-receitas/README.md +1 -1
  12. package/docs/pt/3-receitas/feature-completa-com-sheldon.md +2 -2
  13. package/docs/pt/5-referencia/comandos-cli.md +4 -4
  14. package/docs/pt/README.md +1 -1
  15. package/package.json +1 -1
  16. package/src/commands/agents.js +48 -12
  17. package/src/commands/workflow-next.js +119 -27
  18. package/src/commands/workflow-plan.js +5 -5
  19. package/src/commands/workflow-status.js +14 -5
  20. package/src/constants.js +36 -19
  21. package/src/dossier/schema.js +5 -4
  22. package/src/handoff-contract.js +18 -8
  23. package/src/i18n/messages/en.js +2 -2
  24. package/src/i18n/messages/es.js +2 -2
  25. package/src/i18n/messages/fr.js +2 -2
  26. package/src/i18n/messages/pt-BR.js +2 -2
  27. package/src/install-wizard.js +1 -1
  28. package/src/session-handoff.js +50 -20
  29. package/template/.aioson/agents/analyst.md +4 -4
  30. package/template/.aioson/agents/dev.md +7 -3
  31. package/template/.aioson/agents/discover.md +1 -1
  32. package/template/.aioson/agents/manifests/scope-check.manifest.json +61 -0
  33. package/template/.aioson/agents/neo.md +2 -2
  34. package/template/.aioson/agents/pentester.md +3 -1
  35. package/template/.aioson/agents/product.md +3 -3
  36. package/template/.aioson/agents/qa.md +5 -4
  37. package/template/.aioson/agents/scope-check.md +164 -0
  38. package/template/.aioson/agents/sheldon.md +1 -1
  39. package/template/.aioson/agents/tester.md +5 -3
  40. package/template/.aioson/config.md +16 -7
  41. package/template/.aioson/docs/product/prd-contract.md +1 -1
  42. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +5 -4
  43. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +1 -1
  44. package/template/.aioson/skills/process/prompt-sharpener/SKILL.md +116 -0
  45. package/template/.aioson/skills/process/prompt-sharpener/agents/openai.yaml +4 -0
  46. package/template/.aioson/skills/process/prompt-sharpener/references/prompt-diagnostics.md +51 -0
  47. package/template/.claude/commands/aioson/agent/scope-check.md +20 -0
  48. package/template/AGENTS.md +23 -12
  49. package/template/CLAUDE.md +4 -3
  50. package/template/OPENCODE.md +3 -2
@@ -71,8 +71,8 @@
71
71
  The default order depends on the classification:
72
72
 
73
73
  **MICRO:** `@setup → @product (optional) → @dev`
74
- **SMALL:** `@setup → @product → @sheldon (optional) → @analyst → @architect → @dev → @qa`
75
- **MEDIUM:** `@setup → @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa`
74
+ **SMALL:** `@setup → @product → @sheldon (optional) → @analyst → @scope-check → @architect → @dev → @qa`
75
+ **MEDIUM:** `@setup → @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa`
76
76
 
77
77
  > **Why does `@sheldon` appear so early?** It is the **PRD quality guardian** — it runs *between* `@product` and `@analyst` to detect gaps, validate technical assumptions with web research, and decide between enriching the PRD in-place or creating a phased plan in `.aioson/plans/{slug}/`. Can be invoked N times on the same PRD. Skipping this step on serious features is expensive later.
78
78
 
@@ -73,7 +73,7 @@ Terms in alphabetical order. Each entry has a **short definition** + **concrete
73
73
 
74
74
  **How it works:**
75
75
  - 0–1 points → **MICRO** (`@setup → @product → @dev`)
76
- - 2–3 points → **SMALL** (`@setup → @product → @analyst → @architect → @dev → @qa`)
76
+ - 2–3 points → **SMALL** (`@setup → @product → @analyst → @scope-check → @architect → @dev → @qa`)
77
77
  - 4–6 points → **MEDIUM** (full workflow, all gates, all artifacts)
78
78
 
79
79
  **Where it appears:** `classification:` in the `project.context.md` frontmatter.
@@ -41,7 +41,7 @@ The sum of three factors (each worth 0, 1, or 2 points):
41
41
  - Static portfolio page
42
42
  - Mini API with 3 endpoints
43
43
 
44
- #### SMALL — `@setup → @product → @analyst → @architect → @dev → @qa`
44
+ #### SMALL — `@setup → @product → @analyst → @scope-check → @architect → @dev → @qa`
45
45
 
46
46
  - For: most real apps.
47
47
  - Full discovery+development+QA cycle.
@@ -8,7 +8,7 @@ These three trails show **how features reach development** in AIOSON. You almost
8
8
 
9
9
  | Trail | When to use | Key agents |
10
10
  |---|---|---|
11
- | **[Full feature with @sheldon](./full-feature-with-sheldon.md)** | You have a PRD in mind and want the complete canonical trail (most used) | @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa |
11
+ | **[Full feature with @sheldon](./full-feature-with-sheldon.md)** | You have a PRD in mind and want the complete canonical trail (most used) | @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa |
12
12
  | [From idea to PRD via @briefing](./from-idea-to-prd-via-briefing.md) | Your idea is still vague, several loose notes | @briefing → @product |
13
13
  | [External plans for @product](./external-plans-for-product.md) *(coming soon)* | You already planned in another chat (ChatGPT, Claude.io Web) | @product (reads `/plans/`) |
14
14
 
@@ -10,7 +10,7 @@
10
10
  ## The trail in one line
11
11
 
12
12
  ```
13
- /aioson:agent:product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev
13
+ /aioson:agent:product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev
14
14
 
15
15
  (@qa ↔ @dev) ← autonomous loop
16
16
 
@@ -299,7 +299,7 @@ Six months from now, anyone (or any AI) reads these files and understands **ever
299
299
  `@product → @dev → @qa`. Skip `@sheldon`, `@analyst`, `@architect`, `@ux-ui`, `@pm`, `@orchestrator`. The Constitution Article II (*Right-Sized Process*) protects you from unnecessary ceremony.
300
300
 
301
301
  ### SMALL without UI
302
- `@product → @sheldon → @analyst → @architect → @dev → @qa`. Skip `@ux-ui`, `@pm`, `@orchestrator`.
302
+ `@product → @sheldon → @analyst → @scope-check → @architect → @dev → @qa`. Skip `@ux-ui`, `@pm`, `@orchestrator`.
303
303
 
304
304
  ### Full MEDIUM
305
305
  The complete trail above.
@@ -255,7 +255,7 @@ aioson agent:prompt dev --tool=opencode --json
255
255
  ```
256
256
 
257
257
  **Arguments:**
258
- - `<agent>` — agent id: `setup`, `product`, `analyst`, `architect`, `ux-ui`, `pm`, `dev`, `qa`, `orchestrator`.
258
+ - `<agent>` — agent id: `setup`, `product`, `analyst`, `scope-check`, `architect`, `ux-ui`, `pm`, `dev`, `qa`, `orchestrator`.
259
259
 
260
260
  **Options:**
261
261
  - `--tool=codex|claude|opencode` — formats the prompt for the target CLI. Default: `codex`.
@@ -302,18 +302,18 @@ Notes:
302
302
 
303
303
  **Sequences by classification:**
304
304
  - `MICRO`: `@setup → @product (optional) → @dev`
305
- - `SMALL`: `@setup → @product → @analyst → @architect → @dev → @qa`
306
- - `MEDIUM`: `@setup → @product → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa`
305
+ - `SMALL`: `@setup → @product → @analyst → @scope-check → @architect → @dev → @qa`
306
+ - `MEDIUM`: `@setup → @product → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa`
307
307
 
308
308
  **Feature development workflow (after initial setup):**
309
309
 
310
310
  Once the project is set up, each new feature follows a shorter sequence — no `@setup` required:
311
311
 
312
312
  ```
313
- /aioson:agent:product → @analyst → @dev → @qa
313
+ /aioson:agent:product → @analyst → @scope-check → @dev → @qa
314
314
  ```
315
315
 
316
- `@product` creates a feature-scoped `prd-{slug}.md` and registers the feature in `features.md`. `@analyst` produces `requirements-{slug}.md` and `spec-{slug}.md`. `@dev` reads the feature spec. `@qa` closes the feature by running `feature:close --verdict=PASS`, which updates `spec-{slug}.md` with a QA sign-off, marks it `done` in `features.md`, and automatically archives all feature artefacts to `.aioson/context/done/{slug}/`.
316
+ `@product` creates a feature-scoped `prd-{slug}.md` and registers the feature in `features.md`. `@analyst` produces `requirements-{slug}.md` and `spec-{slug}.md`. `@scope-check` compares intent against the planned implementation before coding. `@dev` reads the feature spec. `@qa` closes the feature by running `feature:close --verdict=PASS`, which updates `spec-{slug}.md` with a QA sign-off, marks it `done` in `features.md`, and automatically archives all feature artefacts to `.aioson/context/done/{slug}/`.
317
317
 
318
318
  The `SMALL` and MEDIUM outputs include a note reminding you of this sequence.
319
319
 
package/docs/en/README.md CHANGED
@@ -23,7 +23,7 @@ This is the entry door to the English documentation. It is not an alphabetical i
23
23
  ### I want a recipe ready for my case
24
24
 
25
25
  **Canonical trails — how features reach the dev:**
26
- 1. **[Full feature with @sheldon](./3-recipes/full-feature-with-sheldon.md)** — the main trail: `@product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa` (with optional gates from `@tester` and `@pentester`)
26
+ 1. **[Full feature with @sheldon](./3-recipes/full-feature-with-sheldon.md)** — the main trail: `@product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa` (with optional gates from `@tester` and `@pentester`)
27
27
  2. [From idea to PRD via @briefing](./3-recipes/from-idea-to-prd-via-briefing.md) — when the idea is still vague
28
28
  3. [Continuity between sessions](./3-recipes/continuity-between-sessions.md) — feature dossier, dev-resume, drift detection
29
29
 
@@ -73,7 +73,7 @@ Termos em ordem alfabética. Cada um tem **definição curta** + **exemplo concr
73
73
 
74
74
  **Como funciona:**
75
75
  - 0–1 ponto → **MICRO** (`@setup → @product → @dev`)
76
- - 2–3 pontos → **SMALL** (`@setup → @product → @analyst → @architect → @dev → @qa`)
76
+ - 2–3 pontos → **SMALL** (`@setup → @product → @analyst → @scope-check → @architect → @dev → @qa`)
77
77
  - 4–6 pontos → **MEDIUM** (workflow completo, todos os gates, todos os artefatos)
78
78
 
79
79
  **Onde aparece:** `classification:` no frontmatter do `project.context.md`.
@@ -71,8 +71,8 @@
71
71
  A ordem padrão depende da classificação:
72
72
 
73
73
  **MICRO:** `@setup → @product (opcional) → @dev`
74
- **SMALL:** `@setup → @product → @sheldon (opcional) → @analyst → @architect → @dev → @qa`
75
- **MEDIUM:** `@setup → @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa`
74
+ **SMALL:** `@setup → @product → @sheldon (opcional) → @analyst → @scope-check → @architect → @dev → @qa`
75
+ **MEDIUM:** `@setup → @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa`
76
76
 
77
77
  > **Por que `@sheldon` aparece tão cedo?** Ele é o **PRD quality guardian** — roda *entre* `@product` e `@analyst` para detectar gaps, validar premissas técnicas com pesquisa web, e decidir entre enriquecer o PRD in-place ou criar um phased plan em `.aioson/plans/{slug}/`. Pode ser invocado N vezes no mesmo PRD. Pular essa etapa em features sérias custa caro lá na frente.
78
78
 
@@ -41,7 +41,7 @@ Soma de três fatores (cada um vale 0, 1 ou 2 pontos):
41
41
  - Página estática de portfólio
42
42
  - Mini-API de 3 endpoints
43
43
 
44
- #### SMALL — `@setup → @product → @analyst → @architect → @dev → @qa`
44
+ #### SMALL — `@setup → @product → @analyst → @scope-check → @architect → @dev → @qa`
45
45
 
46
46
  - Para: a maioria dos apps reais.
47
47
  - Tem o ciclo completo de discovery+desenvolvimento+QA.
@@ -8,7 +8,7 @@ Estas três trilhas mostram **como features chegam ao desenvolvimento** no AIOSO
8
8
 
9
9
  | Trilha | Quando usar | Agentes-chave |
10
10
  |---|---|---|
11
- | **[Feature completa com @sheldon](./feature-completa-com-sheldon.md)** | Você tem PRD em mente e quer a trilha canônica completa (a mais usada) | @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa |
11
+ | **[Feature completa com @sheldon](./feature-completa-com-sheldon.md)** | Você tem PRD em mente e quer a trilha canônica completa (a mais usada) | @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa |
12
12
  | [Da ideia ao PRD via @briefing](./da-ideia-ao-prd-via-briefing.md) | Sua ideia ainda é vaga, várias anotações soltas | @briefing → @product |
13
13
  | [Plans externos para @product](./plans-externos-para-product.md) | Você já planejou em outro chat (ChatGPT, Claude.io Web) | @product (lê `/plans/`) |
14
14
 
@@ -10,7 +10,7 @@
10
10
  ## A trilha em uma linha
11
11
 
12
12
  ```
13
- @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev
13
+ @product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev
14
14
 
15
15
  (@qa ↔ @dev) ← ciclo autônomo
16
16
 
@@ -299,7 +299,7 @@ Daqui a 6 meses, qualquer pessoa (ou IA) lê esses arquivos e entende **tudo**:
299
299
  `@product → @dev → @qa`. Pule `@sheldon`, `@analyst`, `@architect`, `@ux-ui`, `@pm`, `@orchestrator`. A Constitution Article II (*Right-Sized Process*) protege você de cerimônia desnecessária.
300
300
 
301
301
  ### SMALL sem UI
302
- `@product → @sheldon → @analyst → @architect → @dev → @qa`. Pule `@ux-ui`, `@pm`, `@orchestrator`.
302
+ `@product → @sheldon → @analyst → @scope-check → @architect → @dev → @qa`. Pule `@ux-ui`, `@pm`, `@orchestrator`.
303
303
 
304
304
  ### MEDIUM puro
305
305
  A trilha completa acima.
@@ -521,8 +521,8 @@ Importante:
521
521
  - `scan:project` sozinho nao gera `discovery.md`
522
522
  - `scan:project` nunca gera `architecture.md`
523
523
  - se `discovery.md` e `skeleton-system.md` ja existirem e voce rodar com `--with-llm`, o scanner agora entra em modo de atualizacao por padrao: usa os arquivos atuais como memoria base, gera a nova versao consolidada e cria backup automatico em `.aioson/backups/` antes de sobrescrever
524
- - em projetos SMALL brownfield, o fluxo tipico depois do scan completo e `@analyst` -> `@architect` -> `@dev`
525
- - sem API LLM configurada, o fluxo local tambem e valido: `scan:project --folder=...` -> `@analyst` no seu Codex/Claude -> `@architect` -> `@dev`
524
+ - em projetos SMALL brownfield, o fluxo tipico depois do scan completo e `@analyst` -> `@scope-check` -> `@architect` -> `@dev`
525
+ - sem API LLM configurada, o fluxo local tambem e valido: `scan:project --folder=...` -> `@analyst` no seu Codex/Claude -> `@scope-check` -> `@architect` -> `@dev`
526
526
 
527
527
  O parâmetro `--folder` agora é obrigatório. Ele define quais pastas do projeto devem ganhar um mapa completo com pastas e arquivos. Você pode informar uma pasta ou várias separadas por vírgula.
528
528
 
@@ -574,8 +574,8 @@ Quando usar cada modo:
574
574
 
575
575
  Fluxos recomendados:
576
576
 
577
- - **Com API no aioson:** `scan:project --folder=src --with-llm --provider=...` -> `@analyst` -> `@architect` -> `@dev`
578
- - **Sem API no aioson:** `scan:project --folder=src` -> abrir seu AI CLI -> `@analyst` -> `@architect` -> `@dev`
577
+ - **Com API no aioson:** `scan:project --folder=src --with-llm --provider=...` -> `@analyst` -> `@scope-check` -> `@architect` -> `@dev`
578
+ - **Sem API no aioson:** `scan:project --folder=src` -> abrir seu AI CLI -> `@analyst` -> `@scope-check` -> `@architect` -> `@dev`
579
579
  - **Com contexto mínimo para tarefa específica:** `scan:project --folder=src` -> `context:pack --agent=dev --goal="..." --module=src`
580
580
  - Se o seu cliente nao entender `@analyst`, gere um prompt pronto com `aioson agent:prompt analyst --tool=codex` ou troque `--tool` para o cliente correto
581
581
 
package/docs/pt/README.md CHANGED
@@ -22,7 +22,7 @@ Esta é a porta de entrada da documentação em português. Não é um índice a
22
22
  ### Quero uma receita pronta para o meu caso
23
23
 
24
24
  **Trilhas canônicas — como features chegam ao dev:**
25
- 1. **[Feature completa com @sheldon](./3-receitas/feature-completa-com-sheldon.md)** — a trilha principal: `@product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @dev → @qa` (com gates opcionais de `@tester` e `@pentester`)
25
+ 1. **[Feature completa com @sheldon](./3-receitas/feature-completa-com-sheldon.md)** — a trilha principal: `@product → @sheldon → @analyst → @architect → @ux-ui → @pm → @orchestrator → @scope-check → @dev → @qa` (com gates opcionais de `@tester` e `@pentester`)
26
26
  2. [Da ideia ao PRD via @briefing](./3-receitas/da-ideia-ao-prd-via-briefing.md) — quando a ideia ainda é vaga
27
27
  3. [Plans externos para @product](./3-receitas/plans-externos-para-product.md) — quando você planejou em ChatGPT/Claude.io e quer trazer
28
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaimevalasek/aioson",
3
- "version": "1.21.5",
3
+ "version": "1.21.6",
4
4
  "description": "AI operating framework for hyper-personalized software.",
5
5
  "keywords": [
6
6
  "ai",
@@ -20,17 +20,51 @@ const { readAutonomyProtocol, resolveEffectiveMode } = require('../autonomy-poli
20
20
  const { readAgentManifest, buildAgentCapabilitySummary } = require('../agent-manifests');
21
21
  const { emitSecurityRuntimeEvent } = require('../lib/security/runtime-events');
22
22
 
23
- const WORKFLOW_AGENT_IDS = new Set([
24
- 'setup',
25
- 'product',
26
- 'analyst',
27
- 'architect',
23
+ const WORKFLOW_AGENT_IDS = new Set([
24
+ 'setup',
25
+ 'product',
26
+ 'analyst',
27
+ 'scope-check',
28
+ 'architect',
28
29
  'ux-ui',
29
30
  'pm',
30
31
  'orchestrator',
31
32
  'dev',
32
- 'qa'
33
- ]);
33
+ 'qa'
34
+ ]);
35
+ const SCOPE_CHECK_MODES = new Set(['pre-dev', 'post-dev', 'post-fix', 'final']);
36
+
37
+ function normalizeScopeCheckMode(input) {
38
+ const mode = String(input || '').trim().toLowerCase();
39
+ return SCOPE_CHECK_MODES.has(mode) ? mode : null;
40
+ }
41
+
42
+ function getScopeCheckModeOption(options = {}) {
43
+ return normalizeScopeCheckMode(
44
+ options.scopeMode ||
45
+ options['scope-mode'] ||
46
+ options.checkMode ||
47
+ options['check-mode'] ||
48
+ options.mode
49
+ );
50
+ }
51
+
52
+ function buildScopeCheckActivationContext(options = {}) {
53
+ const mode = getScopeCheckModeOption(options) || 'pre-dev';
54
+ const lines = [`Scope-check mode: ${mode}.`];
55
+ const featureSlug = String(options.feature || options.slug || '').trim();
56
+ if (featureSlug) lines.push(`Feature slug: ${featureSlug}.`);
57
+ if (mode === 'pre-dev') {
58
+ lines.push('Compare user intent against planning artifacts before implementation.');
59
+ } else if (mode === 'post-dev') {
60
+ lines.push('Compare the approved planning artifacts against the actual implementation diff and changed files before QA.');
61
+ } else if (mode === 'post-fix') {
62
+ lines.push('Compare approved scope, QA/tester/pentester findings, and correction diff; confirm the fix did not change product intent.');
63
+ } else if (mode === 'final') {
64
+ lines.push('Reconcile intent, plan, delivered behavior, and remaining exclusions before close/commit/release.');
65
+ }
66
+ return lines.join('\n');
67
+ }
34
68
 
35
69
  function normalizePentesterTargetMode(input) {
36
70
  const mode = String(input || '').trim().toLowerCase();
@@ -173,10 +207,12 @@ async function runAgentPrompt({ args, options, logger, t }) {
173
207
 
174
208
  if (!prompt) {
175
209
  instructionPath = await resolveExistingInstructionPath(targetDir, promptAgent, locale);
176
- if (promptAgent.id === 'pentester') {
177
- pentesterTargetMode = normalizePentesterTargetMode(options.mode);
178
- activationContext = buildPentesterActivationContext(options, t);
179
- }
210
+ if (promptAgent.id === 'pentester') {
211
+ pentesterTargetMode = normalizePentesterTargetMode(options.mode);
212
+ activationContext = buildPentesterActivationContext(options, t);
213
+ } else if (promptAgent.id === 'scope-check') {
214
+ activationContext = buildScopeCheckActivationContext(options);
215
+ }
180
216
  const autonomyProtocol = await readAutonomyProtocol(targetDir);
181
217
  const manifest = await readAgentManifest(targetDir, promptAgent.id);
182
218
  effectiveMode = resolveEffectiveMode({
@@ -184,7 +220,7 @@ async function runAgentPrompt({ args, options, logger, t }) {
184
220
  tool,
185
221
  agentId: promptAgent.id,
186
222
  manifest,
187
- requestedMode: options.mode || null
223
+ requestedMode: promptAgent.id === 'scope-check' && getScopeCheckModeOption(options) ? null : options.mode || null
188
224
  });
189
225
  prompt = buildAgentPrompt(promptAgent, tool, {
190
226
  instructionPath,
@@ -26,15 +26,16 @@ const { emitDossierEvent } = require('../lib/dossier-telemetry');
26
26
 
27
27
  const STATE_RELATIVE_PATH = '.aioson/context/workflow.state.json';
28
28
  const CONFIG_RELATIVE_PATH = '.aioson/context/workflow.config.json';
29
- const EVENTS_RELATIVE_PATH = '.aioson/context/workflow.events.jsonl';
29
+ const EVENTS_RELATIVE_PATH = '.aioson/context/workflow.events.jsonl';
30
+ const SCOPE_CHECK_MODES = new Set(['pre-dev', 'post-dev', 'post-fix', 'final']);
30
31
 
31
32
  const DEFAULT_FEATURE_WORKFLOW_BY_CLASSIFICATION = {
32
33
  MICRO: ['product', 'dev', 'qa'],
33
- SMALL: ['product', 'analyst', 'architect', 'discovery-design-doc', 'dev', 'qa'],
34
- MEDIUM: ['product', 'analyst', 'architect', 'discovery-design-doc', 'dev', 'pentester', 'qa']
34
+ SMALL: ['product', 'analyst', 'scope-check', 'architect', 'discovery-design-doc', 'dev', 'qa'],
35
+ MEDIUM: ['product', 'analyst', 'architect', 'discovery-design-doc', 'scope-check', 'dev', 'pentester', 'qa']
35
36
  };
36
37
 
37
- function normalizeAgentName(input) {
38
+ function normalizeAgentName(input) {
38
39
  return String(input || '')
39
40
  .trim()
40
41
  .toLowerCase()
@@ -52,8 +53,8 @@ function buildDefaultWorkflowConfig() {
52
53
  version: 1,
53
54
  project: {
54
55
  MICRO: ['setup', 'dev'],
55
- SMALL: ['setup', 'product', 'analyst', 'architect', 'discovery-design-doc', 'dev', 'qa'],
56
- MEDIUM: ['setup', 'product', 'analyst', 'architect', 'discovery-design-doc', 'ux-ui', 'pm', 'orchestrator', 'dev', 'qa']
56
+ SMALL: ['setup', 'product', 'analyst', 'scope-check', 'architect', 'discovery-design-doc', 'dev', 'qa'],
57
+ MEDIUM: ['setup', 'product', 'analyst', 'architect', 'discovery-design-doc', 'ux-ui', 'pm', 'orchestrator', 'scope-check', 'dev', 'qa']
57
58
  },
58
59
  feature: DEFAULT_FEATURE_WORKFLOW_BY_CLASSIFICATION,
59
60
  rules: {
@@ -82,6 +83,21 @@ function parseFeaturesMarkdown(markdown) {
82
83
  .filter((row) => !/^-+$/ .test(row.slug));
83
84
  }
84
85
 
86
+ function normalizeScopeCheckMode(input) {
87
+ const mode = String(input || '').trim().toLowerCase();
88
+ return SCOPE_CHECK_MODES.has(mode) ? mode : null;
89
+ }
90
+
91
+ function getScopeCheckModeOption(options = {}) {
92
+ return normalizeScopeCheckMode(
93
+ options.scopeMode ||
94
+ options['scope-mode'] ||
95
+ options.checkMode ||
96
+ options['check-mode'] ||
97
+ options.mode
98
+ );
99
+ }
100
+
85
101
  function chooseActiveFeature(features, preferredSlug = null) {
86
102
  const activeFeatures = (features || []).filter((feature) => feature.status === 'in_progress');
87
103
  if (preferredSlug) {
@@ -253,18 +269,25 @@ async function validateStageArtifacts(targetDir, state, stage) {
253
269
  return await exists(path.join(base, 'prd.md'));
254
270
  }
255
271
 
256
- if (stage === 'analyst') {
257
- if (state.mode === 'feature' && slug) {
258
- const requirements = path.join(base, `requirements-${slug}.md`);
259
- const spec = path.join(base, `spec-${slug}.md`);
260
- return (await exists(requirements)) && (await exists(spec));
261
- }
262
- return await exists(path.join(base, 'discovery.md'));
263
- }
264
-
265
- if (stage === 'architect') {
266
- return await exists(path.join(base, 'architecture.md'));
267
- }
272
+ if (stage === 'analyst') {
273
+ if (state.mode === 'feature' && slug) {
274
+ const requirements = path.join(base, `requirements-${slug}.md`);
275
+ const spec = path.join(base, `spec-${slug}.md`);
276
+ return (await exists(requirements)) && (await exists(spec));
277
+ }
278
+ return await exists(path.join(base, 'discovery.md'));
279
+ }
280
+
281
+ if (stage === 'scope-check') {
282
+ if (state.mode === 'feature' && slug) {
283
+ return await exists(path.join(base, `scope-check-${slug}.md`));
284
+ }
285
+ return await exists(path.join(base, 'scope-check.md'));
286
+ }
287
+
288
+ if (stage === 'architect') {
289
+ return await exists(path.join(base, 'architecture.md'));
290
+ }
268
291
 
269
292
  if (stage === 'ux-ui') {
270
293
  return await exists(path.join(base, 'ui-spec.md'));
@@ -403,11 +426,11 @@ function reconcileWorkflowState(state) {
403
426
  };
404
427
  }
405
428
 
406
- function isInferableStage(stage) {
407
- return ['setup', 'product', 'analyst', 'architect', 'ux-ui', 'orchestrator'].includes(
408
- normalizeAgentName(stage)
409
- );
410
- }
429
+ function isInferableStage(stage) {
430
+ return ['setup', 'product', 'analyst', 'scope-check', 'architect', 'ux-ui', 'orchestrator'].includes(
431
+ normalizeAgentName(stage)
432
+ );
433
+ }
411
434
 
412
435
  function isSecurityGateBlocked(contractCheck, state, stageName) {
413
436
  if (normalizeAgentName(stageName) !== 'qa' || state.mode !== 'feature' || !state.featureSlug) {
@@ -905,6 +928,36 @@ function normalizeContextDependency(relPath) {
905
928
  }
906
929
 
907
930
  async function resolveStageDependencies(targetDir, state, stageName, agent) {
931
+ if (stageName === 'scope-check') {
932
+ const contextDir = path.join(targetDir, '.aioson', 'context');
933
+ const slug = state.featureSlug;
934
+ const candidates = [
935
+ 'project.context.md',
936
+ 'features.md',
937
+ slug ? `prd-${slug}.md` : 'prd.md',
938
+ slug ? `requirements-${slug}.md` : 'discovery.md',
939
+ slug ? `spec-${slug}.md` : 'spec.md',
940
+ slug ? `sheldon-enrichment-${slug}.md` : 'sheldon-enrichment.md',
941
+ 'architecture.md',
942
+ slug ? `design-doc-${slug}.md` : null,
943
+ slug ? `readiness-${slug}.md` : null,
944
+ 'design-doc.md',
945
+ 'readiness.md',
946
+ 'ui-spec.md',
947
+ slug ? `implementation-plan-${slug}.md` : 'implementation-plan.md',
948
+ 'dev-state.md',
949
+ 'last-handoff.json',
950
+ 'project-pulse.md'
951
+ ].filter(Boolean);
952
+ const existing = [];
953
+ for (const candidate of candidates) {
954
+ if (await exists(path.join(contextDir, candidate))) {
955
+ existing.push(normalizeContextDependency(candidate));
956
+ }
957
+ }
958
+ return existing.length > 0 ? existing : agent.dependsOn;
959
+ }
960
+
908
961
  if (stageName === 'discovery-design-doc') {
909
962
  const contextDir = path.join(targetDir, '.aioson', 'context');
910
963
  const slug = state.featureSlug;
@@ -956,6 +1009,8 @@ async function resolveStageDependencies(targetDir, state, stageName, agent) {
956
1009
  `readiness-${slug}.md`,
957
1010
  'design-doc.md',
958
1011
  'readiness.md',
1012
+ `scope-check-${slug}.md`,
1013
+ 'scope-check.md',
959
1014
  `implementation-plan-${slug}.md`
960
1015
  ];
961
1016
  const existing = [];
@@ -967,7 +1022,41 @@ async function resolveStageDependencies(targetDir, state, stageName, agent) {
967
1022
  return existing.length > 0 ? existing : agent.dependsOn;
968
1023
  }
969
1024
 
970
- function buildStageActivationContext(state, stageName, dependencies) {
1025
+ function inferScopeCheckMode(state, requestedMode = null) {
1026
+ if (requestedMode) return requestedMode;
1027
+ const completed = Array.isArray(state.completed) ? state.completed.map(normalizeAgentName) : [];
1028
+ const current = normalizeAgentName(state.current || state.next);
1029
+ if (completed.includes('dev')) return 'post-dev';
1030
+ if (completed.includes('qa') || completed.includes('tester') || completed.includes('pentester')) return 'post-fix';
1031
+ if (current === 'scope-check') return 'pre-dev';
1032
+ return 'pre-dev';
1033
+ }
1034
+
1035
+ function buildScopeCheckActivationContext(state, mode) {
1036
+ const resolvedMode = inferScopeCheckMode(state, mode);
1037
+ const lines = [
1038
+ `Scope-check mode: ${resolvedMode}`,
1039
+ `Workflow mode: ${state.mode || 'unknown'}`,
1040
+ `Classification: ${state.classification || 'unknown'}`
1041
+ ];
1042
+ if (state.featureSlug) lines.push(`Feature slug: ${state.featureSlug}`);
1043
+ if (resolvedMode === 'pre-dev') {
1044
+ lines.push('Compare user intent against planning artifacts before implementation.');
1045
+ } else if (resolvedMode === 'post-dev') {
1046
+ lines.push('Compare the approved scope-check/design artifacts against the actual implementation diff and changed files before QA.');
1047
+ } else if (resolvedMode === 'post-fix') {
1048
+ lines.push('Compare approved scope, QA/tester/pentester findings, and the correction diff; confirm the fix did not change product intent.');
1049
+ } else if (resolvedMode === 'final') {
1050
+ lines.push('Reconcile intent, plan, delivered behavior, and remaining exclusions before close/commit/release.');
1051
+ }
1052
+ return lines.join('\n');
1053
+ }
1054
+
1055
+ function buildStageActivationContext(state, stageName, dependencies, scopeCheckMode = null) {
1056
+ if (stageName === 'scope-check') {
1057
+ return buildScopeCheckActivationContext(state, scopeCheckMode);
1058
+ }
1059
+
971
1060
  if (stageName !== 'dev' || state.mode !== 'feature' || !state.featureSlug) return '';
972
1061
  return [
973
1062
  `Feature slug: ${state.featureSlug}`,
@@ -979,7 +1068,7 @@ function buildStageActivationContext(state, stageName, dependencies) {
979
1068
  ].join('\n');
980
1069
  }
981
1070
 
982
- async function activateStage(targetDir, state, locale, tool, explicitAgent = null, requestedMode = null) {
1071
+ async function activateStage(targetDir, state, locale, tool, explicitAgent = null, requestedMode = null, scopeCheckMode = null) {
983
1072
  const stageName = normalizeAgentName(explicitAgent || state.current || state.next);
984
1073
  if (!stageName) {
985
1074
  return {
@@ -1087,7 +1176,7 @@ async function activateStage(targetDir, state, locale, tool, explicitAgent = nul
1087
1176
  autonomyMode: effectiveMode,
1088
1177
  capabilitySummary: buildAgentCapabilitySummary(agentManifest, tool),
1089
1178
  dependsOn: dependencies,
1090
- activationContext: buildStageActivationContext(state, stageName, dependencies)
1179
+ activationContext: buildStageActivationContext(state, stageName, dependencies, scopeCheckMode)
1091
1180
  });
1092
1181
 
1093
1182
  if (testBriefing) {
@@ -1358,7 +1447,10 @@ async function runWorkflowNext({ args, options, logger, t }) {
1358
1447
  requestedAgent = 'validator';
1359
1448
  }
1360
1449
 
1361
- const activation = await activateStage(targetDir, state, locale, tool, requestedAgent, options.mode || null);
1450
+ const activationAgent = normalizeAgentName(requestedAgent || state.current || state.next);
1451
+ const scopeCheckMode = activationAgent === 'scope-check' ? getScopeCheckModeOption(options) : null;
1452
+ const requestedAutonomyMode = scopeCheckMode && activationAgent === 'scope-check' ? null : options.mode || null;
1453
+ const activation = await activateStage(targetDir, state, locale, tool, requestedAgent, requestedAutonomyMode, scopeCheckMode);
1362
1454
  state = activation.state;
1363
1455
 
1364
1456
  // ── Living Memory: if a reflect manifest is pending (created above by the
@@ -3,11 +3,11 @@
3
3
  const path = require('node:path');
4
4
  const { validateProjectContextFile } = require('../context');
5
5
 
6
- const WORKFLOW_BY_CLASSIFICATION = {
7
- MICRO: ['setup', 'dev'],
8
- SMALL: ['setup', 'product', 'analyst', 'architect', 'dev', 'qa'],
9
- MEDIUM: ['setup', 'product', 'analyst', 'architect', 'ux-ui', 'pm', 'orchestrator', 'dev', 'qa']
10
- };
6
+ const WORKFLOW_BY_CLASSIFICATION = {
7
+ MICRO: ['setup', 'dev'],
8
+ SMALL: ['setup', 'product', 'analyst', 'scope-check', 'architect', 'dev', 'qa'],
9
+ MEDIUM: ['setup', 'product', 'analyst', 'architect', 'ux-ui', 'pm', 'orchestrator', 'scope-check', 'dev', 'qa']
10
+ };
11
11
 
12
12
  function normalizeClassification(value, fallback = 'MICRO') {
13
13
  const text = String(value || '').trim().toUpperCase();
@@ -427,11 +427,20 @@ async function runWorkflowStatus({ args, options, logger, t }) {
427
427
  if (handoff) {
428
428
  logger.log('Last handoff:');
429
429
  if (handoff.last_agent) logger.log(` Agent: ${handoff.last_agent}`);
430
- if (handoff.what_was_done) logger.log(` Done: ${handoff.what_was_done}`);
431
- if (handoff.what_comes_next) logger.log(` Next: ${handoff.what_comes_next}`);
432
- if (handoff.session_ended_at) logger.log(` When: ${timeSince(handoff.session_ended_at)} ago`);
433
- logger.log('');
434
- }
430
+ if (handoff.what_was_done) logger.log(` Done: ${handoff.what_was_done}`);
431
+ if (handoff.what_comes_next) logger.log(` Next: ${handoff.what_comes_next}`);
432
+ if (Array.isArray(handoff.optional_handoffs) && handoff.optional_handoffs.length > 0) {
433
+ logger.log(' Optional handoffs:');
434
+ for (const optional of handoff.optional_handoffs) {
435
+ const label = optional.agent || '@unknown';
436
+ const mode = optional.mode ? ` (${optional.mode})` : '';
437
+ const command = optional.command ? ` — ${optional.command}` : '';
438
+ logger.log(` - ${label}${mode}${command}`);
439
+ }
440
+ }
441
+ if (handoff.session_ended_at) logger.log(` When: ${timeSince(handoff.session_ended_at)} ago`);
442
+ logger.log('');
443
+ }
435
444
 
436
445
  if (handoffProtocol) {
437
446
  logger.log('Handoff protocol:');
package/src/constants.js CHANGED
@@ -6,10 +6,11 @@ const MANAGED_FILES = [
6
6
  'OPENCODE.md',
7
7
  '.aioson/config.md',
8
8
  '.aioson/agents/setup.md',
9
- '.aioson/agents/discovery-design-doc.md',
10
- '.aioson/agents/discover.md',
11
- '.aioson/agents/analyst.md',
12
- '.aioson/agents/architect.md',
9
+ '.aioson/agents/discovery-design-doc.md',
10
+ '.aioson/agents/discover.md',
11
+ '.aioson/agents/analyst.md',
12
+ '.aioson/agents/scope-check.md',
13
+ '.aioson/agents/architect.md',
13
14
  '.aioson/agents/ux-ui.md',
14
15
  '.aioson/agents/product.md',
15
16
  '.aioson/agents/deyvin.md',
@@ -59,10 +60,13 @@ const MANAGED_FILES = [
59
60
  '.aioson/docs/dev/stack-conventions.md',
60
61
  '.aioson/docs/dev/execution-discipline.md',
61
62
  '.aioson/docs/quality/code-health-analysis.md',
62
- '.aioson/skills/process/decision-presentation/SKILL.md',
63
- '.aioson/skills/process/decision-presentation/references/jargon-map.en.yaml',
64
- '.aioson/skills/process/decision-presentation/references/jargon-map.pt-BR.yaml',
65
- '.aioson/skills/static/laravel-conventions.md',
63
+ '.aioson/skills/process/decision-presentation/SKILL.md',
64
+ '.aioson/skills/process/decision-presentation/references/jargon-map.en.yaml',
65
+ '.aioson/skills/process/decision-presentation/references/jargon-map.pt-BR.yaml',
66
+ '.aioson/skills/process/prompt-sharpener/SKILL.md',
67
+ '.aioson/skills/process/prompt-sharpener/references/prompt-diagnostics.md',
68
+ '.aioson/skills/process/prompt-sharpener/agents/openai.yaml',
69
+ '.aioson/skills/static/laravel-conventions.md',
66
70
  '.aioson/skills/static/tall-stack-patterns.md',
67
71
  '.aioson/skills/static/jetstream-setup.md',
68
72
  '.aioson/skills/static/rails-conventions.md',
@@ -213,17 +217,30 @@ const AGENT_DEFINITIONS = [
213
217
  dependsOn: ['.aioson/context/project.context.md'],
214
218
  output: 'small code changes + continuity notes in spec.md + runtime logs/tasks'
215
219
  },
216
- {
217
- id: 'analyst',
218
- displayName: 'Analyst',
219
- description: 'Domain discovery and entity mapping (SMALL/MEDIUM)',
220
- command: '@analyst',
221
- path: '.aioson/agents/analyst.md',
222
- dependsOn: ['.aioson/context/project.context.md'],
223
- output: '.aioson/context/discovery.md'
224
- },
225
- {
226
- id: 'architect',
220
+ {
221
+ id: 'analyst',
222
+ displayName: 'Analyst',
223
+ description: 'Domain discovery and entity mapping (SMALL/MEDIUM)',
224
+ command: '@analyst',
225
+ path: '.aioson/agents/analyst.md',
226
+ dependsOn: ['.aioson/context/project.context.md'],
227
+ output: '.aioson/context/discovery.md'
228
+ },
229
+ {
230
+ id: 'scope-check',
231
+ displayName: 'Scope Check',
232
+ description: 'Scope alignment before development and optional post-dev drift checks',
233
+ command: '@scope-check',
234
+ path: '.aioson/agents/scope-check.md',
235
+ dependsOn: [
236
+ '.aioson/context/project.context.md',
237
+ '.aioson/context/prd.md or .aioson/context/prd-{slug}.md',
238
+ '.aioson/context/discovery.md or .aioson/context/requirements-{slug}.md + .aioson/context/spec-{slug}.md'
239
+ ],
240
+ output: '.aioson/context/scope-check.md or .aioson/context/scope-check-{slug}.md'
241
+ },
242
+ {
243
+ id: 'architect',
227
244
  displayName: 'Architect',
228
245
  description: 'Project structure and technical decisions (SMALL/MEDIUM)',
229
246
  command: '@architect',