sinapse-ai 1.9.0 → 1.10.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/.claude/rules/mandatory-delegation.md +1 -1
- package/.codex/delegation-matrix.json +4 -3
- package/.codex/delegation-parity.json +4 -3
- package/.codex/instructions.md +2 -2
- package/.sinapse-ai/constitution.md +2 -2
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +76 -10
- package/.sinapse-ai/core/execution/subagent-dispatcher.js +1 -1
- package/.sinapse-ai/core/synapse/engine.js +15 -0
- package/.sinapse-ai/data/entity-registry.yaml +13 -13
- package/.sinapse-ai/development/agents/snps-orqx.md +4 -4
- package/.sinapse-ai/git-hooks/lib/secret-scanner-core.js +76 -4
- package/.sinapse-ai/git-hooks/pre-push +7 -1
- package/.sinapse-ai/install-manifest.yaml +9 -9
- package/AGENTS.md +4 -4
- package/CHANGELOG.md +1257 -0
- package/README.en.md +4 -3
- package/README.md +5 -6
- package/bin/commands/install.js +6 -3
- package/bin/commands/uninstall.js +2 -2
- package/bin/sinapse.js +20 -0
- package/bin/utils/secret-scanner-core.js +76 -4
- package/docs/agent-reference-guide.md +1 -1
- package/docs/framework/architecture-overview.md +4 -4
- package/docs/framework/guiding-principles.md +9 -9
- package/docs/getting-started.md +1 -1
- package/docs/guides/agent-reference.md +1 -1
- package/docs/guides/codex-config.md +4 -5
- package/docs/pt/architecture/sub-orqx-pattern.md +20 -18
- package/package.json +8 -2
- package/packages/installer/src/installer/git-hooks-installer.js +3 -1
- package/packages/installer/src/installer/sinapse-ai-installer.js +32 -7
- package/packages/installer/src/wizard/ide-config-generator.js +9 -1
- package/packages/installer/src/wizard/index.js +3 -4
- package/scripts/regenerate-orqx-stubs.ps1 +0 -1
- package/scripts/sync-counts.js +10 -2
- package/scripts/sync-squad-yaml-components.js +108 -6
- package/scripts/validate-article-vii.js +68 -7
- package/scripts/validate-squad-orqx.js +19 -9
- package/sinapse/agents/sinapse-orqx.md +4 -4
- package/sinapse/agents/snps-orqx.md +4 -4
- package/sinapse/knowledge-base/routing-catalog.md +1 -1
- package/sinapse/tasks/diagnose-and-route.md +1 -1
- package/sinapse/tasks/squad-status-report.md +1 -1
- package/squads/claude-code-mastery/agents/claude-mastery-chief.md +1 -1
- package/squads/claude-code-mastery/agents/hooks-architect.md +60 -68
- package/squads/claude-code-mastery/knowledge-base/swarm-orchestration-patterns.md +1 -1
- package/squads/claude-code-mastery/tasks/audit-setup.md +1 -1
- package/squads/claude-code-mastery/workflows/optimization-cycle.yaml +4 -4
- package/squads/claude-code-mastery/workflows/project-setup-cycle.yaml +4 -4
- package/squads/squad-animations/README.md +1 -1
- package/squads/squad-cloning/README.md +1 -1
- package/squads/squad-commercial/README.md +1 -1
- package/squads/squad-content/README.md +1 -1
- package/squads/squad-copy/README.md +1 -1
- package/squads/squad-council/README.md +1 -1
- package/squads/squad-courses/README.md +1 -1
- package/squads/squad-cybersecurity/README.md +1 -1
- package/squads/squad-design/README.md +1 -1
- package/squads/squad-finance/README.md +1 -1
- package/squads/squad-growth/README.md +1 -1
- package/squads/squad-paidmedia/README.md +1 -1
- package/squads/squad-product/README.md +1 -1
- package/squads/squad-research/README.md +1 -1
- package/squads/squad-storytelling/README.md +1 -1
- package/.sinapse-ai/core/memory/__tests__/active-modules.verify.js +0 -265
- package/.sinapse-ai/core/permissions/__tests__/permission-mode.test.js +0 -293
- package/.sinapse-ai/infrastructure/tests/project-status-loader.test.js +0 -569
- package/.sinapse-ai/infrastructure/tests/regression-suite-v2.md +0 -622
- package/.sinapse-ai/infrastructure/tests/validate-module.js +0 -98
- package/.sinapse-ai/infrastructure/tests/worktree-manager.test.js +0 -620
- package/.sinapse-ai/workflow-intelligence/__tests__/confidence-scorer.test.js +0 -335
- package/.sinapse-ai/workflow-intelligence/__tests__/integration.test.js +0 -340
- package/.sinapse-ai/workflow-intelligence/__tests__/suggestion-engine.test.js +0 -438
- package/.sinapse-ai/workflow-intelligence/__tests__/wave-analyzer.test.js +0 -448
- package/.sinapse-ai/workflow-intelligence/__tests__/workflow-registry.test.js +0 -303
- package/packages/installer/src/__tests__/performance-benchmark.js +0 -383
- package/packages/installer/tests/integration/environment-configuration.test.js +0 -332
- package/packages/installer/tests/integration/wizard-detection.test.js +0 -352
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +0 -402
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +0 -193
- package/packages/installer/tests/unit/config-validator.test.js +0 -315
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +0 -539
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +0 -675
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +0 -192
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +0 -192
- package/packages/installer/tests/unit/env-template.test.js +0 -187
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +0 -310
- package/packages/installer/tests/unit/git-hooks-installer.test.js +0 -262
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +0 -231
- package/packages/installer/tests/unit/merger/env-merger.test.js +0 -191
- package/packages/installer/tests/unit/merger/markdown-merger.test.js +0 -262
- package/packages/installer/tests/unit/merger/strategies.test.js +0 -154
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +0 -328
- package/packages/sinapse-install/tests/unit/chrome-brain.smoke.test.js +0 -66
|
@@ -320,14 +320,13 @@ function llmLabel(selectedLLM) {
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
/**
|
|
323
|
-
*
|
|
323
|
+
* 18 orqx agent definitions to install globally (17 squad orqx + 1 master).
|
|
324
324
|
* Each entry maps agent-id to its squad directory name.
|
|
325
325
|
*/
|
|
326
326
|
const GLOBAL_AGENTS = [
|
|
327
327
|
{ id: 'sinapse-orqx', squad: 'sinapse' },
|
|
328
328
|
{ id: 'animations-orqx', squad: 'squad-animations' },
|
|
329
329
|
{ id: 'brand-orqx', squad: 'squad-brand' },
|
|
330
|
-
{ id: 'claude-orqx', squad: 'squad-claude' },
|
|
331
330
|
{ id: 'cloning-orqx', squad: 'squad-cloning' },
|
|
332
331
|
{ id: 'commercial-orqx', squad: 'squad-commercial' },
|
|
333
332
|
{ id: 'content-orqx', squad: 'squad-content' },
|
|
@@ -342,7 +341,7 @@ const GLOBAL_AGENTS = [
|
|
|
342
341
|
{ id: 'product-orqx', squad: 'squad-product' },
|
|
343
342
|
{ id: 'research-orqx', squad: 'squad-research' },
|
|
344
343
|
{ id: 'storytelling-orqx', squad: 'squad-storytelling' },
|
|
345
|
-
{ id: 'swarm-orqx', squad: '
|
|
344
|
+
{ id: 'swarm-orqx', squad: 'claude-code-mastery' },
|
|
346
345
|
];
|
|
347
346
|
|
|
348
347
|
/**
|
|
@@ -381,7 +380,7 @@ function buildAgentTemplate(agentId, squadName, homedir) {
|
|
|
381
380
|
}
|
|
382
381
|
|
|
383
382
|
/**
|
|
384
|
-
* Install
|
|
383
|
+
* Install 18 global orqx agent definitions to ~/.claude/agents/
|
|
385
384
|
* Each file is a small markdown that points to the full agent definition
|
|
386
385
|
* inside the user's ~/.sinapse/{squad}/ directory.
|
|
387
386
|
*
|
|
@@ -9,7 +9,6 @@ $ErrorActionPreference = 'Stop'
|
|
|
9
9
|
$mapping = @(
|
|
10
10
|
@{ id = 'animations-orqx'; squad = 'squad-animations' }
|
|
11
11
|
@{ id = 'brand-orqx'; squad = 'squad-brand' }
|
|
12
|
-
@{ id = 'claude-orqx'; squad = 'squad-claude' }
|
|
13
12
|
@{ id = 'cloning-orqx'; squad = 'squad-cloning' }
|
|
14
13
|
@{ id = 'commercial-orqx'; squad = 'squad-commercial' }
|
|
15
14
|
@{ id = 'content-orqx'; squad = 'squad-content' }
|
package/scripts/sync-counts.js
CHANGED
|
@@ -28,6 +28,11 @@ function countMatching(dir, predicate) {
|
|
|
28
28
|
let count = 0;
|
|
29
29
|
for (const entry of entries) {
|
|
30
30
|
const full = path.join(dir, entry.name);
|
|
31
|
+
// Never count anything under a _deprecated/ folder — those entities are
|
|
32
|
+
// retired (e.g. squads/claude-code-mastery/_deprecated/claude-orqx.md).
|
|
33
|
+
if (entry.name === '_deprecated' || full.includes(`${path.sep}_deprecated${path.sep}`)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
31
36
|
if (entry.isDirectory()) {
|
|
32
37
|
count += countMatching(full, predicate);
|
|
33
38
|
} else if (predicate(full, entry.name)) {
|
|
@@ -52,8 +57,11 @@ function isTaskFile(fullPath, filename) {
|
|
|
52
57
|
return fullPath.includes(`${path.sep}tasks${path.sep}`);
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
function isOrqxFile(
|
|
56
|
-
|
|
60
|
+
function isOrqxFile(fullPath, filename) {
|
|
61
|
+
// Only count orqx personas that live under a squad's agents/ directory.
|
|
62
|
+
// Guards against stray/retired orqx files outside the canonical location.
|
|
63
|
+
if (!filename.endsWith('-orqx.md')) return false;
|
|
64
|
+
return fullPath.includes(`${path.sep}agents${path.sep}`);
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
function countSquadDirs() {
|
|
@@ -15,9 +15,18 @@
|
|
|
15
15
|
* `components.agents` block based on disk reality, restoring manifest
|
|
16
16
|
* as a reliable source of truth.
|
|
17
17
|
*
|
|
18
|
+
* --check mode (E8 / auditoria-pos-190):
|
|
19
|
+
* Beyond detecting a MISSING block, --check now RECONCILES the declared
|
|
20
|
+
* agents list against the actual `.md` files on disk. It fails (exit 1) when:
|
|
21
|
+
* - a squad.yaml is missing the components.agents block (needs-update), OR
|
|
22
|
+
* - the declared list diverges from disk (drift): a declared agent has no
|
|
23
|
+
* file, or an agent file is not declared.
|
|
24
|
+
* Inline `# comments` after a filename are stripped before comparison, so a
|
|
25
|
+
* `- foo.md # Persona — Role` entry reconciles cleanly against `foo.md`.
|
|
26
|
+
*
|
|
18
27
|
* Usage:
|
|
19
28
|
* node scripts/sync-squad-yaml-components.js # apply changes
|
|
20
|
-
* node scripts/sync-squad-yaml-components.js --check # report
|
|
29
|
+
* node scripts/sync-squad-yaml-components.js --check # report + reconcile, no write
|
|
21
30
|
*/
|
|
22
31
|
|
|
23
32
|
'use strict';
|
|
@@ -64,6 +73,61 @@ function hasComponentsAgents(yamlContent) {
|
|
|
64
73
|
return false;
|
|
65
74
|
}
|
|
66
75
|
|
|
76
|
+
// parseDeclaredAgents extracts the filenames declared under components.agents.
|
|
77
|
+
// It tolerates inline `# comments` after each filename (several squad.yaml files
|
|
78
|
+
// annotate entries like `- brand-auditor.md # Sentinel — Guardian`). Returns a
|
|
79
|
+
// sorted array of bare filenames, or null if no components.agents block exists.
|
|
80
|
+
function parseDeclaredAgents(yamlContent) {
|
|
81
|
+
const lines = yamlContent.split('\n');
|
|
82
|
+
let inAgents = false;
|
|
83
|
+
let found = false;
|
|
84
|
+
const agents = [];
|
|
85
|
+
for (let i = 0; i < lines.length; i++) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
if (!inAgents) {
|
|
88
|
+
if (/^components:\s*$/.test(line)) {
|
|
89
|
+
// scan forward for the agents: sub-key (block style)
|
|
90
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
91
|
+
if (/^ {2}agents:/.test(lines[j])) {
|
|
92
|
+
inAgents = true;
|
|
93
|
+
found = true;
|
|
94
|
+
i = j; // continue after the agents: header
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
// a new top-level key ends the components: block
|
|
98
|
+
if (/^\S/.test(lines[j]) && !/^\s*#/.test(lines[j])) break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Inside the agents list: collect ` - name.md` items, stop at dedent.
|
|
104
|
+
const itemMatch = line.match(/^ {4}-\s*(.+?)\s*$/);
|
|
105
|
+
if (itemMatch) {
|
|
106
|
+
// strip an inline comment (`# ...`) and surrounding quotes/whitespace
|
|
107
|
+
let value = itemMatch[1].replace(/\s+#.*$/, '').trim();
|
|
108
|
+
value = value.replace(/^["']|["']$/g, '').trim();
|
|
109
|
+
if (value) agents.push(value);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// blank line inside the list is tolerated; anything else dedented ends it
|
|
113
|
+
if (line.trim() === '') continue;
|
|
114
|
+
if (!/^ {4}/.test(line)) break;
|
|
115
|
+
}
|
|
116
|
+
if (!found) return null;
|
|
117
|
+
return agents.sort();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// reconcileAgents compares the declared list against disk reality.
|
|
121
|
+
// Returns { declaredOnly, diskOnly } arrays (empty when in sync).
|
|
122
|
+
function reconcileAgents(declared, diskFiles) {
|
|
123
|
+
const declaredSet = new Set(declared);
|
|
124
|
+
const diskSet = new Set(diskFiles);
|
|
125
|
+
return {
|
|
126
|
+
declaredOnly: declared.filter((f) => !diskSet.has(f)), // declared, no file
|
|
127
|
+
diskOnly: diskFiles.filter((f) => !declaredSet.has(f)), // file, not declared
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
67
131
|
function buildComponentsBlock(agentFiles) {
|
|
68
132
|
const lines = ['', '# ════════════════════════════════════════════════════', '# COMPONENTS — declared agents (synced from filesystem)', '# ════════════════════════════════════════════════════', 'components:', ' agents:'];
|
|
69
133
|
for (const file of agentFiles) {
|
|
@@ -83,6 +147,20 @@ function processSquad(squadName) {
|
|
|
83
147
|
return { squadName, status: 'no-agents', changes: 0 };
|
|
84
148
|
}
|
|
85
149
|
if (hasComponentsAgents(content)) {
|
|
150
|
+
// Block is present — in --check mode, reconcile the declared list vs disk.
|
|
151
|
+
if (CHECK_ONLY) {
|
|
152
|
+
const declared = parseDeclaredAgents(content) || [];
|
|
153
|
+
const { declaredOnly, diskOnly } = reconcileAgents(declared, agents);
|
|
154
|
+
if (declaredOnly.length > 0 || diskOnly.length > 0) {
|
|
155
|
+
return {
|
|
156
|
+
squadName,
|
|
157
|
+
status: 'drift',
|
|
158
|
+
changes: declaredOnly.length + diskOnly.length,
|
|
159
|
+
declaredOnly,
|
|
160
|
+
diskOnly,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
86
164
|
return { squadName, status: 'already-declared', changes: 0 };
|
|
87
165
|
}
|
|
88
166
|
if (CHECK_ONLY) {
|
|
@@ -100,11 +178,13 @@ function run() {
|
|
|
100
178
|
let updated = 0;
|
|
101
179
|
let alreadyDeclared = 0;
|
|
102
180
|
let needsUpdate = 0;
|
|
181
|
+
let drift = 0;
|
|
103
182
|
let other = 0;
|
|
104
183
|
for (const r of results) {
|
|
105
184
|
if (r.status === 'updated') updated++;
|
|
106
185
|
else if (r.status === 'already-declared') alreadyDeclared++;
|
|
107
186
|
else if (r.status === 'needs-update') needsUpdate++;
|
|
187
|
+
else if (r.status === 'drift') drift++;
|
|
108
188
|
else other++;
|
|
109
189
|
}
|
|
110
190
|
|
|
@@ -114,17 +194,32 @@ function run() {
|
|
|
114
194
|
for (const r of results) {
|
|
115
195
|
const marker = r.status === 'updated' ? 'UPDATED'
|
|
116
196
|
: r.status === 'needs-update' ? 'NEEDS UPDATE'
|
|
197
|
+
: r.status === 'drift' ? 'DRIFT'
|
|
117
198
|
: r.status === 'already-declared' ? 'ok'
|
|
118
199
|
: r.status.toUpperCase();
|
|
119
200
|
console.log(` ${marker.padEnd(14)} ${r.squadName} (${r.changes} agent(s))`);
|
|
201
|
+
if (r.status === 'drift') {
|
|
202
|
+
if (r.declaredOnly.length > 0) {
|
|
203
|
+
console.log(` declared but no file: ${r.declaredOnly.join(', ')}`);
|
|
204
|
+
}
|
|
205
|
+
if (r.diskOnly.length > 0) {
|
|
206
|
+
console.log(` file but not declared: ${r.diskOnly.join(', ')}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
120
209
|
}
|
|
121
210
|
console.log('');
|
|
122
|
-
console.log(`Summary: ${alreadyDeclared} already declared, ${updated} updated, ${needsUpdate} need update, ${other} other`);
|
|
211
|
+
console.log(`Summary: ${alreadyDeclared} already declared, ${updated} updated, ${needsUpdate} need update, ${drift} drift, ${other} other`);
|
|
123
212
|
|
|
124
|
-
if (CHECK_ONLY && needsUpdate > 0) {
|
|
213
|
+
if (CHECK_ONLY && (needsUpdate > 0 || drift > 0)) {
|
|
125
214
|
console.error('');
|
|
126
|
-
|
|
127
|
-
|
|
215
|
+
if (needsUpdate > 0) {
|
|
216
|
+
console.error('FAIL: some squad.yaml files are missing components.agents.');
|
|
217
|
+
console.error('Run `node scripts/sync-squad-yaml-components.js` to apply.');
|
|
218
|
+
}
|
|
219
|
+
if (drift > 0) {
|
|
220
|
+
console.error('FAIL: some squad.yaml components.agents lists diverge from disk.');
|
|
221
|
+
console.error('Reconcile the declared list with the actual files in squads/{squad}/agents/.');
|
|
222
|
+
}
|
|
128
223
|
return 1;
|
|
129
224
|
}
|
|
130
225
|
return 0;
|
|
@@ -134,4 +229,11 @@ if (require.main === module) {
|
|
|
134
229
|
process.exit(run());
|
|
135
230
|
}
|
|
136
231
|
|
|
137
|
-
module.exports = {
|
|
232
|
+
module.exports = {
|
|
233
|
+
run,
|
|
234
|
+
listSquads,
|
|
235
|
+
listAgentFiles,
|
|
236
|
+
hasComponentsAgents,
|
|
237
|
+
parseDeclaredAgents,
|
|
238
|
+
reconcileAgents,
|
|
239
|
+
};
|
|
@@ -31,6 +31,29 @@ const path = require('path');
|
|
|
31
31
|
const { collectCounts } = require('./sync-counts.js');
|
|
32
32
|
|
|
33
33
|
const ROOT = path.resolve(__dirname, '..');
|
|
34
|
+
const CONSTITUTION = path.join(ROOT, '.sinapse-ai', 'constitution.md');
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Count Constitution articles + NON-NEGOTIABLE ones from the canonical source.
|
|
38
|
+
* Articles are `### <Roman>. <Title>` headings; NON-NEGOTIABLE ones carry the
|
|
39
|
+
* `(NON-NEGOTIABLE)` marker in the heading. This is what was drifting in the
|
|
40
|
+
* README ("10 articles" while the constitution had 11) with no guard — now there
|
|
41
|
+
* is one.
|
|
42
|
+
* @returns {{articles:number, nonNegotiable:number}}
|
|
43
|
+
*/
|
|
44
|
+
function collectConstitutionCounts() {
|
|
45
|
+
let articles = 0;
|
|
46
|
+
let nonNegotiable = 0;
|
|
47
|
+
try {
|
|
48
|
+
const md = fs.readFileSync(CONSTITUTION, 'utf8');
|
|
49
|
+
const headings = md.match(/^###\s+[IVXLC]+\.\s.*$/gm) || [];
|
|
50
|
+
articles = headings.length;
|
|
51
|
+
nonNegotiable = headings.filter((h) => /\(NON-NEGOTIABLE\)/.test(h)).length;
|
|
52
|
+
} catch {
|
|
53
|
+
// Missing/unreadable constitution → leave zeros; the guards below are no-ops.
|
|
54
|
+
}
|
|
55
|
+
return { articles, nonNegotiable };
|
|
56
|
+
}
|
|
34
57
|
|
|
35
58
|
const TARGETS = [
|
|
36
59
|
{ file: 'README.md', label: 'README PT' },
|
|
@@ -44,12 +67,14 @@ const TARGETS = [
|
|
|
44
67
|
* Build the set of expected numeric tokens that MUST appear consistently.
|
|
45
68
|
* Returns an object describing canonical counts and a regex helper.
|
|
46
69
|
*/
|
|
47
|
-
function buildExpectations(counts) {
|
|
70
|
+
function buildExpectations(counts, constitution = { articles: 0, nonNegotiable: 0 }) {
|
|
48
71
|
return {
|
|
49
72
|
squads: counts.squads,
|
|
50
73
|
agents: counts.totalAgents,
|
|
51
74
|
orqx: counts.totalOrqx,
|
|
52
75
|
tasks: counts.tasks,
|
|
76
|
+
articles: constitution.articles,
|
|
77
|
+
nonNegotiable: constitution.nonNegotiable,
|
|
53
78
|
};
|
|
54
79
|
}
|
|
55
80
|
|
|
@@ -89,6 +114,39 @@ function findDrift(content, expected) {
|
|
|
89
114
|
}
|
|
90
115
|
}
|
|
91
116
|
|
|
117
|
+
// Constitution total articles: "<N> artigos"/"<N> articles" NOT immediately
|
|
118
|
+
// part of a NON-NEGOTIABLE clause, plus the shields.io badge
|
|
119
|
+
// "Constitution-<N>%20articles". Guards the exact drift that slipped through
|
|
120
|
+
// before (README said "10 articles" while the constitution had 11).
|
|
121
|
+
if (expected.articles) {
|
|
122
|
+
const artRe = /\b(\d{1,2})\s+(?:artigos|articles)\b(?![^.\n]{0,40}NON-NEGOTIABLE)/gi;
|
|
123
|
+
for (const m of content.matchAll(artRe)) {
|
|
124
|
+
const n = parseInt(m[1], 10);
|
|
125
|
+
if (n !== expected.articles && n >= 5) {
|
|
126
|
+
findings.push({ kind: 'articles', found: n, expected: expected.articles, snippet: m[0].trim() });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const badgeRe = /Constitution-(\d{1,2})%20articles/gi;
|
|
130
|
+
for (const m of content.matchAll(badgeRe)) {
|
|
131
|
+
const n = parseInt(m[1], 10);
|
|
132
|
+
if (n !== expected.articles) {
|
|
133
|
+
findings.push({ kind: 'articles (badge)', found: n, expected: expected.articles, snippet: m[0] });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Constitution NON-NEGOTIABLE article count: "<N> (desses|of those) artigos
|
|
139
|
+
// sao/are NON-NEGOTIABLE".
|
|
140
|
+
if (expected.nonNegotiable) {
|
|
141
|
+
const nnRe = /\b(\d{1,2})\s+(?:(?:desses|de|of\s+those)\s+)?(?:artigos|articles)\s+(?:sao|são|are)\s+NON-NEGOTIABLE/gi;
|
|
142
|
+
for (const m of content.matchAll(nnRe)) {
|
|
143
|
+
const n = parseInt(m[1], 10);
|
|
144
|
+
if (n !== expected.nonNegotiable) {
|
|
145
|
+
findings.push({ kind: 'NON-NEGOTIABLE articles', found: n, expected: expected.nonNegotiable, snippet: m[0].trim() });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
92
150
|
return findings;
|
|
93
151
|
}
|
|
94
152
|
|
|
@@ -112,14 +170,17 @@ function main() {
|
|
|
112
170
|
const fixMode = args.includes('--fix');
|
|
113
171
|
|
|
114
172
|
const counts = collectCounts();
|
|
115
|
-
const
|
|
173
|
+
const constitution = collectConstitutionCounts();
|
|
174
|
+
const expected = buildExpectations(counts, constitution);
|
|
116
175
|
|
|
117
176
|
console.log('Article VII (Metrics Accuracy) — validacao de drift');
|
|
118
177
|
console.log('Numeros canonicos (de .sinapse-ai/constitution.md):');
|
|
119
|
-
console.log(` squads
|
|
120
|
-
console.log(` agentes
|
|
121
|
-
console.log(` orqx
|
|
122
|
-
console.log(` tasks
|
|
178
|
+
console.log(` squads ${expected.squads}`);
|
|
179
|
+
console.log(` agentes ${expected.agents}`);
|
|
180
|
+
console.log(` orqx ${expected.orqx}`);
|
|
181
|
+
console.log(` tasks ${expected.tasks}`);
|
|
182
|
+
console.log(` artigos ${expected.articles}`);
|
|
183
|
+
console.log(` NON-NEGOTIABLE ${expected.nonNegotiable}`);
|
|
123
184
|
console.log('');
|
|
124
185
|
|
|
125
186
|
const allDrifts = [];
|
|
@@ -173,4 +234,4 @@ if (require.main === module) {
|
|
|
173
234
|
main();
|
|
174
235
|
}
|
|
175
236
|
|
|
176
|
-
module.exports = { findDrift, buildExpectations, TARGETS };
|
|
237
|
+
module.exports = { findDrift, buildExpectations, collectConstitutionCounts, TARGETS };
|
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Checks per orqx file:
|
|
12
12
|
* 1. File exists at squads/{squad}/agents/{name}-orqx.md
|
|
13
|
-
* 2. Contains a
|
|
14
|
-
* 3. agent.name
|
|
15
|
-
* 4. agent.id
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* 2. Contains a recognized identity block (YAML / frontmatter / Markdown)
|
|
14
|
+
* 3. At least one of agent.name / agent.id / agent.title is present
|
|
15
|
+
* 4. agent.id (when declared) matches `{squad}/{name}-orqx` OR the bare
|
|
16
|
+
* `{name}-orqx` file-base — anything else is a HARD ERROR (id-mismatch)
|
|
17
|
+
* 5. persona.role (or a Role/Papel section) exists — a missing role is a
|
|
18
|
+
* HARD ERROR (persona-role)
|
|
19
|
+
*
|
|
20
|
+
* Rationale (E8 / auditoria-pos-190): id-mismatch and persona-role were
|
|
21
|
+
* previously `warn` only and never blocked, so a malformed orqx (wrong id /
|
|
22
|
+
* no role) passed the gate silently. They now block (exit 1).
|
|
18
23
|
*
|
|
19
24
|
* Squad-level checks:
|
|
20
25
|
* - Every directory under squads/ that has agents/ MUST have at least
|
|
@@ -193,22 +198,27 @@ function validateOrqxFile(filePath) {
|
|
|
193
198
|
return findings;
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
// ID match is a
|
|
197
|
-
// "
|
|
201
|
+
// ID match is now a HARD check. The tolerance stays: an orqx may declare its id
|
|
202
|
+
// as the squad-prefixed "{squad}/{name}-orqx" OR the bare file-base "{name}-orqx"
|
|
203
|
+
// (Markdown format often omits the squad prefix). Anything else is a real
|
|
204
|
+
// divergence — a malformed orqx that would be reached under the wrong id — and
|
|
205
|
+
// is an ERROR, not a soft warning.
|
|
198
206
|
if (data.agent.id && data.agent.id !== expectedId) {
|
|
199
207
|
const fileBaseId = path.basename(filePath, '.md');
|
|
200
208
|
if (data.agent.id !== fileBaseId) {
|
|
201
209
|
findings.push({
|
|
202
|
-
level: '
|
|
210
|
+
level: 'error',
|
|
203
211
|
rule: 'id-mismatch',
|
|
204
212
|
message: `agent.id="${data.agent.id}" does not match "${expectedId}" or "${fileBaseId}"`,
|
|
205
213
|
});
|
|
206
214
|
}
|
|
207
215
|
}
|
|
208
216
|
|
|
217
|
+
// persona.role is now REQUIRED. An orqx with no role declared is malformed —
|
|
218
|
+
// the orchestrator persona is undefined. ERROR, not warning.
|
|
209
219
|
if (!data.persona || !data.persona.role) {
|
|
210
220
|
findings.push({
|
|
211
|
-
level: '
|
|
221
|
+
level: 'error',
|
|
212
222
|
rule: 'persona-role',
|
|
213
223
|
message: 'persona.role / Role section is missing',
|
|
214
224
|
});
|
|
@@ -360,8 +360,8 @@ routing_table:
|
|
|
360
360
|
|
|
361
361
|
- squad: claude-code-mastery
|
|
362
362
|
prefix: claude
|
|
363
|
-
orchestrator:
|
|
364
|
-
invocation: "/claude:agents:
|
|
363
|
+
orchestrator: swarm-orqx (Nexus)
|
|
364
|
+
invocation: "/claude:agents:swarm-orqx"
|
|
365
365
|
domain: "Claude Code mastery, prompt engineering, MCP, automacao, hooks, skills, plugins, agent teams, context engineering"
|
|
366
366
|
agents: 11
|
|
367
367
|
tasks: 51
|
|
@@ -652,7 +652,7 @@ relationships:
|
|
|
652
652
|
context: "All product strategy, discovery, roadmap"
|
|
653
653
|
- agent: research-orqx (Prism)
|
|
654
654
|
context: "All market research, competitive intelligence"
|
|
655
|
-
- agent:
|
|
655
|
+
- agent: swarm-orqx (Nexus)
|
|
656
656
|
context: "All Claude Code mastery, prompt engineering, MCP"
|
|
657
657
|
- agent: council-orqx (Zenith)
|
|
658
658
|
context: "All strategic counsel, mental models, advisory"
|
|
@@ -766,7 +766,7 @@ Imperator can provide ecosystem-wide insights by combining capabilities across s
|
|
|
766
766
|
| 9 | paidmedia | pm | Apex | Midia paga, Meta/Google Ads |
|
|
767
767
|
| 10 | product | product | Vector | Produto, discovery, roadmap |
|
|
768
768
|
| 11 | research | research | Prism | Pesquisa, inteligencia competitiva |
|
|
769
|
-
| 12 | claude | claude |
|
|
769
|
+
| 12 | claude-code-mastery | claude | Nexus | Claude Code, prompt engineering |
|
|
770
770
|
| 13 | council | council | Zenith | Conselho estrategico, advisory |
|
|
771
771
|
| 14 | storytelling | narrative | Arc | Storytelling, pitch, apresentacao |
|
|
772
772
|
| 15 | cybersecurity | cyber | Fortress | Cybersecurity, compliance, pentest |
|
|
@@ -267,8 +267,8 @@ routing_table:
|
|
|
267
267
|
|
|
268
268
|
- squad: claude-code-mastery
|
|
269
269
|
prefix: claude
|
|
270
|
-
orchestrator:
|
|
271
|
-
invocation: "/claude:agents:
|
|
270
|
+
orchestrator: swarm-orqx (Nexus)
|
|
271
|
+
invocation: "/claude:agents:swarm-orqx"
|
|
272
272
|
domain: "Claude Code mastery, prompt engineering, MCP, automacao, hooks, skills, plugins, agent teams, context engineering"
|
|
273
273
|
agents: 11
|
|
274
274
|
tasks: 51
|
|
@@ -559,7 +559,7 @@ relationships:
|
|
|
559
559
|
context: "All product strategy, discovery, roadmap"
|
|
560
560
|
- agent: research-orqx (Prism)
|
|
561
561
|
context: "All market research, competitive intelligence"
|
|
562
|
-
- agent:
|
|
562
|
+
- agent: swarm-orqx (Nexus)
|
|
563
563
|
context: "All Claude Code mastery, prompt engineering, MCP"
|
|
564
564
|
- agent: council-orqx (Zenith)
|
|
565
565
|
context: "All strategic counsel, mental models, advisory"
|
|
@@ -657,7 +657,7 @@ Imperator can provide ecosystem-wide insights by combining capabilities across s
|
|
|
657
657
|
| 9 | paidmedia | pm | Apex | Midia paga, Meta/Google Ads |
|
|
658
658
|
| 10 | product | product | Vector | Produto, discovery, roadmap |
|
|
659
659
|
| 11 | research | research | Prism | Pesquisa, inteligencia competitiva |
|
|
660
|
-
| 12 | claude | claude |
|
|
660
|
+
| 12 | claude-code-mastery | claude | Nexus | Claude Code, prompt engineering |
|
|
661
661
|
| 13 | council | council | Zenith | Conselho estrategico, advisory |
|
|
662
662
|
| 14 | storytelling | narrative | Arc | Storytelling, pitch, apresentacao |
|
|
663
663
|
| 15 | cybersecurity | cyber | Fortress | Cybersecurity, compliance, pentest |
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
| 9 | squad-paidmedia | pm | paidmedia-orqx (Apex) | `/pm:agents:paidmedia-orqx` |
|
|
18
18
|
| 10 | squad-product | product | product-orqx (Vector) | `/product:agents:product-orqx` |
|
|
19
19
|
| 11 | squad-research | research | research-orqx (Prism) | `/research:agents:research-orqx` |
|
|
20
|
-
| 12 | claude-code-mastery | claude |
|
|
20
|
+
| 12 | claude-code-mastery | claude | swarm-orqx (Nexus) | `/claude:agents:swarm-orqx` |
|
|
21
21
|
| 13 | squad-council | council | council-orqx (Zenith) | `/council:agents:council-orqx` |
|
|
22
22
|
| 14 | squad-storytelling | narrative | storytelling-orqx (Arc) | `/narrative:agents:storytelling-orqx` |
|
|
23
23
|
| 15 | squad-cybersecurity | cyber | cyber-orqx (Fortress) | `/cyber:agents:cyber-orqx` |
|
|
@@ -63,7 +63,7 @@ Mapear contra a routing table:
|
|
|
63
63
|
| Midia paga/ads | paid-media | pm | Apex | `/pm:agents:paidmedia-orqx` |
|
|
64
64
|
| Produto/discovery | product-systems | product | Vector | `/product:agents:product-orqx` |
|
|
65
65
|
| Pesquisa/competitivo | research-intelligence | research | Prism | `/research:agents:research-orqx` |
|
|
66
|
-
| Claude Code/prompts | claude-mastery | claude |
|
|
66
|
+
| Claude Code/prompts | claude-mastery | claude | Nexus | `/claude:agents:swarm-orqx` |
|
|
67
67
|
| Estrategia/advisory | strategic-council | council | Zenith | `/council:agents:council-orqx` |
|
|
68
68
|
| Narrativa/pitch | narrative-masters | narrative | Arc | `/narrative:agents:storytelling-orqx` |
|
|
69
69
|
| Seguranca/compliance | cyber-defense | cyber | Fortress | `/cyber:agents:cyber-orqx` |
|
|
@@ -111,7 +111,7 @@ QUICK ACCESS — HOW TO INVOKE:
|
|
|
111
111
|
/pm:agents:paidmedia-orqx → Midia Paga
|
|
112
112
|
/product:agents:product-orqx → Produto
|
|
113
113
|
/research:agents:research-orqx → Pesquisa
|
|
114
|
-
/claude:agents:
|
|
114
|
+
/claude:agents:swarm-orqx → Claude Mastery
|
|
115
115
|
/council:agents:council-orqx → Conselho
|
|
116
116
|
/narrative:agents:storytelling-orqx → Narrativa
|
|
117
117
|
/cyber:agents:cyber-orqx → Seguranca
|
|
@@ -195,7 +195,7 @@ sinapse_awareness:
|
|
|
195
195
|
- 14 workflow definitions in .sinapse-ai/development/workflows/
|
|
196
196
|
- L1-L4 boundary protection model
|
|
197
197
|
- Entity registry with 740+ entities
|
|
198
|
-
-
|
|
198
|
+
- Hook system: runtime grounding hooks in .sinapse-ai/hooks/ (wired via .claude/settings.json) + git hooks in .sinapse-ai/git-hooks/ (core.hooksPath)
|
|
199
199
|
- Template engine with Handlebars (.hbs)
|
|
200
200
|
- Quality gates (Layer 1-4: pre-commit, CI, pre-push, deployment)
|
|
201
201
|
- CLI: sinapse doctor, sinapse graph, sinapse workers, sinapse manifest, etc.
|