sinapse-ai 7.5.2 → 7.6.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.
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: Enforce Architecture-First Development (CJS port)
6
+ *
7
+ * RULE: Code in protected paths can only be created/edited if prior
8
+ * architecture documentation exists.
9
+ *
10
+ * Protocol (Claude Code PreToolUse):
11
+ * exit 0 → allow
12
+ * exit 2 → block (message shown to model via stderr)
13
+ *
14
+ * Fail-open: if parsing fails or project root is unresolvable, allow.
15
+ *
16
+ * @module enforce-architecture-first
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Configuration: paths that REQUIRE prior documentation
24
+ // ---------------------------------------------------------------------------
25
+
26
+ const PROTECTED_PATHS = [
27
+ {
28
+ pattern: 'supabase/functions/',
29
+ docPatterns: [
30
+ 'docs/architecture/{name}.md',
31
+ 'docs/architecture/{name}-architecture.md',
32
+ 'docs/approved-plans/{name}.md',
33
+ ],
34
+ extractName(p) {
35
+ const idx = p.indexOf('supabase/functions/');
36
+ if (idx === -1) return null;
37
+ return p.slice(idx + 'supabase/functions/'.length).split('/')[0] || null;
38
+ },
39
+ },
40
+ {
41
+ pattern: 'supabase/migrations/',
42
+ docPatterns: [
43
+ 'docs/approved-plans/migration-{name}.md',
44
+ 'docs/architecture/database-changes.md',
45
+ ],
46
+ extractName(p) {
47
+ const idx = p.indexOf('supabase/migrations/');
48
+ if (idx === -1) return null;
49
+ return path.basename(p, path.extname(p));
50
+ },
51
+ allowIfExists: true,
52
+ },
53
+ ];
54
+
55
+ const ALWAYS_ALLOWED = [
56
+ '.claude/', 'docs/', 'outputs/', 'squads/', '.sinapse-ai/',
57
+ '.sinapse-custom/', 'node_modules/', '.git/',
58
+ 'package.json', 'package-lock.json', 'tsconfig.json', '.env', 'README.md',
59
+ ];
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Helpers
63
+ // ---------------------------------------------------------------------------
64
+
65
+ function projectRoot() {
66
+ return process.env.CLAUDE_PROJECT_DIR || process.cwd();
67
+ }
68
+
69
+ function relativize(filePath, root) {
70
+ if (filePath.startsWith(root)) {
71
+ return filePath.slice(root.length).replace(/^[/\\]+/, '');
72
+ }
73
+ return filePath;
74
+ }
75
+
76
+ function isAlwaysAllowed(rel) {
77
+ return ALWAYS_ALLOWED.some((a) => rel.includes(a));
78
+ }
79
+
80
+ function findProtection(rel) {
81
+ return PROTECTED_PATHS.find((p) => rel.includes(p.pattern)) || null;
82
+ }
83
+
84
+ function docExists(rel, protection, root) {
85
+ const name = protection.extractName(rel);
86
+ if (!name) return true;
87
+
88
+ for (const dp of protection.docPatterns) {
89
+ const docPath = path.join(root, dp.replace('{name}', name));
90
+ if (fs.existsSync(docPath)) return true;
91
+ }
92
+
93
+ if (protection.allowIfExists) {
94
+ const full = path.isAbsolute(rel) ? rel : path.join(root, rel);
95
+ if (fs.existsSync(full)) return true;
96
+ }
97
+
98
+ return false;
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Main
103
+ // ---------------------------------------------------------------------------
104
+
105
+ function main() {
106
+ let input;
107
+ try {
108
+ input = JSON.parse(fs.readFileSync(0, 'utf8'));
109
+ } catch {
110
+ process.exit(0); // fail-open
111
+ }
112
+
113
+ const toolName = input.tool_name || '';
114
+ if (toolName !== 'Write' && toolName !== 'Edit') {
115
+ process.exit(0);
116
+ }
117
+
118
+ const filePath = (input.tool_input || {}).file_path || '';
119
+ if (!filePath) process.exit(0);
120
+
121
+ const root = projectRoot();
122
+ const rel = relativize(filePath, root);
123
+
124
+ if (isAlwaysAllowed(rel)) process.exit(0);
125
+
126
+ const protection = findProtection(rel);
127
+ if (!protection) process.exit(0);
128
+
129
+ if (docExists(rel, protection, root)) process.exit(0);
130
+
131
+ // BLOCK
132
+ const name = protection.extractName(rel) || 'unknown';
133
+ const accepted = protection.docPatterns.map((d) => ` - ${d.replace('{name}', name)}`).join('\n');
134
+
135
+ process.stderr.write(
136
+ `\nARCHITECTURE-FIRST BLOCK: Documentation required before code.\n` +
137
+ `File: ${rel}\n` +
138
+ `Create one of:\n${accepted}\n` +
139
+ `Then retry the operation.\n`,
140
+ );
141
+ process.exit(2);
142
+ }
143
+
144
+ main();
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: Enforce Mandatory Delegation — Constitution Article VIII
6
+ *
7
+ * RULE: Orchestrator agents (*-orqx) must NEVER execute domain work directly.
8
+ * They can only read, search, and delegate via Agent/SendMessage.
9
+ *
10
+ * Protocol (Claude Code PreToolUse):
11
+ * exit 0 → allow
12
+ * exit 2 → block (message shown to model via stderr)
13
+ *
14
+ * Fail-open: if session state is unreadable or agent is unknown, allow.
15
+ *
16
+ * Exception: sinapse-orqx is allowed Write/Edit in .sinapse-ai/ paths
17
+ * (framework governance — operates above the story layer).
18
+ *
19
+ * @module enforce-delegation
20
+ */
21
+
22
+ const fs = require('fs');
23
+ const path = require('path');
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Configuration
27
+ // ---------------------------------------------------------------------------
28
+
29
+ /** Agent IDs that are orchestrators (must delegate, never execute). */
30
+ const ORCHESTRATOR_PATTERN = /-orqx$/;
31
+
32
+ /** Tools that orchestrators are NOT allowed to use. */
33
+ const BLOCKED_TOOLS = ['Write', 'Edit', 'Bash', 'NotebookEdit'];
34
+
35
+ /** Paths where sinapse-orqx IS allowed to Write/Edit (framework governance). */
36
+ const FRAMEWORK_GOVERNANCE_PATHS = [
37
+ '.sinapse-ai/', '.claude/', '.sinapse/', 'bin/',
38
+ 'package.json', 'core-config.yaml',
39
+ ];
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Helpers
43
+ // ---------------------------------------------------------------------------
44
+
45
+ function projectRoot() {
46
+ return process.env.CLAUDE_PROJECT_DIR || process.cwd();
47
+ }
48
+
49
+ function relativize(filePath, root) {
50
+ const normalized = filePath.replace(/\\/g, '/');
51
+ const normalizedRoot = root.replace(/\\/g, '/');
52
+ if (normalized.startsWith(normalizedRoot)) {
53
+ return normalized.slice(normalizedRoot.length).replace(/^\/+/, '');
54
+ }
55
+ return normalized;
56
+ }
57
+
58
+ /**
59
+ * Read the active agent from session state.
60
+ * Returns the agent ID string or null if unknown.
61
+ */
62
+ function getActiveAgent(root) {
63
+ const sessionStatePath = path.join(root, '.sinapse', 'session-state.json');
64
+ try {
65
+ const state = JSON.parse(fs.readFileSync(sessionStatePath, 'utf8'));
66
+ return state.lastAgent || null;
67
+ } catch {
68
+ return null; // fail-open
69
+ }
70
+ }
71
+
72
+ function isOrchestrator(agentId) {
73
+ return ORCHESTRATOR_PATTERN.test(agentId);
74
+ }
75
+
76
+ function isFrameworkGovernancePath(rel) {
77
+ return FRAMEWORK_GOVERNANCE_PATHS.some((fp) => rel.startsWith(fp) || rel === fp);
78
+ }
79
+
80
+ // ---------------------------------------------------------------------------
81
+ // Main
82
+ // ---------------------------------------------------------------------------
83
+
84
+ function main() {
85
+ let input;
86
+ try {
87
+ input = JSON.parse(fs.readFileSync(0, 'utf8'));
88
+ } catch {
89
+ process.exit(0); // fail-open
90
+ }
91
+
92
+ const toolName = input.tool_name || '';
93
+
94
+ // Only intercept domain-execution tools
95
+ if (!BLOCKED_TOOLS.includes(toolName)) {
96
+ process.exit(0);
97
+ }
98
+
99
+ const root = projectRoot();
100
+ const agentId = getActiveAgent(root);
101
+
102
+ // If no agent tracked or not an orchestrator, allow
103
+ if (!agentId || !isOrchestrator(agentId)) {
104
+ process.exit(0);
105
+ }
106
+
107
+ // Special case: sinapse-orqx allowed for framework governance
108
+ if (agentId === 'sinapse-orqx') {
109
+ if (toolName === 'Write' || toolName === 'Edit') {
110
+ const filePath = (input.tool_input || {}).file_path || '';
111
+ if (filePath) {
112
+ const rel = relativize(filePath, root);
113
+ if (isFrameworkGovernancePath(rel)) {
114
+ process.exit(0); // Framework governance exception
115
+ }
116
+ }
117
+ }
118
+ // sinapse-orqx blocked for non-governance Write/Edit and all Bash
119
+ // (it should delegate to @developer or @devops)
120
+ }
121
+
122
+ // BLOCK
123
+ const delegationMap = {
124
+ Write: '@developer (Dex)',
125
+ Edit: '@developer (Dex)',
126
+ Bash: '@developer (Dex) or @devops (Gage)',
127
+ NotebookEdit: '@developer (Dex)',
128
+ };
129
+
130
+ const delegate = delegationMap[toolName] || '@developer';
131
+
132
+ process.stderr.write(
133
+ `\nMANDATORY DELEGATION BLOCK (Constitution Article VIII)\n` +
134
+ `Agent: ${agentId} (orchestrator)\n` +
135
+ `Tool: ${toolName}\n` +
136
+ `Orchestrators NEVER execute domain work directly.\n` +
137
+ `Delegate to ${delegate} for this operation.\n`,
138
+ );
139
+ process.exit(2);
140
+ }
141
+
142
+ main();
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: Enforce Story Gate — Constitution Article III (Documentation-First)
6
+ *
7
+ * RULE: Code files in implementation paths cannot be created/edited unless
8
+ * a story exists in docs/stories/ with status >= Ready.
9
+ *
10
+ * Protocol (Claude Code PreToolUse):
11
+ * exit 0 → allow
12
+ * exit 2 → block (message shown to model via stderr)
13
+ *
14
+ * Fail-open: if session state is unreadable or story status is indeterminate,
15
+ * the hook allows the operation (never blocks productive work).
16
+ *
17
+ * @module enforce-story-gate
18
+ */
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Configuration
25
+ // ---------------------------------------------------------------------------
26
+
27
+ /** Paths that require an active story before code changes. */
28
+ const CODE_PATHS = [
29
+ 'packages/', 'src/', 'app/', 'lib/', 'bin/',
30
+ 'components/', 'pages/', 'api/', 'services/',
31
+ ];
32
+
33
+ /** Paths always exempt from story requirement. */
34
+ const EXEMPT_PATHS = [
35
+ '.claude/', '.sinapse-ai/', '.sinapse/', '.sinapse-custom/',
36
+ 'docs/', 'tests/', '__tests__/', 'test/',
37
+ 'node_modules/', '.git/', 'squads/', 'outputs/',
38
+ ];
39
+
40
+ /** Config files always exempt. */
41
+ const EXEMPT_FILES = [
42
+ 'package.json', 'package-lock.json', 'tsconfig.json',
43
+ '.env', '.env.local', '.env.example',
44
+ '.gitignore', '.eslintrc', '.prettierrc',
45
+ 'README.md', 'CHANGELOG.md',
46
+ 'jest.config.js', 'jest.config.ts',
47
+ 'vite.config.ts', 'next.config.js', 'next.config.mjs',
48
+ 'tailwind.config.js', 'tailwind.config.ts',
49
+ 'postcss.config.js', 'postcss.config.cjs',
50
+ ];
51
+
52
+ /** Story statuses that allow implementation. */
53
+ const VALID_STATUSES = ['ready', 'inprogress', 'in progress', 'in_progress', 'inreview', 'in review', 'in_review', 'done'];
54
+
55
+ // ---------------------------------------------------------------------------
56
+ // Helpers
57
+ // ---------------------------------------------------------------------------
58
+
59
+ function projectRoot() {
60
+ return process.env.CLAUDE_PROJECT_DIR || process.cwd();
61
+ }
62
+
63
+ function relativize(filePath, root) {
64
+ const normalized = filePath.replace(/\\/g, '/');
65
+ const normalizedRoot = root.replace(/\\/g, '/');
66
+ if (normalized.startsWith(normalizedRoot)) {
67
+ return normalized.slice(normalizedRoot.length).replace(/^\/+/, '');
68
+ }
69
+ return normalized;
70
+ }
71
+
72
+ function isExempt(rel) {
73
+ const basename = path.basename(rel);
74
+ if (EXEMPT_FILES.includes(basename)) return true;
75
+ return EXEMPT_PATHS.some((ep) => rel.startsWith(ep));
76
+ }
77
+
78
+ function isCodePath(rel) {
79
+ return CODE_PATHS.some((cp) => rel.startsWith(cp));
80
+ }
81
+
82
+ /**
83
+ * Check if there's an active story with valid status.
84
+ * Reads .sinapse/session-state.json for story context,
85
+ * then scans docs/stories/ for any story with status >= Ready.
86
+ */
87
+ function hasActiveStory(root) {
88
+ // Strategy 1: Check session state for active story
89
+ const sessionStatePath = path.join(root, '.sinapse', 'session-state.json');
90
+ try {
91
+ const state = JSON.parse(fs.readFileSync(sessionStatePath, 'utf8'));
92
+ if (state.activeStory && state.activeStory.status) {
93
+ const status = state.activeStory.status.toLowerCase().replace(/[\s_-]+/g, '');
94
+ if (VALID_STATUSES.some((vs) => vs.replace(/[\s_-]+/g, '') === status)) {
95
+ return true;
96
+ }
97
+ }
98
+ } catch {
99
+ // No session state or invalid — continue to Strategy 2
100
+ }
101
+
102
+ // Strategy 2: Scan docs/stories/ for any story file
103
+ const storiesDir = path.join(root, 'docs', 'stories');
104
+ try {
105
+ if (!fs.existsSync(storiesDir)) return false;
106
+
107
+ // Recursively find .md files
108
+ const files = walkSync(storiesDir, '.md');
109
+ for (const file of files) {
110
+ try {
111
+ const content = fs.readFileSync(file, 'utf8');
112
+ // Look for status field in YAML frontmatter or markdown
113
+ const statusMatch = content.match(/status:\s*["']?(\w[\w\s]*\w?)["']?/i);
114
+ if (statusMatch) {
115
+ const status = statusMatch[1].toLowerCase().replace(/[\s_-]+/g, '');
116
+ if (VALID_STATUSES.some((vs) => vs.replace(/[\s_-]+/g, '') === status)) {
117
+ return true;
118
+ }
119
+ }
120
+ } catch {
121
+ // Skip unreadable files
122
+ }
123
+ }
124
+ } catch {
125
+ // Can't scan — fail-open
126
+ return true;
127
+ }
128
+
129
+ return false;
130
+ }
131
+
132
+ /** Simple recursive file walker. */
133
+ function walkSync(dir, ext) {
134
+ const results = [];
135
+ try {
136
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
137
+ const full = path.join(dir, entry.name);
138
+ if (entry.isDirectory()) {
139
+ results.push(...walkSync(full, ext));
140
+ } else if (entry.name.endsWith(ext)) {
141
+ results.push(full);
142
+ }
143
+ }
144
+ } catch {
145
+ // Skip inaccessible dirs
146
+ }
147
+ return results;
148
+ }
149
+
150
+ // ---------------------------------------------------------------------------
151
+ // Main
152
+ // ---------------------------------------------------------------------------
153
+
154
+ function main() {
155
+ let input;
156
+ try {
157
+ input = JSON.parse(fs.readFileSync(0, 'utf8'));
158
+ } catch {
159
+ process.exit(0); // fail-open
160
+ }
161
+
162
+ const toolName = input.tool_name || '';
163
+ if (toolName !== 'Write' && toolName !== 'Edit') {
164
+ process.exit(0);
165
+ }
166
+
167
+ const filePath = (input.tool_input || {}).file_path || '';
168
+ if (!filePath) process.exit(0);
169
+
170
+ const root = projectRoot();
171
+ const rel = relativize(filePath, root);
172
+
173
+ // Exempt paths and files
174
+ if (isExempt(rel)) process.exit(0);
175
+
176
+ // Only enforce on code paths
177
+ if (!isCodePath(rel)) process.exit(0);
178
+
179
+ // Check for active story
180
+ if (hasActiveStory(root)) process.exit(0);
181
+
182
+ // BLOCK
183
+ process.stderr.write(
184
+ `\nDOCUMENTATION-FIRST BLOCK (Constitution Article III)\n` +
185
+ `File: ${rel}\n` +
186
+ `No active story found with status >= Ready in docs/stories/.\n` +
187
+ `Create a story first: @sprint-lead *draft\n` +
188
+ `Then validate it: @product-lead *validate\n` +
189
+ `Only then can implementation proceed.\n`,
190
+ );
191
+ process.exit(2);
192
+ }
193
+
194
+ main();
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: Write Path Validation (CJS port)
6
+ *
7
+ * RULE: Documentation files should go to the correct paths per conventions.
8
+ * This hook WARNS (never blocks) when a doc path looks wrong.
9
+ *
10
+ * Protocol: always exit 0 (warn-only, never blocks).
11
+ *
12
+ * @module write-path-validation
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Configuration
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const PATH_RULES = [
23
+ {
24
+ namePatterns: [/session/i, /handoff/i, /^2\d{3}-\d{2}-\d{2}/],
25
+ expectedPath: 'docs/sessions/',
26
+ description: 'Session logs e handoffs → docs/sessions/YYYY-MM/',
27
+ },
28
+ {
29
+ namePatterns: [/architecture/i, /system-design/i, /infra/i],
30
+ expectedPath: 'docs/architecture/',
31
+ description: 'Docs de arquitetura → docs/architecture/',
32
+ excludePatterns: [/ARCHITECTURE_RULES/i],
33
+ },
34
+ {
35
+ namePatterns: [/guide/i, /tutorial/i, /how-to/i],
36
+ expectedPath: 'docs/guides/',
37
+ description: 'Guias e tutoriais → docs/guides/',
38
+ },
39
+ {
40
+ namePatterns: [/prd\.md$/i, /epic.*\.md$/i, /story.*\.md$/i],
41
+ expectedPath: 'docs/projects/',
42
+ description: 'PRDs, Epics, Stories → docs/projects/{project}/',
43
+ },
44
+ {
45
+ namePatterns: [/mind.*specific/i, /mind.*validation/i],
46
+ expectedPath: 'outputs/minds/',
47
+ description: 'Docs de mind → outputs/minds/{slug}/docs/',
48
+ },
49
+ ];
50
+
51
+ const ALWAYS_VALID = [
52
+ '.claude/', '.sinapse-ai/', '.sinapse-upstream/', 'squads/',
53
+ 'node_modules/', '.git/', 'app/', 'supabase/', 'outputs/',
54
+ ];
55
+
56
+ const DOC_EXTENSIONS = ['.md', '.mdx', '.txt', '.rst'];
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Helpers
60
+ // ---------------------------------------------------------------------------
61
+
62
+ function projectRoot() {
63
+ return process.env.CLAUDE_PROJECT_DIR || process.cwd();
64
+ }
65
+
66
+ function relativize(filePath, root) {
67
+ if (filePath.startsWith(root)) return filePath.slice(root.length).replace(/^[/\\]+/, '');
68
+ return filePath;
69
+ }
70
+
71
+ function isAlwaysValid(rel) {
72
+ return ALWAYS_VALID.some((v) => rel.startsWith(v));
73
+ }
74
+
75
+ function isDocFile(rel) {
76
+ return DOC_EXTENSIONS.some((ext) => rel.endsWith(ext));
77
+ }
78
+
79
+ function checkRules(rel) {
80
+ const filename = path.basename(rel);
81
+ for (const rule of PATH_RULES) {
82
+ const matchesName = rule.namePatterns.some((p) => p.test(filename));
83
+ if (!matchesName) continue;
84
+
85
+ if (rule.excludePatterns && rule.excludePatterns.some((p) => p.test(filename))) continue;
86
+
87
+ if (!rel.startsWith(rule.expectedPath)) {
88
+ return { currentPath: rel, expectedPath: rule.expectedPath, description: rule.description };
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // Main
96
+ // ---------------------------------------------------------------------------
97
+
98
+ function main() {
99
+ let input;
100
+ try {
101
+ input = JSON.parse(fs.readFileSync(0, 'utf8'));
102
+ } catch {
103
+ process.exit(0);
104
+ }
105
+
106
+ const toolName = input.tool_name || '';
107
+ if (toolName !== 'Write' && toolName !== 'Edit') process.exit(0);
108
+
109
+ const filePath = (input.tool_input || {}).file_path || '';
110
+ if (!filePath) process.exit(0);
111
+
112
+ const root = projectRoot();
113
+ const rel = relativize(filePath, root);
114
+
115
+ if (isAlwaysValid(rel)) process.exit(0);
116
+ if (!isDocFile(rel)) process.exit(0);
117
+
118
+ const violation = checkRules(rel);
119
+ if (!violation) process.exit(0);
120
+
121
+ // WARN only — never block
122
+ process.stderr.write(
123
+ `\nPATH WARNING: Document may be in the wrong location.\n` +
124
+ ` File: ${violation.currentPath}\n` +
125
+ ` Expected: ${violation.expectedPath}\n` +
126
+ ` Rule: ${violation.description}\n` +
127
+ ` NOTE: This is a WARNING only — the operation will proceed.\n`,
128
+ );
129
+ process.exit(0);
130
+ }
131
+
132
+ main();
@@ -44,6 +44,18 @@ The incoming agent receives:
44
44
  2. The **handoff artifact** from the previous agent (compact summary)
45
45
  3. **NOT** the previous agent's full persona/instructions/tool definitions
46
46
 
47
+ ### Scratchpad Protocol (v1.1)
48
+
49
+ **Before starting work**, the incoming agent MUST:
50
+ 1. Check if `.sinapse/scratchpad/{story-id}/` exists
51
+ 2. If yes, read ALL files in that directory (discoveries from previous agents)
52
+ 3. Use those insights to inform decisions (avoid rediscovering known issues)
53
+
54
+ **Before handing off**, the outgoing agent SHOULD:
55
+ 1. Write key discoveries to `.sinapse/scratchpad/{story-id}/{agent-id}.md`
56
+ 2. Include the scratchpad path in the handoff artifact `scratchpad_path` field
57
+ 3. Keep each file under 2KB (focused insights, not logs)
58
+
47
59
  ### Compaction Limits
48
60
 
49
61
  | Limit | Value |
@@ -40,6 +40,9 @@ handoff:
40
40
  # What the incoming agent should do next (max 2 sentences)
41
41
  next_action: "" # e.g., "Run QA gate on TOK-4A. Verify handoff preserves story context."
42
42
 
43
+ # Cross-agent knowledge sharing (v1.1)
44
+ scratchpad_path: "" # e.g., ".sinapse/scratchpad/TOK-4A/" — read before starting work
45
+
43
46
  # --- Compaction Limits (AC 9) ---
44
47
  # Max artifact size: 500 tokens (~375 words)
45
48
  # Max retained summaries: 3 (oldest discarded on 4th switch)
@@ -7,8 +7,8 @@
7
7
  # - SHA256 hashes for change detection
8
8
  # - File types for categorization
9
9
  #
10
- version: 7.5.2
11
- generated_at: "2026-03-31T19:58:02.055Z"
10
+ version: 7.6.0
11
+ generated_at: "2026-04-01T02:05:35.822Z"
12
12
  generator: scripts/generate-install-manifest.js
13
13
  file_count: 1104
14
14
  files:
@@ -2565,9 +2565,9 @@ files:
2565
2565
  type: task
2566
2566
  size: 2254
2567
2567
  - path: development/templates/agent-handoff-tmpl.yaml
2568
- hash: sha256:abb8d46dce28abb9cd140931db4283202d7c2b89220c43283c6518813a0911ad
2568
+ hash: sha256:9b28cc790c81960acf9c8393555d6d5474afa724e152784f8983bbf70be89b3a
2569
2569
  type: template
2570
- size: 1988
2570
+ size: 2124
2571
2571
  - path: development/templates/chrome-brain/knowledge-base/chrome-brain.md
2572
2572
  hash: sha256:ed47917601edfe48153290ea57b3d367220ceba6b976e7222c2451af6b4a6566
2573
2573
  type: template
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sinapse-ai",
3
- "version": "7.5.2",
3
+ "version": "7.6.0",
4
4
  "description": "SINAPSE AI: Framework de orquestracao de IA — 18 squads, 175 agentes especializados",
5
5
  "bin": {
6
6
  "sinapse": "bin/sinapse.js",