@jaimevalasek/aioson 1.17.3 → 1.19.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 +13 -0
- package/README.md +85 -51
- package/docs/en/3-recipes/full-feature-with-sheldon.md +1 -1
- package/docs/en/5-reference/cli-reference.md +4 -4
- package/docs/en/5-reference/qa-browser.md +2 -2
- package/docs/en/README.md +1 -1
- package/docs/en/deyvin-subtask-scout/how-to-use.md +2 -2
- package/docs/en/deyvin-subtask-scout/sub-task-scout.md +3 -3
- package/docs/en/deyvin-subtask-scout/troubleshooting.md +1 -1
- package/docs/pt/3-receitas/publicar-no-aioson-com.md +17 -0
- package/docs/pt/5-referencia/comandos-cli.md +2 -2
- package/docs/pt/5-referencia/inteligencia-adaptativa.md +3 -3
- package/docs/pt/5-referencia/skills.md +1 -1
- package/docs/pt/5-referencia/web3.md +3 -3
- package/docs/pt/README.md +1 -1
- package/docs/pt/_arquivo/README.md +1 -1
- package/docs/pt/_arquivo/cenarios.md +31 -31
- package/docs/pt/_arquivo/design-hybrid-forge.md +5 -5
- package/docs/pt/_arquivo/guia-engineer.md +1 -1
- package/docs/pt/_arquivo/profiler-system.md +1 -1
- package/docs/pt/_arquivo/site-forge.md +16 -16
- package/docs/pt/_arquivo/squad-genome.md +2 -2
- package/docs/pt/agentes.md +37 -37
- package/docs/pt/deyvin-subtask-scout/como-usar.md +2 -2
- package/docs/pt/deyvin-subtask-scout/sub-task-scout.md +1 -1
- package/docs/pt/deyvin-subtask-scout/troubleshooting.md +1 -1
- package/docs/pt/living-memory/README.md +1 -1
- package/docs/pt/living-memory/memoria-viva.md +2 -2
- package/docs/pt/living-memory/reflexao-in-harness.md +1 -1
- package/docs/pt/living-memory/troubleshooting.md +6 -6
- package/package.json +1 -1
- package/src/cli.js +111 -7
- package/src/commands/gate-approve.js +56 -1
- package/src/commands/live.js +81 -54
- package/src/commands/op-capture.js +27 -2
- package/src/commands/op-list.js +33 -1
- package/src/commands/store-system.js +4 -0
- package/src/commands/tool-capabilities.js +14 -10
- package/src/commands/workflow-heal.js +47 -1
- package/src/constants.js +73 -0
- package/src/i18n/messages/en.js +20 -2
- package/src/i18n/messages/es.js +18 -1
- package/src/i18n/messages/fr.js +18 -1
- package/src/i18n/messages/pt-BR.js +20 -2
- package/src/lib/dev-resume.js +6 -1
- package/src/lib/tool-capabilities.js +64 -37
- package/src/operator-memory/decision.js +11 -4
- package/src/operator-memory/proposal.js +11 -7
- package/src/session-handoff.js +52 -1
- package/template/.aioson/agents/analyst.md +33 -1
- package/template/.aioson/agents/architect.md +33 -1
- package/template/.aioson/agents/briefing.md +23 -0
- package/template/.aioson/agents/orchestrator.md +26 -0
- package/template/.aioson/agents/pentester.md +66 -14
- package/template/.aioson/agents/pm.md +18 -1
- package/template/.aioson/agents/product.md +11 -0
- package/template/.aioson/agents/sheldon.md +21 -1
- package/template/.aioson/agents/tester.md +114 -1
- package/template/.aioson/docs/pentester/browser-dast-playbook.md +398 -0
- package/template/.aioson/rules/agent-structural-contract.md +139 -0
- package/template/.aioson/skills/process/decision-presentation/SKILL.md +2 -2
- package/template/.claude/commands/aioson/agent/analyst.md +16 -5
- package/template/.claude/commands/aioson/agent/architect.md +17 -5
- package/template/.claude/commands/aioson/agent/briefing.md +16 -5
- package/template/.claude/commands/aioson/agent/committer.md +16 -5
- package/template/.claude/commands/aioson/agent/copywriter.md +16 -5
- package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/dev.md +18 -5
- package/template/.claude/commands/aioson/agent/deyvin.md +16 -5
- package/template/.claude/commands/aioson/agent/discover.md +16 -5
- package/template/.claude/commands/aioson/agent/discovery-design-doc.md +16 -5
- package/template/.claude/commands/aioson/agent/genome.md +16 -5
- package/template/.claude/commands/aioson/agent/neo.md +16 -5
- package/template/.claude/commands/aioson/agent/orache.md +16 -5
- package/template/.claude/commands/aioson/agent/orchestrator.md +21 -5
- package/template/.claude/commands/aioson/agent/pair.md +16 -5
- package/template/.claude/commands/aioson/agent/pentester.md +22 -5
- package/template/.claude/commands/aioson/agent/pm.md +20 -5
- package/template/.claude/commands/aioson/agent/product.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-enricher.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-researcher.md +16 -5
- package/template/.claude/commands/aioson/agent/qa.md +16 -5
- package/template/.claude/commands/aioson/agent/setup.md +16 -5
- package/template/.claude/commands/aioson/agent/sheldon.md +16 -5
- package/template/.claude/commands/aioson/agent/site-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/squad.md +16 -5
- package/template/.claude/commands/aioson/agent/tester.md +16 -5
- package/template/.claude/commands/aioson/agent/ux-ui.md +19 -5
- package/template/.claude/commands/aioson/agent/validator.md +17 -5
package/src/i18n/messages/en.js
CHANGED
|
@@ -19,6 +19,8 @@ module.exports = {
|
|
|
19
19
|
help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=en]',
|
|
20
20
|
help_agent_prompt:
|
|
21
21
|
'aioson agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=<bcp47-tag>] [--locale=en]',
|
|
22
|
+
help_agent_help:
|
|
23
|
+
'aioson agent:help [agent] [--json]',
|
|
22
24
|
help_agent_invoke:
|
|
23
25
|
'aioson agent:invoke <agent> [path] [--tool=codex|claude|gemini|opencode] [--mode=framework_target|app_target] [--feature=<slug>] [--scope=<area>] [--lang=<bcp47-tag>] [--locale=en]',
|
|
24
26
|
help_context_validate: 'aioson context:validate [path] [--json] [--locale=en]',
|
|
@@ -219,7 +221,7 @@ module.exports = {
|
|
|
219
221
|
help_runtime_emit:
|
|
220
222
|
'aioson runtime:emit [path] --agent=<name> [--type=<event>] [--summary=<text>] [--title=<text>] [--refs=<file[,file2]>] [--plan-step=<id>] [--meta=<json>] [--json] [--locale=en]',
|
|
221
223
|
help_live_start:
|
|
222
|
-
'aioson live:start [path] --tool=codex|claude|gemini|opencode --agent=<name> [--tool-bin=<binary>] [--tool-args=<args>] [--title=<text>] [--goal=<text>] [--plan=<file>] [--session=<key>] [--message=<text>] [--attach] [--no-launch] [--tmux] [--json] [--locale=en]',
|
|
224
|
+
'aioson live:start [path] --tool=codex|claude|gemini|opencode --agent=<name> [--tool-bin=<binary>] [--permission-mode=default|yolo] [--tool-args=<args>] [--title=<text>] [--goal=<text>] [--plan=<file>] [--session=<key>] [--message=<text>] [--attach] [--no-launch] [--tmux] [--json] [--locale=en]',
|
|
223
225
|
help_live_status:
|
|
224
226
|
'aioson live:status [path] [--agent=<name>] [--limit=8] [--watch=2] [--format=compact|tmux-bar] [--json] [--locale=en]',
|
|
225
227
|
help_live_handoff:
|
|
@@ -505,7 +507,22 @@ module.exports = {
|
|
|
505
507
|
'Pentester app_target requires --feature=<slug> (or --slug=<slug>).',
|
|
506
508
|
prompt_missing_scope_for_app_target:
|
|
507
509
|
'Pentester app_target requires --scope=<area>.',
|
|
508
|
-
prompt_title: 'Prompt for agent "{agent}" on tool "{tool}" (locale: {locale}):'
|
|
510
|
+
prompt_title: 'Prompt for agent "{agent}" on tool "{tool}" (locale: {locale}):',
|
|
511
|
+
help_available: 'Available agents:',
|
|
512
|
+
help_run_detail: 'Run "aioson agent:help <name>" for details on a specific agent.',
|
|
513
|
+
help_usage: 'Usage:',
|
|
514
|
+
help_claude_code: '(Claude Code)',
|
|
515
|
+
help_common_options: 'Common options:',
|
|
516
|
+
help_opt_tool: 'Target tool (codex|claude|gemini|opencode)',
|
|
517
|
+
help_opt_language: 'Interaction language (e.g., pt-BR, en)',
|
|
518
|
+
help_opt_headless: 'Output prompt only, no runtime tracking',
|
|
519
|
+
help_opt_output: 'Save headless prompt to file',
|
|
520
|
+
help_opt_json: 'JSON output mode',
|
|
521
|
+
help_agent_options: 'Agent-specific options ({command}):',
|
|
522
|
+
help_requires: 'Requires:',
|
|
523
|
+
help_produces: 'Produces:',
|
|
524
|
+
help_instruction_file: 'Instruction file:',
|
|
525
|
+
help_unknown_agent: 'Unknown agent: {agent}'
|
|
509
526
|
},
|
|
510
527
|
context_validate: {
|
|
511
528
|
missing_file: 'Context file not found: {path}',
|
|
@@ -1093,6 +1110,7 @@ module.exports = {
|
|
|
1093
1110
|
json_requires_no_launch: '--json requires --no-launch for live:start because foreground launch is interactive.',
|
|
1094
1111
|
tool_binary_not_found: 'Tool binary not found in PATH: {binary}',
|
|
1095
1112
|
tool_mismatch: 'Active session uses tool "{existing}" but --tool={requested} was given. Close the session first or use the same tool.',
|
|
1113
|
+
tool_mismatch_auto_closed: 'Previous live session used "{existing}" and was auto-closed. Starting a new session with "{requested}".',
|
|
1096
1114
|
micro_task_already_open: 'A live micro-task is already open for {agent}. Emit task_completed before task_started again.',
|
|
1097
1115
|
handoff_same_agent: 'live:handoff requires different --agent and --to values.',
|
|
1098
1116
|
handoff_agent_mismatch: 'No active live session found for {agent}.',
|
package/src/i18n/messages/es.js
CHANGED
|
@@ -20,6 +20,8 @@ module.exports = {
|
|
|
20
20
|
help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=es]',
|
|
21
21
|
help_agent_prompt:
|
|
22
22
|
'aioson agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=<bcp47-tag>] [--locale=es]',
|
|
23
|
+
help_agent_help:
|
|
24
|
+
'aioson agent:help [agent] [--json]',
|
|
23
25
|
help_agent_invoke:
|
|
24
26
|
'aioson agent:invoke <agent> [path] [--tool=codex|claude|gemini|opencode] [--mode=framework_target|app_target] [--feature=<slug>] [--scope=<area>] [--lang=<bcp47-tag>] [--locale=es]',
|
|
25
27
|
help_context_validate: 'aioson context:validate [path] [--json] [--locale=es]',
|
|
@@ -383,7 +385,22 @@ module.exports = {
|
|
|
383
385
|
'Pentester app_target requiere --feature=<slug> (o --slug=<slug>).',
|
|
384
386
|
prompt_missing_scope_for_app_target:
|
|
385
387
|
'Pentester app_target requiere --scope=<area>.',
|
|
386
|
-
prompt_title: 'Prompt para el agente "{agent}" en la herramienta "{tool}" (locale: {locale}):'
|
|
388
|
+
prompt_title: 'Prompt para el agente "{agent}" en la herramienta "{tool}" (locale: {locale}):',
|
|
389
|
+
help_available: 'Agentes disponibles:',
|
|
390
|
+
help_run_detail: 'Ejecute "aioson agent:help <nombre>" para detalles de un agente específico.',
|
|
391
|
+
help_usage: 'Uso:',
|
|
392
|
+
help_claude_code: '(Claude Code)',
|
|
393
|
+
help_common_options: 'Opciones comunes:',
|
|
394
|
+
help_opt_tool: 'Herramienta destino (codex|claude|gemini|opencode)',
|
|
395
|
+
help_opt_language: 'Idioma de interacción (ej: pt-BR, en)',
|
|
396
|
+
help_opt_headless: 'Solo salida del prompt, sin rastreo de runtime',
|
|
397
|
+
help_opt_output: 'Guardar prompt headless en archivo',
|
|
398
|
+
help_opt_json: 'Modo de salida JSON',
|
|
399
|
+
help_agent_options: 'Opciones específicas del agente ({command}):',
|
|
400
|
+
help_requires: 'Requiere:',
|
|
401
|
+
help_produces: 'Produce:',
|
|
402
|
+
help_instruction_file: 'Archivo de instrucción:',
|
|
403
|
+
help_unknown_agent: 'Agente desconocido: {agent}'
|
|
387
404
|
},
|
|
388
405
|
context_validate: {
|
|
389
406
|
missing_file: 'Archivo de contexto no encontrado: {path}',
|
package/src/i18n/messages/fr.js
CHANGED
|
@@ -20,6 +20,8 @@ module.exports = {
|
|
|
20
20
|
help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=fr]',
|
|
21
21
|
help_agent_prompt:
|
|
22
22
|
'aioson agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=<bcp47-tag>] [--locale=fr]',
|
|
23
|
+
help_agent_help:
|
|
24
|
+
'aioson agent:help [agent] [--json]',
|
|
23
25
|
help_agent_invoke:
|
|
24
26
|
'aioson agent:invoke <agent> [path] [--tool=codex|claude|gemini|opencode] [--mode=framework_target|app_target] [--feature=<slug>] [--scope=<area>] [--lang=<bcp47-tag>] [--locale=fr]',
|
|
25
27
|
help_context_validate: 'aioson context:validate [path] [--json] [--locale=fr]',
|
|
@@ -382,7 +384,22 @@ module.exports = {
|
|
|
382
384
|
'Pentester app_target exige --feature=<slug> (ou --slug=<slug>).',
|
|
383
385
|
prompt_missing_scope_for_app_target:
|
|
384
386
|
'Pentester app_target exige --scope=<area>.',
|
|
385
|
-
prompt_title: 'Prompt pour l agent "{agent}" sur l outil "{tool}" (locale : {locale}) :'
|
|
387
|
+
prompt_title: 'Prompt pour l agent "{agent}" sur l outil "{tool}" (locale : {locale}) :',
|
|
388
|
+
help_available: 'Agents disponibles :',
|
|
389
|
+
help_run_detail: 'Exécutez "aioson agent:help <nom>" pour les détails d un agent spécifique.',
|
|
390
|
+
help_usage: 'Utilisation :',
|
|
391
|
+
help_claude_code: '(Claude Code)',
|
|
392
|
+
help_common_options: 'Options communes :',
|
|
393
|
+
help_opt_tool: 'Outil cible (codex|claude|gemini|opencode)',
|
|
394
|
+
help_opt_language: 'Langue d interaction (ex : pt-BR, en)',
|
|
395
|
+
help_opt_headless: 'Sortie du prompt uniquement, sans suivi runtime',
|
|
396
|
+
help_opt_output: 'Enregistrer le prompt headless dans un fichier',
|
|
397
|
+
help_opt_json: 'Mode de sortie JSON',
|
|
398
|
+
help_agent_options: 'Options spécifiques de l agent ({command}) :',
|
|
399
|
+
help_requires: 'Requiert :',
|
|
400
|
+
help_produces: 'Produit :',
|
|
401
|
+
help_instruction_file: 'Fichier d instruction :',
|
|
402
|
+
help_unknown_agent: 'Agent inconnu : {agent}'
|
|
386
403
|
},
|
|
387
404
|
context_validate: {
|
|
388
405
|
missing_file: 'Fichier de contexte introuvable : {path}',
|
|
@@ -20,6 +20,8 @@ module.exports = {
|
|
|
20
20
|
help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=pt-BR]',
|
|
21
21
|
help_agent_prompt:
|
|
22
22
|
'aioson agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=<bcp47-tag>] [--locale=pt-BR]',
|
|
23
|
+
help_agent_help:
|
|
24
|
+
'aioson agent:help [agent] [--json]',
|
|
23
25
|
help_agent_invoke:
|
|
24
26
|
'aioson agent:invoke <agent> [path] [--tool=codex|claude|gemini|opencode] [--mode=framework_target|app_target] [--feature=<slug>] [--scope=<area>] [--lang=<bcp47-tag>] [--locale=pt-BR]',
|
|
25
27
|
help_context_validate: 'aioson context:validate [path] [--json] [--locale=pt-BR]',
|
|
@@ -217,7 +219,7 @@ module.exports = {
|
|
|
217
219
|
help_runtime_emit:
|
|
218
220
|
'aioson runtime:emit [path] --agent=<nome> [--type=<evento>] [--summary=<texto>] [--title=<texto>] [--refs=<arquivo[,arquivo2]>] [--plan-step=<id>] [--meta=<json>] [--json] [--locale=pt-BR]',
|
|
219
221
|
help_live_start:
|
|
220
|
-
'aioson live:start [path] --tool=codex|claude|gemini|opencode --agent=<nome> [--tool-bin=<binario>] [--tool-args=<args>] [--title=<texto>] [--goal=<texto>] [--plan=<arquivo>] [--session=<chave>] [--message=<texto>] [--attach] [--no-launch] [--tmux] [--json] [--locale=pt-BR]',
|
|
222
|
+
'aioson live:start [path] --tool=codex|claude|gemini|opencode --agent=<nome> [--tool-bin=<binario>] [--permission-mode=default|yolo] [--tool-args=<args>] [--title=<texto>] [--goal=<texto>] [--plan=<arquivo>] [--session=<chave>] [--message=<texto>] [--attach] [--no-launch] [--tmux] [--json] [--locale=pt-BR]',
|
|
221
223
|
help_live_status:
|
|
222
224
|
'aioson live:status [path] [--agent=<nome>] [--limit=8] [--watch=2] [--format=compact|tmux-bar] [--json] [--locale=pt-BR]',
|
|
223
225
|
help_live_handoff:
|
|
@@ -477,7 +479,22 @@ module.exports = {
|
|
|
477
479
|
'Pentester app_target exige --feature=<slug> (ou --slug=<slug>).',
|
|
478
480
|
prompt_missing_scope_for_app_target:
|
|
479
481
|
'Pentester app_target exige --scope=<area>.',
|
|
480
|
-
prompt_title: 'Prompt para o agente "{agent}" na ferramenta "{tool}" (locale: {locale}):'
|
|
482
|
+
prompt_title: 'Prompt para o agente "{agent}" na ferramenta "{tool}" (locale: {locale}):',
|
|
483
|
+
help_available: 'Agentes disponíveis:',
|
|
484
|
+
help_run_detail: 'Execute "aioson agent:help <nome>" para detalhes de um agente específico.',
|
|
485
|
+
help_usage: 'Uso:',
|
|
486
|
+
help_claude_code: '(Claude Code)',
|
|
487
|
+
help_common_options: 'Opções comuns:',
|
|
488
|
+
help_opt_tool: 'Ferramenta alvo (codex|claude|gemini|opencode)',
|
|
489
|
+
help_opt_language: 'Idioma de interação (ex: pt-BR, en)',
|
|
490
|
+
help_opt_headless: 'Saída apenas do prompt, sem rastreamento de runtime',
|
|
491
|
+
help_opt_output: 'Salvar prompt headless em arquivo',
|
|
492
|
+
help_opt_json: 'Modo de saída JSON',
|
|
493
|
+
help_agent_options: 'Opções específicas do agente ({command}):',
|
|
494
|
+
help_requires: 'Requer:',
|
|
495
|
+
help_produces: 'Produz:',
|
|
496
|
+
help_instruction_file: 'Arquivo de instrução:',
|
|
497
|
+
help_unknown_agent: 'Agente desconhecido: {agent}'
|
|
481
498
|
},
|
|
482
499
|
context_validate: {
|
|
483
500
|
missing_file: 'Arquivo de contexto nao encontrado: {path}',
|
|
@@ -1119,6 +1136,7 @@ module.exports = {
|
|
|
1119
1136
|
json_requires_no_launch: '--json requer --no-launch para live:start porque o lancamento em primeiro plano e interativo.',
|
|
1120
1137
|
tool_binary_not_found: 'Binario da ferramenta nao encontrado no PATH: {binary}',
|
|
1121
1138
|
tool_mismatch: 'A sessao ativa usa a ferramenta "{existing}" mas --tool={requested} foi informado. Encerre a sessao primeiro ou use a mesma ferramenta.',
|
|
1139
|
+
tool_mismatch_auto_closed: 'A sessao live anterior usava "{existing}" e foi fechada automaticamente. Iniciando nova sessao com "{requested}".',
|
|
1122
1140
|
micro_task_already_open: 'Uma micro-tarefa live ja esta aberta para {agent}. Emita task_completed antes de task_started novamente.',
|
|
1123
1141
|
handoff_same_agent: 'live:handoff requer valores diferentes para --agent e --to.',
|
|
1124
1142
|
handoff_agent_mismatch: 'Nenhuma sessao live ativa encontrada para {agent}.',
|
package/src/lib/dev-resume.js
CHANGED
|
@@ -121,6 +121,10 @@ async function buildDevResumeData(projectPath) {
|
|
|
121
121
|
? lastHandoff.artifact_uris
|
|
122
122
|
: [];
|
|
123
123
|
|
|
124
|
+
const decisionRationale = Array.isArray(lastHandoff && lastHandoff.decision_rationale)
|
|
125
|
+
? lastHandoff.decision_rationale
|
|
126
|
+
: [];
|
|
127
|
+
|
|
124
128
|
return {
|
|
125
129
|
feature_slug: featureSlug,
|
|
126
130
|
classification,
|
|
@@ -128,7 +132,8 @@ async function buildDevResumeData(projectPath) {
|
|
|
128
132
|
artifacts_consumed: artifactsConsumed,
|
|
129
133
|
code_map_paths: extractCodeMapPaths(dossierRaw),
|
|
130
134
|
sheldon_plan: sheldonPlan,
|
|
131
|
-
next_step: devStateNext || deriveNextStepFromPlan(planRaw)
|
|
135
|
+
next_step: devStateNext || deriveNextStepFromPlan(planRaw),
|
|
136
|
+
decision_rationale: decisionRationale.length > 0 ? decisionRationale : undefined
|
|
132
137
|
};
|
|
133
138
|
}
|
|
134
139
|
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
// "continue last conversation" is achieved by passing the right resume flag
|
|
6
6
|
// at spawn time — AIOSON never has to track an internal session ID.
|
|
7
7
|
//
|
|
8
|
-
// Used by:
|
|
9
|
-
// - `aioson live:start --resume[=last|<id>]` to map to the correct argv
|
|
10
|
-
// - `aioson
|
|
11
|
-
//
|
|
8
|
+
// Used by:
|
|
9
|
+
// - `aioson live:start --resume[=last|<id>]` to map to the correct argv
|
|
10
|
+
// - `aioson live:start --permission-mode=yolo` to map to the correct argv
|
|
11
|
+
// - `aioson tool:capabilities` to expose this map as JSON to UI clients
|
|
12
|
+
// (e.g. AIOSON Play) so they don't duplicate the lookup.
|
|
12
13
|
//
|
|
13
14
|
// Keep entries minimal and source-of-truth here. Adding a new CLI = one entry.
|
|
14
15
|
const TOOL_CAPS = {
|
|
@@ -17,42 +18,50 @@ const TOOL_CAPS = {
|
|
|
17
18
|
binary: 'claude',
|
|
18
19
|
supports_resume: true,
|
|
19
20
|
resume_last: ['--continue'],
|
|
20
|
-
supports_session_id: true,
|
|
21
|
-
resume_session_id: ['--resume', '<id>'],
|
|
22
|
-
supports_session_picker: true,
|
|
23
|
-
session_picker: ['--resume'],
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
supports_session_id: true,
|
|
22
|
+
resume_session_id: ['--resume', '<id>'],
|
|
23
|
+
supports_session_picker: true,
|
|
24
|
+
session_picker: ['--resume'],
|
|
25
|
+
supports_yolo: true,
|
|
26
|
+
yolo_args: ['--dangerously-skip-permissions'],
|
|
27
|
+
},
|
|
28
|
+
codex: {
|
|
26
29
|
install_command: 'npm install -g @openai/codex',
|
|
27
30
|
binary: 'codex',
|
|
28
31
|
supports_resume: true,
|
|
29
32
|
resume_last: ['resume', '--last'],
|
|
30
|
-
supports_session_id: true,
|
|
31
|
-
resume_session_id: ['resume', '<id>'],
|
|
32
|
-
supports_session_picker: true,
|
|
33
|
-
session_picker: ['resume'],
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
supports_session_id: true,
|
|
34
|
+
resume_session_id: ['resume', '<id>'],
|
|
35
|
+
supports_session_picker: true,
|
|
36
|
+
session_picker: ['resume'],
|
|
37
|
+
supports_yolo: true,
|
|
38
|
+
yolo_args: ['--dangerously-bypass-approvals-and-sandbox'],
|
|
39
|
+
},
|
|
40
|
+
opencode: {
|
|
36
41
|
install_command: 'npm install -g opencode-ai',
|
|
37
42
|
binary: 'opencode',
|
|
38
43
|
supports_resume: true,
|
|
39
44
|
resume_last: ['--continue'],
|
|
40
|
-
supports_session_id: true,
|
|
41
|
-
resume_session_id: ['--session', '<id>'],
|
|
42
|
-
supports_session_picker: false,
|
|
43
|
-
session_picker: null,
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
supports_session_id: true,
|
|
46
|
+
resume_session_id: ['--session', '<id>'],
|
|
47
|
+
supports_session_picker: false,
|
|
48
|
+
session_picker: null,
|
|
49
|
+
supports_yolo: false,
|
|
50
|
+
yolo_args: null,
|
|
51
|
+
},
|
|
52
|
+
gemini: {
|
|
46
53
|
install_command: 'npm install -g @google/gemini-cli',
|
|
47
54
|
binary: 'gemini',
|
|
48
55
|
supports_resume: false,
|
|
49
56
|
resume_last: null,
|
|
50
|
-
supports_session_id: false,
|
|
51
|
-
resume_session_id: null,
|
|
52
|
-
supports_session_picker: false,
|
|
53
|
-
session_picker: null,
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
supports_session_id: false,
|
|
58
|
+
resume_session_id: null,
|
|
59
|
+
supports_session_picker: false,
|
|
60
|
+
session_picker: null,
|
|
61
|
+
supports_yolo: false,
|
|
62
|
+
yolo_args: null,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
56
65
|
|
|
57
66
|
function getToolCapabilities(tool) {
|
|
58
67
|
const key = String(tool || '').trim().toLowerCase();
|
|
@@ -71,7 +80,7 @@ function listSupportedTools() {
|
|
|
71
80
|
// - '' / undefined / null / false → no resume
|
|
72
81
|
// - any other string → treat as session id
|
|
73
82
|
// Returns [] when the tool doesn't support resume or resumeOpt is falsy.
|
|
74
|
-
function resolveResumeArgs(tool, resumeOpt) {
|
|
83
|
+
function resolveResumeArgs(tool, resumeOpt) {
|
|
75
84
|
if (resumeOpt === undefined || resumeOpt === null || resumeOpt === '' || resumeOpt === false) {
|
|
76
85
|
return [];
|
|
77
86
|
}
|
|
@@ -92,11 +101,29 @@ function resolveResumeArgs(tool, resumeOpt) {
|
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
return Array.isArray(caps.resume_last) ? [...caps.resume_last] : [];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function resolvePermissionModeArgs(tool, permissionMode) {
|
|
107
|
+
const mode = String(permissionMode || '').trim().toLowerCase();
|
|
108
|
+
if (!mode || mode === 'default') return [];
|
|
109
|
+
if (mode !== 'yolo') {
|
|
110
|
+
throw new Error(`permission_mode_unknown:${permissionMode}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const caps = getToolCapabilities(tool);
|
|
114
|
+
if (!caps) {
|
|
115
|
+
throw new Error(`tool_unknown:${tool}`);
|
|
116
|
+
}
|
|
117
|
+
if (!caps.supports_yolo || !Array.isArray(caps.yolo_args)) {
|
|
118
|
+
throw new Error(`permission_mode_unsupported:${tool}:yolo`);
|
|
119
|
+
}
|
|
120
|
+
return [...caps.yolo_args];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
TOOL_CAPS,
|
|
125
|
+
getToolCapabilities,
|
|
126
|
+
listSupportedTools,
|
|
127
|
+
resolveResumeArgs,
|
|
128
|
+
resolvePermissionModeArgs,
|
|
129
|
+
};
|
|
@@ -81,7 +81,7 @@ function deriveTitle(proposal) {
|
|
|
81
81
|
function serializeDecision(data) {
|
|
82
82
|
const body = String(data.body || data.proposal || '').slice(0, MAX_BODY_CHARS);
|
|
83
83
|
const title = deriveTitle(data.title || data.proposal);
|
|
84
|
-
|
|
84
|
+
const lines = [
|
|
85
85
|
'---',
|
|
86
86
|
`slug: ${data.slug}`,
|
|
87
87
|
`signal_type: ${data.signal_type}`,
|
|
@@ -93,8 +93,13 @@ function serializeDecision(data) {
|
|
|
93
93
|
`source_agent: ${data.source_agent}`,
|
|
94
94
|
`quotes:${quotesToYaml(data.quotes)}`,
|
|
95
95
|
`version_schema: "${SCHEMA_VERSION}"`,
|
|
96
|
-
`deprecated_by: ${data.deprecated_by ?? 'null'}
|
|
97
|
-
|
|
96
|
+
`deprecated_by: ${data.deprecated_by ?? 'null'}`
|
|
97
|
+
];
|
|
98
|
+
if (data.feature_slug) lines.push(`feature_slug: ${escapeYamlString(data.feature_slug)}`);
|
|
99
|
+
if (data.session_id) lines.push(`session_id: ${escapeYamlString(data.session_id)}`);
|
|
100
|
+
lines.push('---');
|
|
101
|
+
return [
|
|
102
|
+
...lines,
|
|
98
103
|
'',
|
|
99
104
|
`# ${title}`,
|
|
100
105
|
'',
|
|
@@ -178,7 +183,9 @@ function promoteProposal({ identity, proposal: proposalData }) {
|
|
|
178
183
|
quotes: proposalData.quotes || [],
|
|
179
184
|
body,
|
|
180
185
|
title: proposalData.proposal,
|
|
181
|
-
deprecated_by: null
|
|
186
|
+
deprecated_by: null,
|
|
187
|
+
feature_slug: proposalData.feature_slug || null,
|
|
188
|
+
session_id: proposalData.session_id || null
|
|
182
189
|
};
|
|
183
190
|
|
|
184
191
|
const decFilePath = decisionPath(identity, decision.slug);
|
|
@@ -46,7 +46,7 @@ function quotesToYaml(quotes) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function serializeProposal(data) {
|
|
49
|
-
|
|
49
|
+
const lines = [
|
|
50
50
|
'---',
|
|
51
51
|
`slug: ${data.slug}`,
|
|
52
52
|
`signal_type: ${data.signal_type}`,
|
|
@@ -56,10 +56,12 @@ function serializeProposal(data) {
|
|
|
56
56
|
`quotes:${quotesToYaml(data.quotes)}`,
|
|
57
57
|
`proposal: ${escapeYamlString(data.proposal)}`,
|
|
58
58
|
`source_agent: ${data.source_agent}`,
|
|
59
|
-
`proposal_fingerprint: ${data.proposal_fingerprint}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
`proposal_fingerprint: ${data.proposal_fingerprint}`
|
|
60
|
+
];
|
|
61
|
+
if (data.feature_slug) lines.push(`feature_slug: ${escapeYamlString(data.feature_slug)}`);
|
|
62
|
+
if (data.session_id) lines.push(`session_id: ${escapeYamlString(data.session_id)}`);
|
|
63
|
+
lines.push('---', '');
|
|
64
|
+
return lines.join('\n');
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
function parseProposalFrontmatter(content) {
|
|
@@ -130,7 +132,7 @@ function deleteProposal(identity, slug) {
|
|
|
130
132
|
return false;
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
function captureSignal({ identity, slug, signal_type, quote, proposal, source_agent }) {
|
|
135
|
+
function captureSignal({ identity, slug, signal_type, quote, proposal, source_agent, feature_slug, session_id }) {
|
|
134
136
|
if (!VALID_SIGNAL_TYPES.includes(signal_type)) {
|
|
135
137
|
throw new Error(`Invalid signal_type '${signal_type}'. Must be one of: ${VALID_SIGNAL_TYPES.join(', ')}`);
|
|
136
138
|
}
|
|
@@ -160,7 +162,9 @@ function captureSignal({ identity, slug, signal_type, quote, proposal, source_ag
|
|
|
160
162
|
quotes: quote ? [String(quote).trim()].filter(Boolean) : [],
|
|
161
163
|
proposal,
|
|
162
164
|
source_agent: source_agent || 'unknown',
|
|
163
|
-
proposal_fingerprint: fingerprintProposal(proposal)
|
|
165
|
+
proposal_fingerprint: fingerprintProposal(proposal),
|
|
166
|
+
feature_slug: feature_slug || null,
|
|
167
|
+
session_id: session_id || null
|
|
164
168
|
};
|
|
165
169
|
writeProposal(identity, fresh);
|
|
166
170
|
return { proposal: fresh, isNew: true };
|
package/src/session-handoff.js
CHANGED
|
@@ -6,6 +6,8 @@ const { exists, ensureDir } = require('./utils');
|
|
|
6
6
|
|
|
7
7
|
const HANDOFF_RELATIVE_PATH = '.aioson/context/last-handoff.json';
|
|
8
8
|
const HANDOFF_PROTOCOL_RELATIVE_PATH = '.aioson/context/handoff-protocol.json';
|
|
9
|
+
const CONFIRMATIONS_JSONL = '.aioson/runtime/session-confirmations.jsonl';
|
|
10
|
+
const DECISION_RATIONALE_MAX = 5;
|
|
9
11
|
|
|
10
12
|
// handoff-protocol.json schema_version for `artifact_uris`:
|
|
11
13
|
// v1 (legacy) — array of strings; v2 — array of {path, kind, agent, added_at}.
|
|
@@ -63,10 +65,52 @@ function coerceArtifactUris(uris, fallbackAgent) {
|
|
|
63
65
|
.filter(Boolean);
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
async function collectDecisionRationale(targetDir) {
|
|
69
|
+
const accPath = path.join(targetDir, CONFIRMATIONS_JSONL);
|
|
70
|
+
try {
|
|
71
|
+
const raw = await fs.readFile(accPath, 'utf8');
|
|
72
|
+
const lines = raw.trim().split('\n').filter(Boolean);
|
|
73
|
+
const entries = [];
|
|
74
|
+
for (const line of lines) {
|
|
75
|
+
try {
|
|
76
|
+
const obj = JSON.parse(line);
|
|
77
|
+
entries.push({
|
|
78
|
+
agent: obj.agent || 'unknown',
|
|
79
|
+
decision: obj.decision || '',
|
|
80
|
+
alternatives_considered: null,
|
|
81
|
+
rationale: obj.quote || null,
|
|
82
|
+
confidence: 'confirmed'
|
|
83
|
+
});
|
|
84
|
+
} catch {
|
|
85
|
+
// skip malformed lines
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// BR-AO-04: FIFO — keep only the last N entries
|
|
89
|
+
return entries.slice(-DECISION_RATIONALE_MAX);
|
|
90
|
+
} catch {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function clearConfirmationsAccumulator(targetDir) {
|
|
96
|
+
const accPath = path.join(targetDir, CONFIRMATIONS_JSONL);
|
|
97
|
+
try {
|
|
98
|
+
await fs.unlink(accPath);
|
|
99
|
+
} catch {
|
|
100
|
+
// file may not exist
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
66
104
|
async function writeHandoff(targetDir, payload) {
|
|
67
105
|
const handoffPath = path.join(targetDir, HANDOFF_RELATIVE_PATH);
|
|
68
106
|
const protocolPath = path.join(targetDir, HANDOFF_PROTOCOL_RELATIVE_PATH);
|
|
69
107
|
await ensureDir(path.dirname(handoffPath));
|
|
108
|
+
|
|
109
|
+
// M2: collect decision rationale from session confirmations
|
|
110
|
+
const sessionRationale = await collectDecisionRationale(targetDir);
|
|
111
|
+
const existingRationale = Array.isArray(payload.decisionRationale) ? payload.decisionRationale : [];
|
|
112
|
+
const mergedRationale = [...existingRationale, ...sessionRationale].slice(-DECISION_RATIONALE_MAX);
|
|
113
|
+
|
|
70
114
|
const handoff = {
|
|
71
115
|
version: 1,
|
|
72
116
|
session_ended_at: new Date().toISOString(),
|
|
@@ -79,10 +123,14 @@ async function writeHandoff(targetDir, payload) {
|
|
|
79
123
|
context_files_updated: Array.isArray(payload.contextFilesUpdated) ? payload.contextFilesUpdated : [],
|
|
80
124
|
workflow_mode: payload.workflowMode || null,
|
|
81
125
|
classification: payload.classification || null,
|
|
82
|
-
feature_slug: payload.featureSlug || null
|
|
126
|
+
feature_slug: payload.featureSlug || null,
|
|
127
|
+
decision_rationale: mergedRationale.length > 0 ? mergedRationale : undefined
|
|
83
128
|
};
|
|
84
129
|
await fs.writeFile(handoffPath, `${JSON.stringify(handoff, null, 2)}\n`, 'utf8');
|
|
85
130
|
|
|
131
|
+
// Clear accumulator after writing to handoff
|
|
132
|
+
await clearConfirmationsAccumulator(targetDir);
|
|
133
|
+
|
|
86
134
|
const protocol = payload.protocol || buildBasicHandoffProtocol(payload);
|
|
87
135
|
await fs.writeFile(protocolPath, `${JSON.stringify(protocol, null, 2)}\n`, 'utf8');
|
|
88
136
|
|
|
@@ -283,9 +331,12 @@ function buildRuntimeLogHandoff(agentName, message, summary) {
|
|
|
283
331
|
module.exports = {
|
|
284
332
|
HANDOFF_RELATIVE_PATH,
|
|
285
333
|
HANDOFF_PROTOCOL_RELATIVE_PATH,
|
|
334
|
+
CONFIRMATIONS_JSONL,
|
|
335
|
+
DECISION_RATIONALE_MAX,
|
|
286
336
|
ARTIFACT_KINDS,
|
|
287
337
|
coerceArtifactUri,
|
|
288
338
|
coerceArtifactUris,
|
|
339
|
+
collectDecisionRationale,
|
|
289
340
|
writeHandoff,
|
|
290
341
|
readHandoff,
|
|
291
342
|
readHandoffProtocol,
|
|
@@ -34,6 +34,8 @@ Before any manual checks, run these commands if the `aioson` CLI is available:
|
|
|
34
34
|
```bash
|
|
35
35
|
aioson workflow:status . # confirm current stage and what is expected
|
|
36
36
|
aioson context:validate . # validate project.context.md; detects brownfield state
|
|
37
|
+
aioson preflight . --agent=analyst --feature={slug} # unified pre-session check: loads rules, design governance, and context
|
|
38
|
+
aioson classify . # auto-detect project classification (MICRO/SMALL/MEDIUM) for cross-reference
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
For feature mode with existing requirements, run before the synchronization gate:
|
|
@@ -341,5 +343,35 @@ aioson dev:state:write . --feature={slug} --phase=1 \
|
|
|
341
343
|
|
|
342
344
|
`--context` accepts canonical tokens (`prd`, `requirements`, `spec`, `architecture`, `impl-plan`, `sheldon`, `design-doc`, `dossier`), max 4 entries total; missing files emit a warning and are skipped. Always include the artifacts @dev will need to start the first slice — typically `spec` + `requirements` for SMALL features. Idempotent: re-running with the same args does not duplicate state.
|
|
343
345
|
|
|
346
|
+
**Handoff message:**
|
|
347
|
+
```
|
|
348
|
+
Requirements written: .aioson/context/requirements-{slug}.md
|
|
349
|
+
Spec skeleton: .aioson/context/spec-{slug}.md
|
|
350
|
+
Gate A: approved
|
|
351
|
+
Next agent: @architect (MEDIUM) or @dev (SMALL — skip architecture)
|
|
352
|
+
Why: Requirements and spec ready — @architect defines system design, or @dev starts implementation for SMALL features.
|
|
353
|
+
Action: /architect or /dev
|
|
354
|
+
```
|
|
355
|
+
> Recommended: `/clear` before activating — fresh context window.
|
|
356
|
+
|
|
357
|
+
## Strategic commands (use during session)
|
|
358
|
+
|
|
359
|
+
- Search memory before web research: `aioson memory:search . --query="<topic>" 2>/dev/null || true`
|
|
360
|
+
- Search context files: `aioson context:search . --query="<term>" 2>/dev/null || true`
|
|
361
|
+
- Compress context before handoff: `aioson context:pack . 2>/dev/null || true`
|
|
362
|
+
- Create spec checkpoint before changes: `aioson spec:checkpoint . --feature={slug} 2>/dev/null || true`
|
|
363
|
+
|
|
344
364
|
## Observability
|
|
345
|
-
|
|
365
|
+
|
|
366
|
+
At strategic milestones during execution, emit progress signals:
|
|
367
|
+
```bash
|
|
368
|
+
aioson runtime:emit . --agent=analyst --type=milestone --summary="Requirements written: {slug}, {N} BRs, {N} ECs" 2>/dev/null || true
|
|
369
|
+
aioson runtime:emit . --agent=analyst --type=milestone --summary="Spec skeleton created: {slug}" 2>/dev/null || true
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
At session end, register:
|
|
373
|
+
```bash
|
|
374
|
+
aioson gate:approve . --feature={slug} --gate=A 2>/dev/null || true
|
|
375
|
+
aioson pulse:update . --agent=analyst --feature={slug} --action="Discovery completed: {N} entities, {N} rules" --next="<next agent recommendation>" 2>/dev/null || true
|
|
376
|
+
aioson agent:done . --agent=analyst --summary="Discovery <slug>: <N> entities, <N> rules" 2>/dev/null || true
|
|
377
|
+
```
|
|
@@ -124,6 +124,20 @@ Before handing off to `@dev`:
|
|
|
124
124
|
- If a relevant spec file exists and design is still pending, do not claim Gate B passed.
|
|
125
125
|
- Tell the user explicitly whether Gate B passed or is blocked before handoff.
|
|
126
126
|
|
|
127
|
+
When Gate B passes, register it via CLI:
|
|
128
|
+
```bash
|
|
129
|
+
aioson gate:approve . --feature={slug} --gate=B 2>/dev/null || true
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Handoff message:**
|
|
133
|
+
```
|
|
134
|
+
Architecture defined: .aioson/context/architecture.md
|
|
135
|
+
Gate B: {approved|blocked}
|
|
136
|
+
Next agent: @pm (MEDIUM — implementation planning) or @dev (SMALL — direct implementation)
|
|
137
|
+
Action: /pm or /dev
|
|
138
|
+
```
|
|
139
|
+
> Recommended: `/clear` before activating — fresh context window.
|
|
140
|
+
|
|
127
141
|
## Rules
|
|
128
142
|
- Do not redesign entities produced by `@analyst`. Consume the data design as-is.
|
|
129
143
|
- Keep architecture proportional to classification. Never apply MEDIUM patterns to a MICRO project.
|
|
@@ -321,5 +335,23 @@ Keep architecture.md proportional — verbose output costs tokens without adding
|
|
|
321
335
|
- Do not introduce patterns that do not exist in the chosen stack's conventions.
|
|
322
336
|
- Do not copy content from discovery.md into architecture.md. Reference sections by name: "see discovery.md § Entities". The document chain is already in context.
|
|
323
337
|
|
|
338
|
+
## Strategic commands (use during session)
|
|
339
|
+
|
|
340
|
+
- Search context for existing decisions: `aioson context:search . --query="<architectural term>" 2>/dev/null || true`
|
|
341
|
+
- Validate artifacts against spec: `aioson artifact:validate . --feature={slug} 2>/dev/null || true`
|
|
342
|
+
- Compress context before handoff: `aioson context:pack . 2>/dev/null || true`
|
|
343
|
+
- Audit dossier completeness: `aioson dossier:audit . --check=coverage 2>/dev/null || true`
|
|
344
|
+
|
|
324
345
|
## Observability
|
|
325
|
-
|
|
346
|
+
|
|
347
|
+
At strategic milestones during execution, emit progress signals:
|
|
348
|
+
```bash
|
|
349
|
+
aioson runtime:emit . --agent=architect --type=milestone --summary="Architecture decided: {slug}, {stack}" 2>/dev/null || true
|
|
350
|
+
aioson runtime:emit . --agent=architect --type=gate_check --summary="Gate B: {approved|blocked} for {slug}" 2>/dev/null || true
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
At session end, register:
|
|
354
|
+
```bash
|
|
355
|
+
aioson pulse:update . --agent=architect --feature={slug} --action="Architecture defined: {stack}, {N} modules" --next="<next agent recommendation>" 2>/dev/null || true
|
|
356
|
+
aioson agent:done . --agent=architect --summary="Architecture <slug>: <stack>, <N> modules" 2>/dev/null || true
|
|
357
|
+
```
|
|
@@ -92,6 +92,16 @@ Wait for confirmation.
|
|
|
92
92
|
Write `.aioson/briefings/{slug}/briefings.md` and update `.aioson/briefings/config.md`.
|
|
93
93
|
See **Output contract** below for exact formats.
|
|
94
94
|
|
|
95
|
+
After writing the briefing draft, emit a milestone:
|
|
96
|
+
```bash
|
|
97
|
+
aioson runtime:emit . --agent=briefing --type=milestone --summary="Briefing draft written: {slug}" 2>/dev/null || true
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If a feature dossier exists for the target slug, record the briefing:
|
|
101
|
+
```bash
|
|
102
|
+
aioson dossier:add-finding . --slug={slug} --agent=briefing --section="Agent Trail" --content="Briefing created: {N} themes, {N} risks, {N} open questions" 2>/dev/null || true
|
|
103
|
+
```
|
|
104
|
+
|
|
95
105
|
## Mode: Conversational (no plans)
|
|
96
106
|
|
|
97
107
|
When `plans/` is empty or the user wants to plan via conversation:
|
|
@@ -222,12 +232,24 @@ Always register additional files with a note at the bottom of `briefings.md`:
|
|
|
222
232
|
- `{specific-theme}.md` — {one line description}
|
|
223
233
|
```
|
|
224
234
|
|
|
235
|
+
## Feature dossier
|
|
236
|
+
|
|
237
|
+
Check `.aioson/context/features/{slug}/dossier.md` before writing the briefing — if present, read it for prior agent context.
|
|
238
|
+
|
|
239
|
+
**After writing the briefing**, record in the dossier:
|
|
240
|
+
```
|
|
241
|
+
aioson dossier:add-finding . --slug={slug} --agent=briefing --section="Agent Trail" --content="Briefing created: {N} themes, {N} risks, {N} open questions" 2>/dev/null || true
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Skip silently when the dossier is absent.
|
|
245
|
+
|
|
225
246
|
## Rules
|
|
226
247
|
|
|
227
248
|
- **Never modify `plans/`** — they are read-only. Plans belong to the user.
|
|
228
249
|
- **Never access `.aioson/briefings/` from @dev** — briefings are pre-production. @dev receives the PRD already built.
|
|
229
250
|
- **Never create a PRD** — that is `@product`'s responsibility.
|
|
230
251
|
- **Never approve a briefing automatically** — approval requires explicit user action via CLI.
|
|
252
|
+
- When a briefing is approved (via CLI), emit: `aioson runtime:emit . --agent=briefing --type=milestone --summary="Briefing approved: {slug}" 2>/dev/null || true`
|
|
231
253
|
- **Never overwrite an existing briefing** without confirming with the user first.
|
|
232
254
|
- **Slug must be confirmed** by the user before any file is written.
|
|
233
255
|
- **Never recommend `@sheldon` (or any post-PRD agent) as the next step.** The only handoff from `@briefing` is `@product`. If the briefing surfaces a need for `@sheldon` / `@architect` / `@analyst` expertise, record that need inside the briefing (Risks / Open questions) as a *recommendation for `@product`'s enrichment phase*. `@product` decides when to invoke specialists after the PRD exists. See `briefing-craft.md` §1 "Mitigating weak markers" for examples.
|
|
@@ -252,6 +274,7 @@ Always register additional files with a note at the bottom of `briefings.md`:
|
|
|
252
274
|
- `config.md` frontmatter must be valid YAML — verify after writing.
|
|
253
275
|
- All 8 sections must appear in `briefings.md` even when empty (`TBD`).
|
|
254
276
|
- At session end, update `.aioson/context/project-pulse.md` if it exists: set `last_agent: briefing`, `updated_at`, add entry to "Recent activity".
|
|
277
|
+
- At session end, update pulse: `aioson pulse:update . --agent=briefing --feature={slug} --action="<summary>" --next="<next agent recommendation>" 2>/dev/null || true`
|
|
255
278
|
- At session end, register: `aioson agent:done . --agent=briefing --summary="<one-line summary>" 2>/dev/null || true`
|
|
256
279
|
- If `aioson` CLI is not available, write a devlog following the "Devlog" section in `.aioson/config.md`.
|
|
257
280
|
|