analyzthis_design 1.1.0 → 1.2.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/bin/cli.js CHANGED
@@ -2,80 +2,97 @@
2
2
  'use strict';
3
3
 
4
4
  const path = require('path');
5
- const os = require('os');
6
- const fs = require('fs');
5
+ const os = require('os');
6
+ const fs = require('fs');
7
7
  const { install, remove, SKILLS, TARGET_DIRS } = require('../lib/install');
8
+ const { connect, disconnect, sync, status } = require('../lib/knowledge');
8
9
 
9
10
  const HELP = `
10
- Analyzthis_Design — 7 AI design personas for Cursor, Claude, and Codex
11
+ Analyzthis_Design — 7 AI design personas with a personal knowledge bank
11
12
 
12
13
  Usage:
13
14
  npx analyzthis_design [command] [options]
14
15
 
15
- Commands:
16
- install Copy all skills to the target AI tool's skills directory (default)
16
+ ── Skill commands ───────────────────────────────────────────
17
+ install Copy all skills to the target AI tool's directory (default)
17
18
  remove Delete installed skills from the target AI tool's directory
18
19
  list Show installed skills for a target
19
20
 
20
- Options:
21
- --target AI tool to install into: cursor | claude | codex | all (default: cursor)
21
+ ── Knowledge bank commands ──────────────────────────────────
22
+ connect Register a vault or knowledge folder as a source
23
+ sync Read all sources and build the knowledge-bank skill
24
+ disconnect Remove a source from the registry
25
+ status Show connected sources and last sync time
26
+
27
+ ── Options ──────────────────────────────────────────────────
28
+ --target AI tool: cursor | claude | codex | all (default: cursor)
22
29
  --force Overwrite existing skills on install
30
+ --vault Path to Obsidian vault or markdown folder (connect command)
31
+ --tags Comma-separated tags to filter by, e.g. design,brand,ux
32
+ --include Comma-separated sub-folder names to include, e.g. Design,Brand
23
33
  --help Show this help message
24
34
 
25
- Examples:
26
- npx analyzthis_design # install for Cursor
27
- npx analyzthis_design --target claude # install for Claude Code
28
- npx analyzthis_design --target codex # install for Codex CLI
29
- npx analyzthis_design --target all # install for all tools
30
- npx analyzthis_design remove --target all # remove from all tools
35
+ ── Examples ─────────────────────────────────────────────────
36
+ npx analyzthis_design # install for Cursor
37
+ npx analyzthis_design --target all # install for all tools
38
+
39
+ npx analyzthis_design connect --vault ~/Documents/MyVault
40
+ npx analyzthis_design connect --vault ~/docs --tags design,brand,product
41
+ npx analyzthis_design connect --vault ~/vault --include Design,Research
42
+ npx analyzthis_design sync # sync to Cursor
43
+ npx analyzthis_design sync --target all # sync to all tools
44
+ npx analyzthis_design status # show sources
45
+ npx analyzthis_design disconnect --vault ~/Documents/MyVault
31
46
 
32
- Install paths:
47
+ ── Install paths ────────────────────────────────────────────
33
48
  Cursor → ~/.cursor/skills/
34
49
  Claude → ~/.claude/commands/
35
50
  Codex → ~/.codex/skills/
36
51
 
37
- Personas installed:
38
- Arjun UX Agent (UX Honeycomb critique)
39
- Meera Business Agent (retention, ARR, GTM)
40
- Priya Feasibility Agent (effort sizing, risks)
41
- Zara Delight Agent (Peak-End, one moment)
42
- Noor IA Architect (Concept A, minimalist)
43
- Anuj Power-User Advocate (Concept B, dense)
44
- Raj Arbitrator (stalemate only)
45
-
46
- Orchestrating skills:
47
- design-critic 4-persona critique → SHIP/REVISE/BLOCK
48
- ux-ideator 6-phase ideation workflow
49
- design-personas Session context template
52
+ ── Knowledge bank config ────────────────────────────────────
53
+ Config → ~/.analyzthis_design/config.json
50
54
 
51
55
  Docs: https://github.com/rishikeshjoshi/analyzthis_design
52
56
  `;
53
57
 
58
+ // ─── Parse args ──────────────────────────────────────────────────────────────
59
+
54
60
  const [,, cmd, ...flags] = process.argv;
55
- const force = flags.includes('--force');
56
- const targetFlag = flags.find(f => f.startsWith('--target=')) || flags[flags.indexOf('--target') + 1];
57
- const target = (typeof targetFlag === 'string' && !targetFlag.startsWith('--'))
58
- ? targetFlag
59
- : 'cursor';
61
+
62
+ function getFlag(name) {
63
+ // Supports both --flag=value and --flag value
64
+ const eq = flags.find(f => f.startsWith(`--${name}=`));
65
+ if (eq) return eq.split('=').slice(1).join('=');
66
+ const idx = flags.indexOf(`--${name}`);
67
+ if (idx !== -1 && flags[idx + 1] && !flags[idx + 1].startsWith('--')) return flags[idx + 1];
68
+ return null;
69
+ }
70
+
71
+ const force = flags.includes('--force');
72
+ const targetVal = getFlag('target') || 'cursor';
73
+ const vaultVal = getFlag('vault');
74
+ const tagsVal = getFlag('tags');
75
+ const includeVal = getFlag('include');
76
+
77
+ // ─── Commands ────────────────────────────────────────────────────────────────
60
78
 
61
79
  switch (cmd) {
62
80
  case undefined:
63
81
  case 'install':
64
- install({ force, target });
82
+ install({ force, target: targetVal });
65
83
  break;
66
84
 
67
85
  case 'remove':
68
86
  case 'uninstall':
69
- remove({ target });
87
+ remove({ target: targetVal });
70
88
  break;
71
89
 
72
90
  case 'list': {
73
- const targets = target === 'all' ? Object.keys(TARGET_DIRS) : [target];
91
+ const targets = targetVal === 'all' ? Object.keys(TARGET_DIRS) : [targetVal];
74
92
  for (const t of targets) {
75
93
  const dir = TARGET_DIRS[t];
76
94
  console.log(`\nInstalled Analyzthis_Design skills [${t}] (${dir}):\n`);
77
95
  for (const skill of SKILLS) {
78
- // Check both directory and flat .md forms
79
96
  const asDir = path.join(dir, skill);
80
97
  const asFile = path.join(dir, `${skill}.md`);
81
98
  const exists = fs.existsSync(asDir) || fs.existsSync(asFile);
@@ -86,6 +103,75 @@ switch (cmd) {
86
103
  break;
87
104
  }
88
105
 
106
+ // ── Knowledge bank ──────────────────────────────────────────────────────
107
+
108
+ case 'connect': {
109
+ if (!vaultVal) {
110
+ console.error('\n ✗ --vault is required. Example: npx analyzthis_design connect --vault ~/Documents/MyVault\n');
111
+ process.exit(1);
112
+ }
113
+ try {
114
+ const tags = tagsVal ? tagsVal.split(',').map(t => t.trim()) : [];
115
+ const include = includeVal ? includeVal.split(',').map(t => t.trim()) : [];
116
+ const abs = connect({ vaultPath: vaultVal, tags, include });
117
+ console.log(`\n✅ Connected: ${abs}`);
118
+ if (tags.length) console.log(` Tags filter: ${tags.join(', ')}`);
119
+ if (include.length) console.log(` Folder filter: ${include.join(', ')}`);
120
+ console.log(`\n Run "npx analyzthis_design sync" to build the knowledge bank.\n`);
121
+ } catch (err) {
122
+ console.error(`\n ✗ ${err.message}\n`);
123
+ process.exit(1);
124
+ }
125
+ break;
126
+ }
127
+
128
+ case 'disconnect': {
129
+ if (!vaultVal) {
130
+ console.error('\n ✗ --vault is required. Example: npx analyzthis_design disconnect --vault ~/Documents/MyVault\n');
131
+ process.exit(1);
132
+ }
133
+ disconnect(vaultVal);
134
+ console.log(`\n🗑 Disconnected: ${path.resolve(vaultVal)}\n`);
135
+ break;
136
+ }
137
+
138
+ case 'sync': {
139
+ const targets = targetVal === 'all' ? Object.keys(TARGET_DIRS) : [targetVal];
140
+ console.log('\n⏳ Syncing knowledge bank...\n');
141
+ try {
142
+ const result = sync({ targets });
143
+ if (result.message) {
144
+ console.log(` ⚠ ${result.message}\n`);
145
+ } else {
146
+ console.log(`✅ Synced ${result.synced} note(s) into the knowledge bank.`);
147
+ for (const t of result.copiedTo) console.log(` • ${t}`);
148
+ console.log(`\n💡 The knowledge bank is now active. All personas will read it first.\n`);
149
+ }
150
+ } catch (err) {
151
+ console.error(`\n ✗ Sync failed: ${err.message}\n`);
152
+ process.exit(1);
153
+ }
154
+ break;
155
+ }
156
+
157
+ case 'status': {
158
+ const cfg = status();
159
+ if (!cfg.sources || cfg.sources.length === 0) {
160
+ console.log('\n No knowledge sources connected.\n Run: npx analyzthis_design connect --vault /path/to/vault\n');
161
+ } else {
162
+ console.log(`\n📚 Knowledge bank sources (${cfg.sources.length}):\n`);
163
+ for (const s of cfg.sources) {
164
+ console.log(` • ${s.path}`);
165
+ if (s.tags.length) console.log(` Tags: ${s.tags.join(', ')}`);
166
+ if (s.include.length) console.log(` Folders: ${s.include.join(', ')}`);
167
+ console.log(` Added: ${s.addedAt}`);
168
+ }
169
+ if (cfg.lastSync) console.log(`\n Last sync: ${cfg.lastSync}`);
170
+ console.log('');
171
+ }
172
+ break;
173
+ }
174
+
89
175
  case '--help':
90
176
  case 'help':
91
177
  case '-h':
package/lib/install.js CHANGED
@@ -26,6 +26,7 @@ const SKILLS = [
26
26
  'ux-ideator',
27
27
  'design-personas',
28
28
  'design-reference',
29
+ 'knowledge-bank',
29
30
  ];
30
31
 
31
32
  // Copies a directory recursively
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const os = require('os');
7
+
8
+ const CONFIG_DIR = path.join(os.homedir(), '.analyzthis_design');
9
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
10
+ const KNOWLEDGE_SKILL = path.join(__dirname, '..', 'skills', 'knowledge-bank', 'SKILL.md');
11
+
12
+ // Keywords used to auto-group vault notes into categories
13
+ const CATEGORIES = {
14
+ brand: ['brand', 'color', 'typography', 'logo', 'visual', 'style', 'tone', 'voice', 'identity'],
15
+ product: ['product', 'feature', 'roadmap', 'vision', 'goal', 'north-star', 'metric', 'kpi', 'okr'],
16
+ design: ['design', 'ux', 'ui', 'wireframe', 'component', 'pattern', 'system', 'figma', 'layout'],
17
+ research: ['research', 'user', 'interview', 'survey', 'insight', 'pain', 'feedback', 'analytics', 'data'],
18
+ tech: ['tech', 'stack', 'api', 'backend', 'frontend', 'infrastructure', 'constraint', 'architecture'],
19
+ };
20
+
21
+ // ─── Config helpers ──────────────────────────────────────────────────────────
22
+
23
+ function loadConfig() {
24
+ if (!fs.existsSync(CONFIG_FILE)) return { sources: [] };
25
+ try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); }
26
+ catch { return { sources: [] }; }
27
+ }
28
+
29
+ function saveConfig(config) {
30
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
31
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
32
+ }
33
+
34
+ // ─── Vault reading ───────────────────────────────────────────────────────────
35
+
36
+ // Recursively collect all .md files under a directory
37
+ function readMarkdownFiles(dir) {
38
+ const files = [];
39
+ if (!fs.existsSync(dir)) return files;
40
+ const walk = (cur) => {
41
+ for (const entry of fs.readdirSync(cur, { withFileTypes: true })) {
42
+ const full = path.join(cur, entry.name);
43
+ if (entry.isDirectory() && !entry.name.startsWith('.')) walk(full);
44
+ else if (entry.isFile() && entry.name.endsWith('.md')) files.push(full);
45
+ }
46
+ };
47
+ walk(dir);
48
+ return files;
49
+ }
50
+
51
+ // Parse YAML-ish frontmatter from a markdown file
52
+ function parseFrontmatter(raw) {
53
+ const m = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
54
+ if (!m) return { meta: {}, body: raw };
55
+ const meta = {};
56
+ for (const line of m[1].split('\n')) {
57
+ const [k, ...v] = line.split(':');
58
+ if (k && v.length) meta[k.trim()] = v.join(':').trim();
59
+ }
60
+ return { meta, body: m[2] };
61
+ }
62
+
63
+ // Collect tags from frontmatter and inline #hashtags
64
+ function extractTags(meta, body) {
65
+ const tags = [];
66
+ if (meta.tags) tags.push(...meta.tags.replace(/[\[\]]/g, '').split(',').map(t => t.trim().toLowerCase()));
67
+ const inline = body.match(/#(\w+)/g) || [];
68
+ tags.push(...inline.map(t => t.slice(1).toLowerCase()));
69
+ return [...new Set(tags)];
70
+ }
71
+
72
+ // Strip Obsidian-specific syntax so the AI reads clean markdown
73
+ function cleanObsidian(text) {
74
+ return text
75
+ .replace(/\[\[([^\]|]+)\|([^\]]+)\]\]/g, '$2') // [[note|alias]] → alias
76
+ .replace(/\[\[([^\]]+)\]\]/g, '$1') // [[note]] → note text
77
+ .replace(/!\[\[([^\]]+)\]\]/g, '') // ![[embed]] → remove
78
+ .replace(/%%[\s\S]*?%%/g, '') // %% comments %% → remove
79
+ .trim();
80
+ }
81
+
82
+ // Map a note to a section category
83
+ function categorize(title, tags, body) {
84
+ const text = `${title} ${tags.join(' ')} ${body.substring(0, 500)}`.toLowerCase();
85
+ for (const [cat, keywords] of Object.entries(CATEGORIES)) {
86
+ if (keywords.some(k => text.includes(k))) return cat;
87
+ }
88
+ return 'other';
89
+ }
90
+
91
+ // ─── Public API ──────────────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * Register a vault or folder as a knowledge source.
95
+ * Options:
96
+ * include — array of sub-folder prefixes to include, e.g. ['Design', 'Brand']
97
+ * tags — array of tags to filter by, e.g. ['ux', 'design', 'brand']
98
+ */
99
+ function connect({ vaultPath, include = [], tags = [] }) {
100
+ const abs = path.resolve(vaultPath);
101
+ if (!fs.existsSync(abs)) throw new Error(`Path does not exist: ${abs}`);
102
+
103
+ const config = loadConfig();
104
+ // Replace any existing entry with the same path
105
+ config.sources = config.sources.filter(s => s.path !== abs);
106
+ config.sources.push({ path: abs, include, tags, addedAt: new Date().toISOString() });
107
+ saveConfig(config);
108
+ return abs;
109
+ }
110
+
111
+ /**
112
+ * Remove a vault/folder from the knowledge sources list.
113
+ */
114
+ function disconnect(vaultPath) {
115
+ const abs = path.resolve(vaultPath);
116
+ const config = loadConfig();
117
+ config.sources = config.sources.filter(s => s.path !== abs);
118
+ saveConfig(config);
119
+ }
120
+
121
+ /**
122
+ * Read all connected sources, filter notes, build knowledge-bank.md,
123
+ * and copy it to all requested target AI tool directories.
124
+ *
125
+ * targets — array of tool names: 'cursor', 'claude', 'codex'
126
+ */
127
+ function sync({ targets = ['cursor'] } = {}) {
128
+ const config = loadConfig();
129
+
130
+ if (!config.sources || config.sources.length === 0) {
131
+ return { synced: 0, message: 'No sources connected. Run: npx analyzthis_design connect --vault /path/to/vault' };
132
+ }
133
+
134
+ const sections = { brand: [], product: [], design: [], research: [], tech: [], other: [] };
135
+ let totalFiles = 0;
136
+
137
+ for (const source of config.sources) {
138
+ const files = readMarkdownFiles(source.path);
139
+
140
+ for (const filePath of files) {
141
+ const raw = fs.readFileSync(filePath, 'utf8');
142
+ const { meta, body } = parseFrontmatter(raw);
143
+ const tags = extractTags(meta, body);
144
+
145
+ // Tag filter: skip file if it doesn't carry one of the required tags
146
+ if (source.tags.length > 0 && !source.tags.some(t => tags.includes(t.toLowerCase()))) continue;
147
+
148
+ // Include-folder filter: skip file if it's not inside one of the allowed sub-paths
149
+ if (source.include.length > 0) {
150
+ const rel = path.relative(source.path, filePath);
151
+ const ok = source.include.some(p => rel.startsWith(p.replace('/**', '').replace('/*', '')));
152
+ if (!ok) continue;
153
+ }
154
+
155
+ const title = meta.title || path.basename(filePath, '.md');
156
+ const cleaned = cleanObsidian(body);
157
+ if (!cleaned.trim()) continue;
158
+
159
+ const cat = categorize(title, tags, cleaned);
160
+ sections[cat].push({ title, content: cleaned });
161
+ totalFiles++;
162
+ }
163
+ }
164
+
165
+ // Build the knowledge-bank markdown
166
+ const sourceList = config.sources.map(s => s.path).join(', ');
167
+ const date = new Date().toISOString().split('T')[0];
168
+
169
+ const sectionDefs = [
170
+ { key: 'brand', heading: '## Brand & Design Guidelines' },
171
+ { key: 'product', heading: '## Product Context' },
172
+ { key: 'design', heading: '## Design Decisions & Patterns' },
173
+ { key: 'research', heading: '## Research & User Insights' },
174
+ { key: 'tech', heading: '## Technical Context' },
175
+ { key: 'other', heading: '## Additional Context' },
176
+ ];
177
+
178
+ let md = `---
179
+ name: knowledge-bank
180
+ description: Personal knowledge bank — takes precedence over all built-in persona defaults.
181
+ disable-model-invocation: true
182
+ ---
183
+
184
+ # Knowledge Bank
185
+
186
+ > Last synced: ${date}
187
+ > Sources: ${sourceList}
188
+ > Files loaded: ${totalFiles}
189
+
190
+ **INSTRUCTION TO ALL PERSONAS:** This knowledge bank contains project-specific context that overrides your built-in defaults. Read every section below before forming any opinion. When this knowledge bank conflicts with your built-in knowledge, this knowledge bank wins.
191
+
192
+ ---
193
+
194
+ `;
195
+
196
+ let hasContent = false;
197
+ for (const { key, heading } of sectionDefs) {
198
+ if (sections[key].length === 0) continue;
199
+ hasContent = true;
200
+ md += `${heading}\n\n`;
201
+ for (const note of sections[key]) {
202
+ md += `### ${note.title}\n\n${note.content}\n\n`;
203
+ }
204
+ md += '---\n\n';
205
+ }
206
+
207
+ if (!hasContent) {
208
+ md += `_No matching files found. Check your --tags or --include filters, or remove filters to include all notes._\n`;
209
+ }
210
+
211
+ // Write to the package's own skills/knowledge-bank/SKILL.md
212
+ fs.mkdirSync(path.dirname(KNOWLEDGE_SKILL), { recursive: true });
213
+ fs.writeFileSync(KNOWLEDGE_SKILL, md);
214
+
215
+ // Copy to each target AI tool's skills directory
216
+ const { TARGET_DIRS } = require('./install');
217
+ const copiedTo = [];
218
+
219
+ for (const target of targets) {
220
+ const dir = TARGET_DIRS[target];
221
+ if (!dir) continue;
222
+ fs.mkdirSync(dir, { recursive: true });
223
+
224
+ if (target === 'cursor') {
225
+ // Cursor expects a sub-directory with SKILL.md inside
226
+ const dest = path.join(dir, 'knowledge-bank');
227
+ fs.mkdirSync(dest, { recursive: true });
228
+ fs.copyFileSync(KNOWLEDGE_SKILL, path.join(dest, 'SKILL.md'));
229
+ } else {
230
+ // Claude/Codex: flat .md file
231
+ fs.copyFileSync(KNOWLEDGE_SKILL, path.join(dir, 'knowledge-bank.md'));
232
+ }
233
+ copiedTo.push(`${target} → ${dir}`);
234
+ }
235
+
236
+ // Persist lastSync timestamp
237
+ config.lastSync = new Date().toISOString();
238
+ saveConfig(config);
239
+
240
+ return { synced: totalFiles, copiedTo };
241
+ }
242
+
243
+ /**
244
+ * Return current config (sources list, lastSync).
245
+ */
246
+ function status() {
247
+ return loadConfig();
248
+ }
249
+
250
+ module.exports = { connect, disconnect, sync, status };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "analyzthis_design",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "7 AI design personas for Cursor — run structured UX critiques and ideation sessions with Arjun (UX), Meera (Business), Priya (Feasibility), Zara (Delight), Noor (IA), Anuj (Power-User), and Raj (Arbitrator).",
5
5
  "keywords": [
6
6
  "cursor",
@@ -9,6 +9,19 @@ Four specialist personas evaluate a design independently across UX, business, fe
9
9
 
10
10
  ---
11
11
 
12
+ ## Step -1: Load knowledge bank (highest priority)
13
+
14
+ Before anything else, read `~/.cursor/skills/knowledge-bank/SKILL.md` (or `~/.claude/commands/knowledge-bank.md` / `~/.codex/skills/knowledge-bank.md` depending on your tool).
15
+
16
+ If the knowledge bank has content (i.e. it is not the "No knowledge bank connected yet" placeholder):
17
+ - Treat every section in the knowledge bank as **ground truth** for this project
18
+ - Brand guidelines, design decisions, product context, and research insights override your built-in defaults
19
+ - Reference specific knowledge bank entries when scoring or critiquing — quote them directly when relevant
20
+
21
+ If the knowledge bank is empty or missing, proceed without it.
22
+
23
+ ---
24
+
12
25
  ## Step 0: Gather session context
13
26
 
14
27
  Before starting, ask the user for (or read from `_session-context` if available):
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: knowledge-bank
3
+ description: Personal knowledge bank. Takes precedence over all built-in persona defaults. Connect your Obsidian vault or any markdown folder, then sync. All 7 personas read this first.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # Knowledge Bank
8
+
9
+ > No knowledge bank connected yet.
10
+
11
+ To populate this with your own project knowledge, run:
12
+
13
+ ```bash
14
+ # Connect an Obsidian vault (all notes)
15
+ npx analyzthis_design connect --vault /path/to/your/obsidian
16
+
17
+ # Connect a folder, filtering to only notes tagged #design or #brand
18
+ npx analyzthis_design connect --vault /path/to/docs --tags design,brand,product
19
+
20
+ # Connect a vault but only include specific sub-folders
21
+ npx analyzthis_design connect --vault /path/to/vault --include Design,Brand,Research
22
+
23
+ # After connecting, sync to generate the knowledge bank
24
+ npx analyzthis_design sync
25
+
26
+ # Sync to all AI tools at once
27
+ npx analyzthis_design sync --target all
28
+ ```
29
+
30
+ Once synced, this file is replaced with your actual vault content, grouped into:
31
+ - Brand & Design Guidelines
32
+ - Product Context
33
+ - Design Decisions & Patterns
34
+ - Research & User Insights
35
+ - Technical Context
36
+
37
+ **All 7 personas (Arjun, Meera, Priya, Zara, Noor, Anuj, Raj) will read this knowledge bank before any critique or ideation begins. Your project-specific knowledge takes full precedence over their built-in defaults.**
@@ -9,6 +9,19 @@ Seven personas collaborate across 6 phases to produce a single, deliberated, imp
9
9
 
10
10
  ---
11
11
 
12
+ ## Step -1: Load knowledge bank (highest priority)
13
+
14
+ Before anything else, read `~/.cursor/skills/knowledge-bank/SKILL.md` (or `~/.claude/commands/knowledge-bank.md` / `~/.codex/skills/knowledge-bank.md` depending on your tool).
15
+
16
+ If the knowledge bank has content (i.e. it is not the "No knowledge bank connected yet" placeholder):
17
+ - Treat every section as **ground truth** — brand guidelines, product decisions, research insights, and technical constraints override built-in persona defaults
18
+ - All 7 personas must reference applicable knowledge bank entries during their respective phases
19
+ - Design decisions already made in the knowledge bank are non-negotiable constraints — do not re-debate them
20
+
21
+ If the knowledge bank is empty or missing, proceed without it.
22
+
23
+ ---
24
+
12
25
  ## Step 0: Load session context
13
26
 
14
27
  Read session context from the user or from `_session-context`: