auroq-os 1.0.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/.auroq-core/constitution.md +153 -0
- package/.auroq-core/core/synapse/context/context-builder.js +34 -0
- package/.auroq-core/core/synapse/context/context-tracker.js +198 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
- package/.auroq-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
- package/.auroq-core/core/synapse/diagnostics/report-formatter.js +484 -0
- package/.auroq-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
- package/.auroq-core/core/synapse/domain/domain-loader.js +322 -0
- package/.auroq-core/core/synapse/engine.js +400 -0
- package/.auroq-core/core/synapse/layers/l0-constitution.js +80 -0
- package/.auroq-core/core/synapse/layers/l1-global.js +102 -0
- package/.auroq-core/core/synapse/layers/l2-agent.js +94 -0
- package/.auroq-core/core/synapse/layers/l3-workflow.js +94 -0
- package/.auroq-core/core/synapse/layers/l4-task.js +83 -0
- package/.auroq-core/core/synapse/layers/l5-squad.js +244 -0
- package/.auroq-core/core/synapse/layers/l6-keyword.js +154 -0
- package/.auroq-core/core/synapse/layers/l7-star-command.js +169 -0
- package/.auroq-core/core/synapse/layers/layer-processor.js +82 -0
- package/.auroq-core/core/synapse/memory/memory-bridge.js +220 -0
- package/.auroq-core/core/synapse/memory/synapse-memory-provider.js +201 -0
- package/.auroq-core/core/synapse/output/formatter.js +561 -0
- package/.auroq-core/core/synapse/runtime/hook-runtime.js +98 -0
- package/.auroq-core/core/synapse/scripts/generate-constitution.js +204 -0
- package/.auroq-core/core/synapse/session/session-manager.js +404 -0
- package/.auroq-core/core/synapse/utils/atomic-write.js +79 -0
- package/.auroq-core/core/synapse/utils/paths.js +57 -0
- package/.auroq-core/core/synapse/utils/tokens.js +25 -0
- package/.auroq-core/core-config.yaml +80 -0
- package/.auroq-core/development/sistema-gestao-projetos.md +193 -0
- package/.auroq-core/development/sistema-memoria.md +157 -0
- package/.auroq-core/dna-operacional.md +134 -0
- package/.claude/CLAUDE.md +399 -0
- package/.claude/commands/AuroqOS/agents/forge.md +374 -0
- package/.claude/commands/AuroqOS/agents/ops.md +277 -0
- package/.claude/commands/companion.md +7 -0
- package/.claude/hooks/precompact-session-digest.cjs +46 -0
- package/.claude/hooks/synapse-engine.cjs +99 -0
- package/.claude/rules/agent-authority.md +79 -0
- package/.claude/rules/agent-handoff.md +97 -0
- package/.claude/rules/commit-inteligente.md +86 -0
- package/.claude/rules/dna-operacional.md +53 -0
- package/.claude/rules/evolucao-incremental.md +43 -0
- package/.claude/rules/mcp-usage.md +38 -0
- package/.claude/rules/memoria-inteligente.md +65 -0
- package/.claude/rules/project-tracker.md +49 -0
- package/.claude/rules/tool-response-filtering.md +57 -0
- package/.claude/settings.json +1 -0
- package/.claude/settings.local.json +33 -0
- package/.env.example +22 -0
- package/.gitignore +23 -0
- package/.synapse/constitution +21 -0
- package/.synapse/context +8 -0
- package/.synapse/global +10 -0
- package/.synapse/manifest +35 -0
- package/README.md +67 -0
- package/agents/companion/agents/companion.md +306 -0
- package/agents/companion/data/contexto-dinamico.md +23 -0
- package/agents/companion/data/demandas-backlog.md +19 -0
- package/agents/companion/data/log-decisoes.md +11 -0
- package/agents/companion/data/padroes-observados.md +10 -0
- package/agents/companion/knowledge/companion-foundation.md +49 -0
- package/agents/companion/knowledge/expert-essencial.md +30 -0
- package/agents/companion/knowledge/modus-operandi.md +161 -0
- package/agents/companion/tasks/new-project.md +111 -0
- package/agents/companion/tasks/save-memory.md +73 -0
- package/agents/companion/tasks/start.md +136 -0
- package/agents/companion/tasks/weekly-review.md +82 -0
- package/bin/auroq-os.js +346 -0
- package/business/campanhas/_template/BRIEFING.md +45 -0
- package/business/campanhas/_template/CHECKLIST.md +29 -0
- package/business/campanhas/_template/DIARIO.md +15 -0
- package/business/campanhas/_template/RETROVISOR.md +34 -0
- package/business/cockpit.md +72 -0
- package/business/templates/tracker-template.md +71 -0
- package/docs/knowledge/expert-business/posicionamento.md +27 -0
- package/docs/knowledge/expert-business/publico-alvo.md +39 -0
- package/docs/knowledge/expert-mind/historia.md +27 -0
- package/docs/knowledge/expert-mind/identidade.md +23 -0
- package/docs/knowledge/expert-mind/tom-de-voz.md +30 -0
- package/docs/knowledge/expert-mind/valores.md +32 -0
- package/package.json +26 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Auroq OS — Constitution
|
|
2
|
+
|
|
3
|
+
> Principios inegociaveis do framework. Governam o comportamento de todos os agentes, squads, workers e minds dentro do Auroq OS.
|
|
4
|
+
|
|
5
|
+
**Version:** 1.0.0
|
|
6
|
+
**Status:** Active
|
|
7
|
+
**Effective Date:** 2026-03-16
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Artigo I — Claude Code e o Centro de Comando
|
|
12
|
+
|
|
13
|
+
**Severity:** NON-NEGOTIABLE
|
|
14
|
+
**Gate:** WARN
|
|
15
|
+
|
|
16
|
+
Toda operacao do negocio passa pelo Claude Code no terminal. Claude Code e o centro de comando — o SO de IA materializado. Ferramentas externas (ManyChat, Hotmart, Meta Ads, N8N, etc.) sao **bracos e pernas**, nao centros alternativos.
|
|
17
|
+
|
|
18
|
+
**Implicacoes:**
|
|
19
|
+
- Decisoes estrategicas: dentro do Claude Code com o Companion
|
|
20
|
+
- Planejamento: dentro do Claude Code com documentos .md
|
|
21
|
+
- Execucao operacional: Claude Code coordena, ferramentas executam
|
|
22
|
+
- Memoria e contexto: persistem no Exocortex (pastas e documentos locais)
|
|
23
|
+
|
|
24
|
+
**Violacao:** Operar o negocio exclusivamente em ferramentas externas sem documentar no sistema.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Artigo II — Cada Um Faz o Seu
|
|
29
|
+
|
|
30
|
+
**Severity:** NON-NEGOTIABLE
|
|
31
|
+
**Gate:** Via definicao de agente
|
|
32
|
+
|
|
33
|
+
Agentes tem dominios exclusivos. Operacoes criticas requerem o agente designado.
|
|
34
|
+
|
|
35
|
+
**Delegation Matrix:**
|
|
36
|
+
|
|
37
|
+
| Operacao | Agente Exclusivo |
|
|
38
|
+
|----------|-----------------|
|
|
39
|
+
| git push, commit, deploy | Ops |
|
|
40
|
+
| Governanca do framework, criacao de agentes | Aurora (auroq-master) |
|
|
41
|
+
| Decisoes estrategicas | Expert + Companion |
|
|
42
|
+
| Execucao operacional | Workers + Squads |
|
|
43
|
+
| Pesquisa e analise | Atlas (analyst) |
|
|
44
|
+
|
|
45
|
+
**Implicacoes:**
|
|
46
|
+
- Um agente nao invade o dominio de outro
|
|
47
|
+
- Se precisa de operacao exclusiva de outro agente, delega
|
|
48
|
+
- Em caso de conflito de boundary, Aurora media
|
|
49
|
+
|
|
50
|
+
**Violacao:** Agente executando operacao exclusiva de outro sem delegacao.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Artigo III — Documentar = Investir
|
|
55
|
+
|
|
56
|
+
**Severity:** MUST
|
|
57
|
+
**Gate:** BLOCK
|
|
58
|
+
|
|
59
|
+
Todo trabalho significativo gera documento. Nada existe so na conversa. O que nao e documentado, morre. O que e documentado, vira poder acumulado.
|
|
60
|
+
|
|
61
|
+
**Implicacoes:**
|
|
62
|
+
- Todo projeto comeca com documento estruturado (briefing/plano)
|
|
63
|
+
- Progresso atualizado no documento de trabalho a cada etapa
|
|
64
|
+
- Decisoes registradas com racional
|
|
65
|
+
- Aprendizados consolidados no Exocortex
|
|
66
|
+
- Antes de autocompact: salvar estado no documento
|
|
67
|
+
|
|
68
|
+
**Violacao:** Trabalho extenso sem documento de acompanhamento. Output que existe so na conversa.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Artigo IV — Nao Inventar
|
|
73
|
+
|
|
74
|
+
**Severity:** MUST
|
|
75
|
+
**Gate:** BLOCK
|
|
76
|
+
|
|
77
|
+
Agentes executam o que foi planejado e fundamentam em repertorio. Nao viajam, nao inventam, nao adicionam o que nao foi pedido.
|
|
78
|
+
|
|
79
|
+
**Implicacoes:**
|
|
80
|
+
- Execucao segue o plano aprovado
|
|
81
|
+
- Output fundamentado em KB, conhecimento tratado ou instrucao explicita do expert
|
|
82
|
+
- Se o agente percebe necessidade de mudar o plano, PARA e pergunta
|
|
83
|
+
- Nao adicionar "melhorias" nao solicitadas
|
|
84
|
+
- Nao gerar dados, numeros ou fatos sem fonte
|
|
85
|
+
|
|
86
|
+
**Violacao:** Agente inventando conteudo, mudando escopo sem aprovacao, gerando informacao sem fundamento.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Artigo V — Qualidade com Julgamento
|
|
91
|
+
|
|
92
|
+
**Severity:** MUST
|
|
93
|
+
**Gate:** BLOCK
|
|
94
|
+
|
|
95
|
+
Output sem verificacao nao e output. O expert julga — a IA nao se auto-aprova em entregas significativas.
|
|
96
|
+
|
|
97
|
+
**Implicacoes:**
|
|
98
|
+
- Quality gates em pontos criticos de workflows
|
|
99
|
+
- Separacao de papeis: quem executa nao se auto-valida
|
|
100
|
+
- Expert tem a palavra final em entregas importantes
|
|
101
|
+
- Verificacao tecnica (checklist) + humana (julgamento do expert)
|
|
102
|
+
|
|
103
|
+
**Violacao:** Agente entregando output critico sem quality gate ou sem aprovacao do expert.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Artigo VI — Evolucao Incremental
|
|
108
|
+
|
|
109
|
+
**Severity:** SHOULD
|
|
110
|
+
**Gate:** WARN
|
|
111
|
+
|
|
112
|
+
Nunca do zero. Sempre verificar o que ja existe antes de criar. O sistema evolui, nao e reconstruido.
|
|
113
|
+
|
|
114
|
+
**Hierarquia:** REUSE > ADAPT > CREATE
|
|
115
|
+
|
|
116
|
+
| Acao | Quando |
|
|
117
|
+
|------|--------|
|
|
118
|
+
| **REUSE** | Se ja existe algo que resolve | Usar direto |
|
|
119
|
+
| **ADAPT** | Se existe algo parecido | Adaptar o existente |
|
|
120
|
+
| **CREATE** | Se nao existe nada | Criar do zero |
|
|
121
|
+
|
|
122
|
+
**Implicacoes:**
|
|
123
|
+
- Antes de criar documento: verificar se ja existe na biblioteca
|
|
124
|
+
- Antes de criar agente: verificar se ja existe squad/worker/mind que resolve
|
|
125
|
+
- Antes de criar processo: verificar se ja existe SOP documentado
|
|
126
|
+
- Templates de campanha sao reutilizados, nao recriados
|
|
127
|
+
- Cada iteracao melhora o existente — nao substitui
|
|
128
|
+
|
|
129
|
+
**Violacao:** Criar do zero algo que ja existe no sistema ou pode ser adaptado.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Governanca
|
|
134
|
+
|
|
135
|
+
### Amendments
|
|
136
|
+
Constitution pode ser modificada via:
|
|
137
|
+
1. Expert identifica necessidade de mudanca
|
|
138
|
+
2. Aurora avalia impacto nos artigos existentes
|
|
139
|
+
3. Expert aprova a mudanca
|
|
140
|
+
4. Versao incrementada (MAJOR para artigos NON-NEGOTIABLE, MINOR para MUST/SHOULD)
|
|
141
|
+
|
|
142
|
+
### Compliance
|
|
143
|
+
- Agentes verificam artigos relevantes antes de executar
|
|
144
|
+
- Quality gates referenciam artigos da Constitution
|
|
145
|
+
- Violacoes geram WARN (SHOULD) ou BLOCK (MUST/NON-NEGOTIABLE)
|
|
146
|
+
|
|
147
|
+
### Gate Severity
|
|
148
|
+
|
|
149
|
+
| Severity | Comportamento |
|
|
150
|
+
|----------|--------------|
|
|
151
|
+
| **NON-NEGOTIABLE** | Jamais violado. Sem excecao |
|
|
152
|
+
| **MUST** | BLOCK — impede execucao ate correcao |
|
|
153
|
+
| **SHOULD** | WARN — alerta mas permite continuar |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build a normalized context payload for SYNAPSE layer execution.
|
|
5
|
+
*
|
|
6
|
+
* Centralizing this shape avoids drift between engine callers and ensures
|
|
7
|
+
* all layers always receive the same contract.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} params
|
|
10
|
+
* @param {string} params.prompt
|
|
11
|
+
* @param {Object} params.session
|
|
12
|
+
* @param {Object} params.config
|
|
13
|
+
* @param {string} params.synapsePath
|
|
14
|
+
* @param {Object} [params.manifest]
|
|
15
|
+
* @param {Array<Object>} [params.previousLayers]
|
|
16
|
+
* @returns {{prompt: string, session: Object, config: Object, previousLayers: Array<Object>}}
|
|
17
|
+
*/
|
|
18
|
+
function buildLayerContext(params) {
|
|
19
|
+
const safeParams = params || {};
|
|
20
|
+
return {
|
|
21
|
+
prompt: safeParams.prompt || '',
|
|
22
|
+
session: safeParams.session || {},
|
|
23
|
+
config: {
|
|
24
|
+
...(safeParams.config || {}),
|
|
25
|
+
synapsePath: safeParams.synapsePath,
|
|
26
|
+
manifest: safeParams.manifest || {},
|
|
27
|
+
},
|
|
28
|
+
previousLayers: Array.isArray(safeParams.previousLayers) ? safeParams.previousLayers : [],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
buildLayerContext,
|
|
34
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SYNAPSE Context Bracket Tracker
|
|
3
|
+
*
|
|
4
|
+
* Calculates the current context bracket (FRESH/MODERATE/DEPLETED/CRITICAL)
|
|
5
|
+
* based on estimated token usage. Provides token budgets and layer filtering
|
|
6
|
+
* per bracket for the SynapseEngine orchestrator.
|
|
7
|
+
*
|
|
8
|
+
* Pure arithmetic module — zero I/O, zero external dependencies.
|
|
9
|
+
*
|
|
10
|
+
* @module core/synapse/context/context-tracker
|
|
11
|
+
* @version 1.0.0
|
|
12
|
+
* @created Story SYN-3 - Context Bracket Tracker
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Bracket definitions with thresholds and token budgets.
|
|
17
|
+
*
|
|
18
|
+
* Thresholds represent the percentage of context remaining:
|
|
19
|
+
* - FRESH: 60-100% remaining (lean injection)
|
|
20
|
+
* - MODERATE: 40-60% remaining (standard injection)
|
|
21
|
+
* - DEPLETED: 25-40% remaining (reinforcement injection)
|
|
22
|
+
* - CRITICAL: 0-25% remaining (warning + handoff prep)
|
|
23
|
+
*
|
|
24
|
+
* @type {Object.<string, {min: number, max: number, tokenBudget: number}>}
|
|
25
|
+
*/
|
|
26
|
+
const BRACKETS = {
|
|
27
|
+
FRESH: { min: 60, max: 100, tokenBudget: 800 },
|
|
28
|
+
MODERATE: { min: 40, max: 60, tokenBudget: 1500 },
|
|
29
|
+
DEPLETED: { min: 25, max: 40, tokenBudget: 2000 },
|
|
30
|
+
CRITICAL: { min: 0, max: 25, tokenBudget: 2500 },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Token budget constants per bracket (shorthand access).
|
|
35
|
+
*
|
|
36
|
+
* @type {Object.<string, number>}
|
|
37
|
+
*/
|
|
38
|
+
const TOKEN_BUDGETS = {
|
|
39
|
+
FRESH: 800,
|
|
40
|
+
MODERATE: 1500,
|
|
41
|
+
DEPLETED: 2000,
|
|
42
|
+
CRITICAL: 2500,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Safety multiplier for XML-heavy output (SYNAPSE rules).
|
|
47
|
+
* chars/4 underestimates by 15-25% on XML; 1.2x corrects this.
|
|
48
|
+
* @see NOG-9 research C6-token-budget.md
|
|
49
|
+
*/
|
|
50
|
+
const XML_SAFETY_MULTIPLIER = 1.2;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Default configuration values.
|
|
54
|
+
*/
|
|
55
|
+
const DEFAULTS = {
|
|
56
|
+
avgTokensPerPrompt: 1500,
|
|
57
|
+
maxContext: 200000,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Layer configurations per bracket.
|
|
62
|
+
*
|
|
63
|
+
* FRESH: L0 (Constitution), L1 (Global), L2 (Agent), L7 (Star-Command if explicit)
|
|
64
|
+
* MODERATE: All 8 layers active
|
|
65
|
+
* DEPLETED: All layers + memory hints enabled
|
|
66
|
+
* CRITICAL: All layers + memory hints + handoff warning
|
|
67
|
+
*/
|
|
68
|
+
const LAYER_CONFIGS = {
|
|
69
|
+
FRESH: { layers: [0, 1, 2, 7], memoryHints: false, handoffWarning: false },
|
|
70
|
+
MODERATE: { layers: [0, 1, 2, 3, 4, 5, 6, 7], memoryHints: false, handoffWarning: false },
|
|
71
|
+
DEPLETED: { layers: [0, 1, 2, 3, 4, 5, 6, 7], memoryHints: true, handoffWarning: false },
|
|
72
|
+
CRITICAL: { layers: [0, 1, 2, 3, 4, 5, 6, 7], memoryHints: true, handoffWarning: true },
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Calculate the context bracket based on remaining context percentage.
|
|
77
|
+
*
|
|
78
|
+
* @param {number} contextPercent - Percentage of context remaining (0-100)
|
|
79
|
+
* @returns {string} Bracket name: 'FRESH' | 'MODERATE' | 'DEPLETED' | 'CRITICAL'
|
|
80
|
+
*/
|
|
81
|
+
function calculateBracket(contextPercent) {
|
|
82
|
+
if (typeof contextPercent !== 'number' || isNaN(contextPercent)) {
|
|
83
|
+
return 'CRITICAL';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (contextPercent >= 60) {
|
|
87
|
+
return 'FRESH';
|
|
88
|
+
}
|
|
89
|
+
if (contextPercent >= 40) {
|
|
90
|
+
return 'MODERATE';
|
|
91
|
+
}
|
|
92
|
+
if (contextPercent >= 25) {
|
|
93
|
+
return 'DEPLETED';
|
|
94
|
+
}
|
|
95
|
+
return 'CRITICAL';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Estimate the percentage of context remaining based on prompt count.
|
|
100
|
+
*
|
|
101
|
+
* Formula: 100 - ((promptCount * avgTokensPerPrompt) / maxContext * 100)
|
|
102
|
+
* Result is clamped to 0-100 range.
|
|
103
|
+
*
|
|
104
|
+
* @param {number} promptCount - Number of prompts in current session
|
|
105
|
+
* @param {Object} [options={}] - Configuration options
|
|
106
|
+
* @param {number} [options.avgTokensPerPrompt=1500] - Average tokens per prompt
|
|
107
|
+
* @param {number} [options.maxContext=200000] - Maximum context window size in tokens
|
|
108
|
+
* @returns {number} Percentage of context remaining (0.0 to 100.0)
|
|
109
|
+
*/
|
|
110
|
+
function estimateContextPercent(promptCount, options = {}) {
|
|
111
|
+
const {
|
|
112
|
+
avgTokensPerPrompt = DEFAULTS.avgTokensPerPrompt,
|
|
113
|
+
maxContext = DEFAULTS.maxContext,
|
|
114
|
+
} = options;
|
|
115
|
+
|
|
116
|
+
if (typeof promptCount !== 'number' || isNaN(promptCount) || promptCount < 0) {
|
|
117
|
+
return 100;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (maxContext <= 0) {
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const usedTokens = promptCount * avgTokensPerPrompt * XML_SAFETY_MULTIPLIER;
|
|
125
|
+
const percent = 100 - (usedTokens / maxContext * 100);
|
|
126
|
+
return Math.max(0, Math.min(100, percent));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get the maximum token budget for injection at the given bracket.
|
|
131
|
+
*
|
|
132
|
+
* @param {string} bracket - Bracket name ('FRESH' | 'MODERATE' | 'DEPLETED' | 'CRITICAL')
|
|
133
|
+
* @returns {number|null} Max tokens for injection, or null for invalid bracket
|
|
134
|
+
*/
|
|
135
|
+
function getTokenBudget(bracket) {
|
|
136
|
+
if (TOKEN_BUDGETS[bracket] !== undefined) {
|
|
137
|
+
return TOKEN_BUDGETS[bracket];
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get the active layer configuration for a given bracket.
|
|
144
|
+
*
|
|
145
|
+
* Returns an object with:
|
|
146
|
+
* - layers: array of active layer numbers (0-7)
|
|
147
|
+
* - memoryHints: whether memory hints should be included
|
|
148
|
+
* - handoffWarning: whether a context handoff warning should be shown
|
|
149
|
+
*
|
|
150
|
+
* @param {string} bracket - Bracket name ('FRESH' | 'MODERATE' | 'DEPLETED' | 'CRITICAL')
|
|
151
|
+
* @returns {{ layers: number[], memoryHints: boolean, handoffWarning: boolean }|null}
|
|
152
|
+
* Layer config object, or null for invalid bracket
|
|
153
|
+
*/
|
|
154
|
+
function getActiveLayers(bracket) {
|
|
155
|
+
const config = LAYER_CONFIGS[bracket];
|
|
156
|
+
if (!config) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
// Return a copy to prevent mutation
|
|
160
|
+
return {
|
|
161
|
+
layers: [...config.layers],
|
|
162
|
+
memoryHints: config.memoryHints,
|
|
163
|
+
handoffWarning: config.handoffWarning,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Check if the given bracket requires a context handoff warning.
|
|
169
|
+
*
|
|
170
|
+
* @param {string} bracket - Bracket name
|
|
171
|
+
* @returns {boolean} True if bracket is CRITICAL
|
|
172
|
+
*/
|
|
173
|
+
function needsHandoffWarning(bracket) {
|
|
174
|
+
return bracket === 'CRITICAL';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Check if the given bracket should include memory hints.
|
|
179
|
+
*
|
|
180
|
+
* @param {string} bracket - Bracket name
|
|
181
|
+
* @returns {boolean} True if bracket is DEPLETED or CRITICAL
|
|
182
|
+
*/
|
|
183
|
+
function needsMemoryHints(bracket) {
|
|
184
|
+
return bracket === 'DEPLETED' || bracket === 'CRITICAL';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
calculateBracket,
|
|
189
|
+
estimateContextPercent,
|
|
190
|
+
getTokenBudget,
|
|
191
|
+
getActiveLayers,
|
|
192
|
+
needsHandoffWarning,
|
|
193
|
+
needsMemoryHints,
|
|
194
|
+
BRACKETS,
|
|
195
|
+
TOKEN_BUDGETS,
|
|
196
|
+
DEFAULTS,
|
|
197
|
+
XML_SAFETY_MULTIPLIER,
|
|
198
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistency Collector — Cross-validates UAP and Hook metrics for coherence.
|
|
3
|
+
*
|
|
4
|
+
* Performs 4 consistency checks between the two pipeline metrics files:
|
|
5
|
+
* 1. Bracket consistency — Hook bracket matches expected for session state
|
|
6
|
+
* 2. Agent consistency — UAP agentId matches Hook session active_agent
|
|
7
|
+
* 3. Timestamp consistency — Both metrics from same activation window
|
|
8
|
+
* 4. Quality consistency — UAP quality aligns with Hook layer count
|
|
9
|
+
*
|
|
10
|
+
* @module core/synapse/diagnostics/collectors/consistency-collector
|
|
11
|
+
* @version 1.0.0
|
|
12
|
+
* @created Story SYN-14
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const { safeReadJson } = require('./safe-read-json');
|
|
19
|
+
|
|
20
|
+
/** Maximum time gap (ms) between UAP and Hook timestamps to be considered consistent.
|
|
21
|
+
* UAP writes once at activation; Hook writes every prompt. Gaps of several minutes are normal.
|
|
22
|
+
*/
|
|
23
|
+
const MAX_TIMESTAMP_GAP_MS = 10 * 60 * 1000;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Collect cross-pipeline consistency checks.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
29
|
+
* @returns {{
|
|
30
|
+
* available: boolean,
|
|
31
|
+
* checks: Array<{ name: string, status: string, detail: string }>,
|
|
32
|
+
* score: number,
|
|
33
|
+
* maxScore: number
|
|
34
|
+
* }}
|
|
35
|
+
*/
|
|
36
|
+
function collectConsistencyMetrics(projectRoot) {
|
|
37
|
+
const metricsDir = path.join(projectRoot, '.synapse', 'metrics');
|
|
38
|
+
|
|
39
|
+
const uapData = safeReadJson(path.join(metricsDir, 'uap-metrics.json'));
|
|
40
|
+
const hookData = safeReadJson(path.join(metricsDir, 'hook-metrics.json'));
|
|
41
|
+
|
|
42
|
+
if (!uapData && !hookData) {
|
|
43
|
+
return { available: false, checks: [], score: 0, maxScore: 0 };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// If only one side exists, partial consistency is possible
|
|
47
|
+
if (!uapData || !hookData) {
|
|
48
|
+
return {
|
|
49
|
+
available: true,
|
|
50
|
+
checks: [{
|
|
51
|
+
name: 'data-completeness',
|
|
52
|
+
status: 'WARN',
|
|
53
|
+
detail: !uapData ? 'UAP metrics missing — only Hook available' : 'Hook metrics missing — only UAP available',
|
|
54
|
+
}],
|
|
55
|
+
score: 0,
|
|
56
|
+
maxScore: 4,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const checks = [];
|
|
61
|
+
let score = 0;
|
|
62
|
+
const maxScore = 4;
|
|
63
|
+
|
|
64
|
+
// Check 1: Bracket consistency
|
|
65
|
+
const bracketCheck = _checkBracket(hookData);
|
|
66
|
+
checks.push(bracketCheck);
|
|
67
|
+
if (bracketCheck.status === 'PASS') score++;
|
|
68
|
+
|
|
69
|
+
// Check 2: Agent consistency
|
|
70
|
+
const agentCheck = _checkAgent(uapData, projectRoot);
|
|
71
|
+
checks.push(agentCheck);
|
|
72
|
+
if (agentCheck.status === 'PASS') score++;
|
|
73
|
+
|
|
74
|
+
// Check 3: Timestamp consistency
|
|
75
|
+
const timestampCheck = _checkTimestamp(uapData, hookData);
|
|
76
|
+
checks.push(timestampCheck);
|
|
77
|
+
if (timestampCheck.status === 'PASS') score++;
|
|
78
|
+
|
|
79
|
+
// Check 4: Quality consistency
|
|
80
|
+
const qualityCheck = _checkQuality(uapData, hookData);
|
|
81
|
+
checks.push(qualityCheck);
|
|
82
|
+
if (qualityCheck.status === 'PASS') score++;
|
|
83
|
+
|
|
84
|
+
return { available: true, checks, score, maxScore };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check 1: Bracket is a known value.
|
|
89
|
+
* @param {Object} hookData
|
|
90
|
+
* @returns {{ name: string, status: string, detail: string }}
|
|
91
|
+
*/
|
|
92
|
+
function _checkBracket(hookData) {
|
|
93
|
+
const validBrackets = ['FRESH', 'MODERATE', 'DEPLETED', 'CRITICAL'];
|
|
94
|
+
const bracket = hookData.bracket;
|
|
95
|
+
if (validBrackets.includes(bracket)) {
|
|
96
|
+
return { name: 'bracket', status: 'PASS', detail: `Hook bracket: ${bracket}` };
|
|
97
|
+
}
|
|
98
|
+
return { name: 'bracket', status: 'FAIL', detail: `Unknown bracket: ${bracket || 'undefined'}` };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check 2: UAP agentId matches _active-agent.json bridge file.
|
|
103
|
+
* @param {Object} uapData
|
|
104
|
+
* @param {string} projectRoot
|
|
105
|
+
* @returns {{ name: string, status: string, detail: string }}
|
|
106
|
+
*/
|
|
107
|
+
function _checkAgent(uapData, projectRoot) {
|
|
108
|
+
const bridgePath = path.join(projectRoot, '.synapse', 'sessions', '_active-agent.json');
|
|
109
|
+
const bridgeData = safeReadJson(bridgePath);
|
|
110
|
+
|
|
111
|
+
if (!bridgeData || !bridgeData.id) {
|
|
112
|
+
return { name: 'agent', status: 'WARN', detail: 'No active-agent bridge file found' };
|
|
113
|
+
}
|
|
114
|
+
if (uapData.agentId === bridgeData.id) {
|
|
115
|
+
return { name: 'agent', status: 'PASS', detail: `Agent match: ${uapData.agentId}` };
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
name: 'agent',
|
|
119
|
+
status: 'FAIL',
|
|
120
|
+
detail: `UAP agent (${uapData.agentId}) != bridge agent (${bridgeData.id})`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check 3: UAP and Hook timestamps are within MAX_TIMESTAMP_GAP_MS.
|
|
126
|
+
* @param {Object} uapData
|
|
127
|
+
* @param {Object} hookData
|
|
128
|
+
* @returns {{ name: string, status: string, detail: string }}
|
|
129
|
+
*/
|
|
130
|
+
function _checkTimestamp(uapData, hookData) {
|
|
131
|
+
if (!uapData.timestamp || !hookData.timestamp) {
|
|
132
|
+
return { name: 'timestamp', status: 'WARN', detail: 'Missing timestamp in one or both metrics' };
|
|
133
|
+
}
|
|
134
|
+
const gap = Math.abs(new Date(uapData.timestamp).getTime() - new Date(hookData.timestamp).getTime());
|
|
135
|
+
if (gap <= MAX_TIMESTAMP_GAP_MS) {
|
|
136
|
+
return { name: 'timestamp', status: 'PASS', detail: `Gap: ${Math.round(gap / 1000)}s (within ${MAX_TIMESTAMP_GAP_MS / 1000}s)` };
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
name: 'timestamp',
|
|
140
|
+
status: 'FAIL',
|
|
141
|
+
detail: `Gap: ${Math.round(gap / 1000)}s (exceeds ${MAX_TIMESTAMP_GAP_MS / 1000}s threshold)`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Check 4: UAP quality aligns with Hook layer count.
|
|
147
|
+
* 'full' quality should have layers loaded; 'fallback' may have zero.
|
|
148
|
+
* @param {Object} uapData
|
|
149
|
+
* @param {Object} hookData
|
|
150
|
+
* @returns {{ name: string, status: string, detail: string }}
|
|
151
|
+
*/
|
|
152
|
+
function _checkQuality(uapData, hookData) {
|
|
153
|
+
const quality = uapData.quality;
|
|
154
|
+
const layersLoaded = hookData.layersLoaded || 0;
|
|
155
|
+
|
|
156
|
+
if (quality === 'fallback' && layersLoaded > 0) {
|
|
157
|
+
return { name: 'quality', status: 'PASS', detail: `UAP fallback but Hook loaded ${layersLoaded} layers (Hook independent)` };
|
|
158
|
+
}
|
|
159
|
+
if (quality === 'full' && layersLoaded === 0) {
|
|
160
|
+
return { name: 'quality', status: 'WARN', detail: 'UAP full quality but Hook loaded 0 layers' };
|
|
161
|
+
}
|
|
162
|
+
if (quality === 'full' && layersLoaded > 0) {
|
|
163
|
+
return { name: 'quality', status: 'PASS', detail: `UAP ${quality}, Hook ${layersLoaded} layers` };
|
|
164
|
+
}
|
|
165
|
+
return { name: 'quality', status: 'PASS', detail: `UAP ${quality || 'unknown'}, Hook ${layersLoaded} layers` };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = { collectConsistencyMetrics, MAX_TIMESTAMP_GAP_MS };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Collector — Verifies SYNAPSE hook registration and file integrity.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* - settings.local.json has UserPromptSubmit hook entry
|
|
6
|
+
* - Hook file exists at expected path
|
|
7
|
+
* - Hook file is valid Node.js (can be required)
|
|
8
|
+
*
|
|
9
|
+
* @module core/synapse/diagnostics/collectors/hook-collector
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
* @created Story SYN-13
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Collect hook registration and integrity data.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
23
|
+
* @returns {{ checks: Array<{ name: string, status: string, detail: string }> }}
|
|
24
|
+
*/
|
|
25
|
+
function collectHookStatus(projectRoot) {
|
|
26
|
+
const checks = [];
|
|
27
|
+
|
|
28
|
+
// Check 1: settings.local.json has hook entry
|
|
29
|
+
const settingsPath = path.join(projectRoot, '.claude', 'settings.local.json');
|
|
30
|
+
let hasHookRegistered = false;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
if (fs.existsSync(settingsPath)) {
|
|
34
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
35
|
+
const hooks = settings.hooks || {};
|
|
36
|
+
const promptHooks = hooks.UserPromptSubmit || hooks.userPromptSubmit || [];
|
|
37
|
+
|
|
38
|
+
hasHookRegistered = promptHooks.some((entry) => {
|
|
39
|
+
// Flat format: { command: "node ..." } or string
|
|
40
|
+
const flatCmd = typeof entry === 'string' ? entry : (entry.command || '');
|
|
41
|
+
if (flatCmd.includes('synapse-engine')) return true;
|
|
42
|
+
// Nested format (Claude Code actual): { hooks: [{ type, command }] }
|
|
43
|
+
if (Array.isArray(entry.hooks)) {
|
|
44
|
+
return entry.hooks.some((h) => {
|
|
45
|
+
const cmd = typeof h === 'string' ? h : (h.command || '');
|
|
46
|
+
return cmd.includes('synapse-engine');
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
checks.push({
|
|
53
|
+
name: 'Hook registered',
|
|
54
|
+
status: hasHookRegistered ? 'PASS' : 'FAIL',
|
|
55
|
+
detail: hasHookRegistered
|
|
56
|
+
? 'settings.local.json has UserPromptSubmit entry for synapse-engine'
|
|
57
|
+
: 'No synapse-engine hook found in settings.local.json',
|
|
58
|
+
});
|
|
59
|
+
} else {
|
|
60
|
+
checks.push({
|
|
61
|
+
name: 'Hook registered',
|
|
62
|
+
status: 'FAIL',
|
|
63
|
+
detail: 'settings.local.json not found',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
checks.push({
|
|
68
|
+
name: 'Hook registered',
|
|
69
|
+
status: 'ERROR',
|
|
70
|
+
detail: `Failed to read settings: ${error.message}`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check 2: Hook file exists
|
|
75
|
+
const hookPath = path.join(projectRoot, '.claude', 'hooks', 'synapse-engine.cjs');
|
|
76
|
+
const hookExists = fs.existsSync(hookPath);
|
|
77
|
+
|
|
78
|
+
if (hookExists) {
|
|
79
|
+
try {
|
|
80
|
+
const stat = fs.statSync(hookPath);
|
|
81
|
+
const lineCount = fs.readFileSync(hookPath, 'utf8').split('\n').length;
|
|
82
|
+
checks.push({
|
|
83
|
+
name: 'Hook file exists',
|
|
84
|
+
status: 'PASS',
|
|
85
|
+
detail: `.claude/hooks/synapse-engine.cjs (${lineCount} lines, ${stat.size} bytes)`,
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
checks.push({
|
|
89
|
+
name: 'Hook file exists',
|
|
90
|
+
status: 'ERROR',
|
|
91
|
+
detail: `File exists but cannot be read: ${error.message}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
checks.push({
|
|
96
|
+
name: 'Hook file exists',
|
|
97
|
+
status: 'FAIL',
|
|
98
|
+
detail: '.claude/hooks/synapse-engine.cjs not found',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check 3: Hook file is valid Node.js
|
|
103
|
+
if (hookExists) {
|
|
104
|
+
try {
|
|
105
|
+
require.resolve(hookPath);
|
|
106
|
+
checks.push({
|
|
107
|
+
name: 'Hook executable',
|
|
108
|
+
status: 'PASS',
|
|
109
|
+
detail: 'node can resolve the hook file',
|
|
110
|
+
});
|
|
111
|
+
} catch (error) {
|
|
112
|
+
checks.push({
|
|
113
|
+
name: 'Hook executable',
|
|
114
|
+
status: 'FAIL',
|
|
115
|
+
detail: `Cannot resolve: ${error.message}`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
checks.push({
|
|
120
|
+
name: 'Hook executable',
|
|
121
|
+
status: 'SKIP',
|
|
122
|
+
detail: 'Hook file does not exist',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { checks };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
module.exports = { collectHookStatus };
|