bossbuild 0.97.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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/PRINCIPLES.md +70 -0
  3. package/README.md +213 -0
  4. package/VERSION +1 -0
  5. package/bin/boss +3 -0
  6. package/library/README.md +19 -0
  7. package/library/agents/.gitkeep +0 -0
  8. package/library/agents/mentor-venture.md +57 -0
  9. package/library/hooks/.gitkeep +0 -0
  10. package/library/hooks/auto-log.js +133 -0
  11. package/library/hooks/memory-cue.js +82 -0
  12. package/library/hooks/secrets-guard.js +87 -0
  13. package/library/memory-seed/README.md +29 -0
  14. package/library/memory-seed/durable-facts-example.md +16 -0
  15. package/library/practices/.gitkeep +0 -0
  16. package/library/practices/agent-security.md +111 -0
  17. package/library/practices/ai-adoption-culture.md +104 -0
  18. package/library/practices/ai-ux-patterns.md +246 -0
  19. package/library/practices/celebration-of-done.md +100 -0
  20. package/library/practices/conscience-voicing.md +121 -0
  21. package/library/practices/context-discipline.md +116 -0
  22. package/library/practices/design-system.md +152 -0
  23. package/library/practices/git-workflow.md +119 -0
  24. package/library/practices/harm-taxonomy.md +45 -0
  25. package/library/practices/quality-ratchet.md +48 -0
  26. package/library/practices/revalidation.md +57 -0
  27. package/library/practices/scalable-architecture.md +111 -0
  28. package/library/practices/ship-it-live.md +149 -0
  29. package/library/practices/skill-authoring.md +70 -0
  30. package/library/skills/.gitkeep +0 -0
  31. package/library/skills/boss-learn/SKILL.md +63 -0
  32. package/library/skills/boss-sync/SKILL.md +48 -0
  33. package/package.json +49 -0
  34. package/registry/CHANGELOG.md +2737 -0
  35. package/src/board.js +655 -0
  36. package/src/brain.js +288 -0
  37. package/src/cli.js +542 -0
  38. package/src/conscience.js +426 -0
  39. package/src/insights.js +147 -0
  40. package/src/learn.js +92 -0
  41. package/src/map.js +103 -0
  42. package/src/modes.js +82 -0
  43. package/src/paths.js +36 -0
  44. package/src/registry.js +34 -0
  45. package/src/scaffold.js +138 -0
  46. package/src/sync.js +292 -0
  47. package/src/team.js +103 -0
  48. package/stages/L0-quickstart/manifest.json +12 -0
  49. package/stages/L0-quickstart/template/.claude/agents/coder-generalist.md +31 -0
  50. package/stages/L0-quickstart/template/.claude/agents/mentor-venture.md +57 -0
  51. package/stages/L0-quickstart/template/.claude/agents/pm.md +28 -0
  52. package/stages/L0-quickstart/template/.claude/hooks/conscience.js +89 -0
  53. package/stages/L0-quickstart/template/.claude/hooks/lib/loop-runtime.js +507 -0
  54. package/stages/L0-quickstart/template/.claude/hooks/lib/yaml.js +163 -0
  55. package/stages/L0-quickstart/template/.claude/hooks/memory-cue.js +82 -0
  56. package/stages/L0-quickstart/template/.claude/hooks/secrets-guard.js +87 -0
  57. package/stages/L0-quickstart/template/.claude/rules/your-app-code.md +17 -0
  58. package/stages/L0-quickstart/template/.claude/settings.json +36 -0
  59. package/stages/L0-quickstart/template/.claude/skills/boss/SKILL.md +161 -0
  60. package/stages/L0-quickstart/template/.claude/skills/boss-learn/SKILL.md +63 -0
  61. package/stages/L0-quickstart/template/.claude/skills/boss-sync/SKILL.md +55 -0
  62. package/stages/L0-quickstart/template/.claude/skills/canvas/SKILL.md +112 -0
  63. package/stages/L0-quickstart/template/.claude/skills/comprehend/SKILL.md +72 -0
  64. package/stages/L0-quickstart/template/.claude/skills/decide/SKILL.md +122 -0
  65. package/stages/L0-quickstart/template/.claude/skills/feedback/SKILL.md +68 -0
  66. package/stages/L0-quickstart/template/.claude/skills/import/SKILL.md +73 -0
  67. package/stages/L0-quickstart/template/.claude/skills/persona/SKILL.md +92 -0
  68. package/stages/L0-quickstart/template/.claude/skills/prototype/SKILL.md +114 -0
  69. package/stages/L0-quickstart/template/.claude/skills/triage/SKILL.md +104 -0
  70. package/stages/L0-quickstart/template/.claude/skills/welcome/SKILL.md +262 -0
  71. package/stages/L0-quickstart/template/AGENTS.md +31 -0
  72. package/stages/L0-quickstart/template/CLAUDE.md +57 -0
  73. package/stages/L0-quickstart/template/docs/IDS.md +42 -0
  74. package/stages/L0-quickstart/template/docs/ideas/INDEX.md +24 -0
  75. package/stages/L0-quickstart/template/docs/loops/canvas-loop.md +90 -0
  76. package/stages/L0-quickstart/template/docs/loops/capture-loop.md +64 -0
  77. package/stages/L1-mvp/manifest.json +12 -0
  78. package/stages/L1-mvp/template/.claude/agents/mentor-architect.md +124 -0
  79. package/stages/L1-mvp/template/.claude/agents/mentor-cofounder.md +85 -0
  80. package/stages/L1-mvp/template/.claude/agents/mentor-gtm.md +49 -0
  81. package/stages/L1-mvp/template/.claude/agents/program-manager.md +46 -0
  82. package/stages/L1-mvp/template/.claude/agents/tester.md +42 -0
  83. package/stages/L1-mvp/template/.claude/hooks/auto-log.js +133 -0
  84. package/stages/L1-mvp/template/.claude/rules/feature-context.md +18 -0
  85. package/stages/L1-mvp/template/.claude/skills/ai-cost/SKILL.md +249 -0
  86. package/stages/L1-mvp/template/.claude/skills/ai-failure-states/SKILL.md +226 -0
  87. package/stages/L1-mvp/template/.claude/skills/ai-first-init/SKILL.md +227 -0
  88. package/stages/L1-mvp/template/.claude/skills/close/SKILL.md +170 -0
  89. package/stages/L1-mvp/template/.claude/skills/consult/SKILL.md +72 -0
  90. package/stages/L1-mvp/template/.claude/skills/cost-review/SKILL.md +204 -0
  91. package/stages/L1-mvp/template/.claude/skills/design-tokens-init/SKILL.md +192 -0
  92. package/stages/L1-mvp/template/.claude/skills/drift-deep/SKILL.md +170 -0
  93. package/stages/L1-mvp/template/.claude/skills/evals/SKILL.md +154 -0
  94. package/stages/L1-mvp/template/.claude/skills/extract/SKILL.md +209 -0
  95. package/stages/L1-mvp/template/.claude/skills/judge-traces/SKILL.md +68 -0
  96. package/stages/L1-mvp/template/.claude/skills/log/SKILL.md +64 -0
  97. package/stages/L1-mvp/template/.claude/skills/practice/SKILL.md +92 -0
  98. package/stages/L1-mvp/template/.claude/skills/pretotype/SKILL.md +95 -0
  99. package/stages/L1-mvp/template/.claude/skills/red-team/SKILL.md +137 -0
  100. package/stages/L1-mvp/template/.claude/skills/revalidate/SKILL.md +51 -0
  101. package/stages/L1-mvp/template/.claude/skills/ship/SKILL.md +105 -0
  102. package/stages/L1-mvp/template/.claude/skills/smoke/SKILL.md +43 -0
  103. package/stages/L1-mvp/template/.claude/skills/spec/SKILL.md +145 -0
  104. package/stages/L1-mvp/template/claude-append.md +122 -0
  105. package/stages/L1-mvp/template/docs/loops/ai-failure-state-loop.md +107 -0
  106. package/stages/L1-mvp/template/docs/loops/coordination-loop.md +116 -0
  107. package/stages/L1-mvp/template/docs/loops/cost-budget-loop.md +117 -0
  108. package/stages/L1-mvp/template/docs/loops/cost-review-loop.md +113 -0
  109. package/stages/L1-mvp/template/docs/loops/design-tokens-loop.md +98 -0
  110. package/stages/L1-mvp/template/docs/loops/drift-loop.md +149 -0
  111. package/stages/L1-mvp/template/docs/loops/extraction-loop.md +128 -0
  112. package/stages/L1-mvp/template/docs/loops/focus-loop.md +106 -0
  113. package/stages/L1-mvp/template/docs/loops/pretotype-loop.md +88 -0
  114. package/stages/L1-mvp/template/docs/loops/spec-loop.md +83 -0
  115. package/stages/L2-v1/manifest.json +12 -0
  116. package/stages/L2-v1/template/.claude/agents/db-architect.md +91 -0
  117. package/stages/L2-v1/template/.claude/agents/mentor-business.md +124 -0
  118. package/stages/L2-v1/template/.claude/agents/mentor-fundraising.md +72 -0
  119. package/stages/L2-v1/template/.claude/agents/mentor-pitch.md +84 -0
  120. package/stages/L2-v1/template/.claude/agents/mentor-talent.md +84 -0
  121. package/stages/L2-v1/template/.claude/agents/ui-designer.md +81 -0
  122. package/stages/L2-v1/template/.claude/agents/ux-designer.md +87 -0
  123. package/stages/L2-v1/template/.claude/skills/board/SKILL.md +98 -0
  124. package/stages/L2-v1/template/.claude/skills/design-review/SKILL.md +77 -0
  125. package/stages/L2-v1/template/.claude/skills/ux-check/SKILL.md +93 -0
  126. package/stages/L2-v1/template/claude-append.md +59 -0
  127. package/stages/L2-v1/template/docs/loops/design-drift-loop.md +108 -0
  128. package/stages/L3-scale/README.md +13 -0
@@ -0,0 +1,163 @@
1
+ // Minimal YAML parser for the BOSS loop-runtime — zero deps.
2
+ // Covers the subset used by loop specs and eval files:
3
+ // - top-level sequence (- item) or mapping
4
+ // - block mappings (key: value with indented children)
5
+ // - inline mappings ({k: v, k2: v2})
6
+ // - inline sequences ([a, b, c])
7
+ // - scalars: bare string, quoted string, int, true/false, null
8
+ // - comments (# ...) and blank lines
9
+ // NOT supported: anchors, aliases, multi-line scalars, flow-style mixing.
10
+ // Lifted from docs/architecture/conscience-evals/runner.js so the same parser
11
+ // is available to the project-side hook.
12
+
13
+ export function parseYaml(text) {
14
+ const tokens = tokenize(text);
15
+ if (tokens.length === 0) return null;
16
+ const baseIndent = tokens[0].indent;
17
+ const [result] = parseBlock(tokens, 0, baseIndent);
18
+ return result;
19
+ }
20
+
21
+ // Extract YAML frontmatter from a markdown file (between leading `---` and `---`).
22
+ // Returns the parsed object, or null if no frontmatter is present.
23
+ export function parseFrontmatter(text) {
24
+ if (!text.startsWith('---\n')) return null;
25
+ const end = text.indexOf('\n---\n', 4);
26
+ if (end < 0) return null;
27
+ return parseYaml(text.slice(4, end));
28
+ }
29
+
30
+ function parseScalar(s) {
31
+ s = s.trim();
32
+ if (s === '' || s === '~' || s === 'null') return null;
33
+ if (s === 'true') return true;
34
+ if (s === 'false') return false;
35
+ if (/^-?\d+$/.test(s)) return parseInt(s, 10);
36
+ if (/^-?\d+\.\d+$/.test(s)) return parseFloat(s);
37
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
38
+ return s.slice(1, -1);
39
+ }
40
+ if (s.startsWith('[') && s.endsWith(']')) {
41
+ const inner = s.slice(1, -1).trim();
42
+ if (!inner) return [];
43
+ return splitTopLevel(inner, ',').map((p) => parseScalar(p));
44
+ }
45
+ if (s.startsWith('{') && s.endsWith('}')) {
46
+ const inner = s.slice(1, -1).trim();
47
+ if (!inner) return {};
48
+ const obj = {};
49
+ for (const pair of splitTopLevel(inner, ',')) {
50
+ const colonIdx = findTopLevelChar(pair, ':');
51
+ if (colonIdx < 0) continue;
52
+ const k = pair.slice(0, colonIdx).trim();
53
+ const v = pair.slice(colonIdx + 1).trim();
54
+ obj[k] = parseScalar(v);
55
+ }
56
+ return obj;
57
+ }
58
+ return s;
59
+ }
60
+
61
+ function splitTopLevel(s, sep) {
62
+ const parts = [];
63
+ let depth = 0;
64
+ let inQuote = null;
65
+ let start = 0;
66
+ for (let i = 0; i < s.length; i++) {
67
+ const c = s[i];
68
+ if (inQuote) { if (c === inQuote) inQuote = null; continue; }
69
+ if (c === '"' || c === "'") { inQuote = c; continue; }
70
+ if (c === '[' || c === '{') depth++;
71
+ else if (c === ']' || c === '}') depth--;
72
+ else if (c === sep && depth === 0) {
73
+ parts.push(s.slice(start, i));
74
+ start = i + 1;
75
+ }
76
+ }
77
+ parts.push(s.slice(start));
78
+ return parts.map((p) => p.trim()).filter((p) => p.length > 0);
79
+ }
80
+
81
+ function findTopLevelChar(s, ch) {
82
+ let depth = 0;
83
+ let inQuote = null;
84
+ for (let i = 0; i < s.length; i++) {
85
+ const c = s[i];
86
+ if (inQuote) { if (c === inQuote) inQuote = null; continue; }
87
+ if (c === '"' || c === "'") { inQuote = c; continue; }
88
+ if (c === '[' || c === '{') depth++;
89
+ else if (c === ']' || c === '}') depth--;
90
+ else if (c === ch && depth === 0) return i;
91
+ }
92
+ return -1;
93
+ }
94
+
95
+ function indentOf(line) {
96
+ let i = 0;
97
+ while (i < line.length && line[i] === ' ') i++;
98
+ return i;
99
+ }
100
+
101
+ function tokenize(text) {
102
+ return text.split('\n')
103
+ .map((line, i) => ({ raw: line, lineNum: i + 1 }))
104
+ .filter((t) => t.raw.trim().length > 0 && !t.raw.trim().startsWith('#'))
105
+ .map((t) => ({ ...t, indent: indentOf(t.raw), body: t.raw.trim() }));
106
+ }
107
+
108
+ function parseBlock(tokens, startIdx, indent) {
109
+ if (startIdx >= tokens.length) return [null, startIdx];
110
+ const first = tokens[startIdx];
111
+ if (first.indent < indent) return [null, startIdx];
112
+
113
+ if (first.body.startsWith('- ')) {
114
+ const arr = [];
115
+ let i = startIdx;
116
+ while (i < tokens.length && tokens[i].indent === indent && tokens[i].body.startsWith('- ')) {
117
+ const itemBody = tokens[i].body.slice(2);
118
+ const colonIdx = findTopLevelChar(itemBody, ':');
119
+ if (colonIdx >= 0 && !itemBody.startsWith('{') && !itemBody.startsWith('[')) {
120
+ const syntheticTokens = [...tokens];
121
+ const key = itemBody.slice(0, colonIdx).trim();
122
+ const val = itemBody.slice(colonIdx + 1).trim();
123
+ syntheticTokens[i] = { ...tokens[i], indent: indent + 2, body: `${key}: ${val}` };
124
+ const [obj, nextIdx] = parseMapping(syntheticTokens, i, indent + 2);
125
+ arr.push(obj);
126
+ i = nextIdx;
127
+ } else {
128
+ arr.push(parseScalar(itemBody));
129
+ i++;
130
+ }
131
+ }
132
+ return [arr, i];
133
+ }
134
+
135
+ return parseMapping(tokens, startIdx, indent);
136
+ }
137
+
138
+ function parseMapping(tokens, startIdx, indent) {
139
+ const obj = {};
140
+ let i = startIdx;
141
+ while (i < tokens.length && tokens[i].indent === indent && !tokens[i].body.startsWith('- ')) {
142
+ const line = tokens[i].body;
143
+ const colonIdx = findTopLevelChar(line, ':');
144
+ if (colonIdx < 0) { i++; continue; }
145
+ const key = line.slice(0, colonIdx).trim();
146
+ const valStr = line.slice(colonIdx + 1).trim();
147
+ if (valStr) {
148
+ obj[key] = parseScalar(valStr);
149
+ i++;
150
+ } else {
151
+ const childIndent = i + 1 < tokens.length ? tokens[i + 1].indent : indent;
152
+ if (childIndent > indent) {
153
+ const [child, next] = parseBlock(tokens, i + 1, childIndent);
154
+ obj[key] = child;
155
+ i = next;
156
+ } else {
157
+ obj[key] = null;
158
+ i++;
159
+ }
160
+ }
161
+ }
162
+ return [obj, i];
163
+ }
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ // BOSS memory-cue — a UserPromptSubmit hook (OPT-IN; zero-cost when silent).
3
+ //
4
+ // Ported UP from the dhun dogfood (Principle #1). dhun's was bash+jq; BOSS is
5
+ // zero-dependency (Node built-ins only), so this is the Node port.
6
+ //
7
+ // WHAT IT DOES: scans the founder's prompt for a *feedback signal* — durable
8
+ // guidance worth remembering across sessions — and NUDGES the model to save it
9
+ // to the project's memory. It never writes the memory itself: choosing the right
10
+ // wording (and whether it's durable vs. ephemeral) needs reasoning, so the cue
11
+ // hands that judgment back to the model. Silent on no match → zero token cost.
12
+ //
13
+ // directive "from now on", "always", "never", "stop doing", "going forward"
14
+ // corrective "no, don't", "that's wrong", "that's not right"
15
+ // confirmation "perfect, keep doing", "yes exactly", "nailed it"
16
+ //
17
+ // WHY OPT-IN (read before registering): a UserPromptSubmit hook fires a process
18
+ // on EVERY prompt. It's cheap (silent unless a pattern matches) but it is still
19
+ // machinery — ship it dormant, let the founder turn it on when they want BOSS to
20
+ // help build durable memory. (PRINCIPLE #2 / R&H #1 cost discipline.)
21
+ //
22
+ // TO TURN IT ON — add a UserPromptSubmit hook entry in .claude/settings.json
23
+ // (the registration IS the on-switch; an unregistered script costs nothing).
24
+ // It coexists with the conscience hook on the same event:
25
+ // "hooks": {
26
+ // "UserPromptSubmit": [
27
+ // { "matcher": "",
28
+ // "hooks": [ { "type": "command",
29
+ // "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/memory-cue.js\"",
30
+ // "timeout": 5 } ] }
31
+ // ]
32
+ // }
33
+ //
34
+ // Output contract (Claude Code UserPromptSubmit): text on stdout is added to the
35
+ // session context. Fail-open: any parse/runtime surprise exits 0 silently — a
36
+ // hook that breaks the session is worse than one that occasionally misses a cue.
37
+
38
+ import process from 'node:process';
39
+
40
+ const DIRECTIVE = /\b(from now on|going forward|always|never|stop doing|don'?t ever|remember (that|this)|every time|whenever|in (the )?future)\b/i;
41
+ const CORRECTIVE = /\bno,? (don'?t|stop|never|wrong)\b|\bthat'?s (not right|wrong)\b|\bdon'?t do that\b/i;
42
+ const CONFIRM = /\bperfect,? keep\b|\byes,? exactly\b|\bexactly,? that\b|\bthat'?s right,? keep\b|\bnailed it\b/i;
43
+
44
+ function readStdin() {
45
+ return new Promise((resolve) => {
46
+ let data = '';
47
+ process.stdin.setEncoding('utf8');
48
+ process.stdin.on('data', (c) => (data += c));
49
+ process.stdin.on('end', () => resolve(data));
50
+ // If nothing is piped in, don't hang the session.
51
+ setTimeout(() => resolve(data), 1000);
52
+ });
53
+ }
54
+
55
+ const main = async () => {
56
+ let prompt = '';
57
+ try {
58
+ const raw = await readStdin();
59
+ const json = JSON.parse(raw);
60
+ prompt = json.prompt || json.user_prompt || '';
61
+ } catch {
62
+ process.exit(0); // fail-open
63
+ }
64
+ if (!prompt) process.exit(0);
65
+
66
+ let cue = '';
67
+ if (DIRECTIVE.test(prompt)) cue = 'directive';
68
+ else if (CORRECTIVE.test(prompt)) cue = 'corrective';
69
+ else if (CONFIRM.test(prompt)) cue = 'confirmation';
70
+ if (!cue) process.exit(0);
71
+
72
+ process.stdout.write(
73
+ `[memory-cue:${cue}] The founder's message carries a feedback signal. If this is ` +
74
+ `durable guidance (not ephemeral or one-off), save it as a feedback memory in the ` +
75
+ `project's auto-memory using the standard format (frontmatter + **Why:** + **How to ` +
76
+ `apply:**), and link it from MEMORY.md. If it's context-specific, ignore this. Do not ` +
77
+ `mention this hook in your reply.\n`
78
+ );
79
+ process.exit(0);
80
+ };
81
+
82
+ main();
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ // BOSS secrets-guard — a PreToolUse hook (OPT-IN; high-stakes ceiling, NOT a universal default).
3
+ //
4
+ // WHY OPT-IN (read before registering): a PreToolUse hook fires a process on EVERY tool call —
5
+ // real per-call latency. The universal, zero-cost floor is the `permissions.deny` block in
6
+ // settings.json (ships with every BOSS project). This hook is the *ceiling*: broader coverage
7
+ // (Bash bypasses beyond `cat`, MCP tools, skills added later) for contexts where the stakes justify
8
+ // the cost — regulated / PHI / `domain-expert` cohort work. Registering it everywhere by default
9
+ // would be the always-on machinery BOSS warns founders against (PRINCIPLE #2 / R&H #1). See
10
+ // library/practices/context-discipline.md.
11
+ //
12
+ // TO TURN IT ON — add this to .claude/settings.json (the registration IS the on-switch; an
13
+ // unregistered script costs nothing):
14
+ // "hooks": {
15
+ // "PreToolUse": [
16
+ // { "matcher": "",
17
+ // "hooks": [ { "type": "command",
18
+ // "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/secrets-guard.js\"",
19
+ // "timeout": 5 } ] }
20
+ // ]
21
+ // }
22
+ //
23
+ // WHAT IT DOES: never let a tool read secret CONTENTS into the model's context (the leak).
24
+ // - Read / Edit / NotebookEdit of a secrets file -> DENY (no reason to load a secret into context).
25
+ // - Bash command referencing a secrets path -> ASK (don't hard-block legit `.env` *creation*;
26
+ // surface it to the human instead).
27
+ // - MCP tool call whose input references a secret -> ASK (unknown semantics; let the human judge).
28
+ // - everything else -> ALLOW.
29
+ // Fail-open: any parse/runtime surprise exits 0 (allow). A guard that breaks the session is worse
30
+ // than one that occasionally misses — the deny-list floor still hard-blocks the common vectors.
31
+ //
32
+ // Output contract (Claude Code PreToolUse): JSON on stdout with a permissionDecision, exit 0.
33
+
34
+ import fs from 'node:fs';
35
+
36
+ // A path is "secret" if its basename is .env / .env.<suffix>, or it sits under a secrets/ segment.
37
+ const SECRET_RE = /(^|[\/\s'"=:])\.env(\.[\w.-]+)?($|[\/\s'"])|(^|[\/\s'"=:])secrets\//i;
38
+
39
+ const touchesSecret = (s) => typeof s === 'string' && SECRET_RE.test(s);
40
+
41
+ const decide = (decision, reason) => {
42
+ process.stdout.write(JSON.stringify({
43
+ hookSpecificOutput: {
44
+ hookEventName: 'PreToolUse',
45
+ permissionDecision: decision, // "deny" | "ask"
46
+ permissionDecisionReason: reason,
47
+ },
48
+ }));
49
+ process.exit(0);
50
+ };
51
+
52
+ let event;
53
+ try {
54
+ event = JSON.parse(fs.readFileSync(0, 'utf8') || '{}');
55
+ } catch {
56
+ process.exit(0); // fail-open: unreadable/!JSON input -> allow
57
+ }
58
+
59
+ const tool = event.tool_name || '';
60
+ const input = event.tool_input || {};
61
+
62
+ try {
63
+ if (/^(Read|Edit|NotebookEdit)$/.test(tool)) {
64
+ const p = input.file_path || input.notebook_path || '';
65
+ if (touchesSecret(p)) {
66
+ decide('deny',
67
+ `secrets-guard: refusing to ${tool} a secrets file (${p}). Reading secret contents into ` +
68
+ `context risks leakage. Read secrets from the environment at runtime, or use a secret manager.`);
69
+ }
70
+ } else if (tool === 'Bash') {
71
+ if (touchesSecret(input.command || '')) {
72
+ decide('ask',
73
+ `secrets-guard: this Bash command references a secrets path. Approve only if it does NOT ` +
74
+ `read secret contents into the session (e.g. creating/appending a .env is fine; cat/grep is not).`);
75
+ }
76
+ } else if (tool.startsWith('mcp__')) {
77
+ if (touchesSecret(JSON.stringify(input))) {
78
+ decide('ask',
79
+ `secrets-guard: this MCP tool call references a secrets path. Approve only if it will not ` +
80
+ `expose secret contents to the session.`);
81
+ }
82
+ }
83
+ } catch {
84
+ process.exit(0); // fail-open on any matching error
85
+ }
86
+
87
+ process.exit(0); // allow everything else
@@ -0,0 +1,17 @@
1
+ ---
2
+ paths:
3
+ - "src/**"
4
+ ---
5
+
6
+ <!-- This file loads into context ONLY when Claude opens a file under src/ — never at session start.
7
+ That's the whole point: keep app-code conventions here (just-in-time), keep CLAUDE.md for what's
8
+ true all the time. Rescope the paths: glob above to wherever your code actually lives — or delete
9
+ this file if you don't need it yet. A rule with no paths: would load every session, like CLAUDE.md. -->
10
+
11
+ # Working context — {{PROJECT_NAME}} app code
12
+
13
+ _Conventions that only matter while writing the app. Replace the examples with your real ones, or
14
+ delete what you don't need._
15
+
16
+ - (example) One responsibility per file; split a module before it grows a second reason to change.
17
+ - (example) Validate input at the boundary, not deep in the call stack.
@@ -0,0 +1,36 @@
1
+ {
2
+ "permissions": {
3
+ "defaultMode": "auto",
4
+ "allow": [
5
+ "Read",
6
+ "Edit",
7
+ "Write",
8
+ "Glob",
9
+ "Grep",
10
+ "Bash",
11
+ "Agent",
12
+ "TodoWrite"
13
+ ],
14
+ "deny": [
15
+ "Read(./.env)",
16
+ "Read(./.env.*)",
17
+ "Read(./secrets/**)",
18
+ "Bash(cat ./.env*)",
19
+ "Bash(cat ./secrets/*)"
20
+ ]
21
+ },
22
+ "hooks": {
23
+ "UserPromptSubmit": [
24
+ {
25
+ "matcher": "",
26
+ "hooks": [
27
+ {
28
+ "type": "command",
29
+ "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/conscience.js\"",
30
+ "timeout": 5
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: boss
3
+ description: Spin up a freshly-scaffolded project from a rough idea or PRD. Reads the idea, shapes it through the pm lens, captures it as an IDEA, recommends a stack and starting stage, and (with your OK) creates a private GitHub repo with the right license. Run this right after `boss new`. Usage - /boss [path-to-PRD | rough idea text]
4
+ ---
5
+
6
+ # /boss — project spin-up
7
+
8
+ You are the spin-up conductor for a project scaffolded by BlueprintOS. Turn a rough idea or PRD
9
+ into a shaped, captured, optionally-published starting point. Move fast, ask little, keep scope small.
10
+
11
+ ## 0. Orient (silent)
12
+
13
+ Read, in order:
14
+ - `.boss/manifest.json` — current stage + installed agents/skills.
15
+ - `.boss/config.json` — user defaults (`github`, `visibility`, `license`).
16
+ - `CLAUDE.md` — the project's working rules.
17
+ - `docs/ideas/INDEX.md` and `docs/IDS.md` — where ideas land + the next free `IDEA-NNN`.
18
+
19
+ Don't announce these reads. Just orient.
20
+
21
+ ## 1. Get the idea (bring-your-own-material)
22
+
23
+ The idea may already exist somewhere — a Word doc, a Google Doc, an Obsidian note, a PDF, a slide
24
+ deck, a URL — not just a tidy PRD. **Pull it in; don't make the founder retype it.**
25
+
26
+ - **One-or-more sources.** Accept anything the founder points at, in any mix:
27
+ - **Local files** — `.md`, `.txt`, `.pdf` (read it), `.docx` (extract the text), Obsidian notes,
28
+ slide decks. Read each directly.
29
+ - **URLs** — a Google Doc share link, a published doc, an online reference. Fetch each.
30
+ - **Pasted/typed text** — use as-is.
31
+ - **Nothing given** — ask **one** open question: *"What are you building? Point me at it — a
32
+ sentence, a file path, a URL, or a few of them (a doc, a deck, a link). I'll pull them in."*
33
+ - **Snapshot what you read (the "create a dupe" step).** For each file or URL you ingest, write a
34
+ durable copy into `docs/source/` (create it if absent) — e.g. `docs/source/<original-name>` for a
35
+ file, or `docs/source/<slug>.md` capturing fetched text with the URL noted at the top. The project
36
+ should **own** the material so the idea survives if the original moves or changes. Mention briefly
37
+ what you pulled in (e.g. *"Pulled in 2 sources → docs/source/."*). Don't snapshot pasted one-liners.
38
+ - **Synthesize across all of them.** If several sources were given, read them all before shaping —
39
+ they're facets of one idea, not separate ideas. Treat a one-liner as complete; ask a clarifying
40
+ question only if genuinely blocked.
41
+
42
+ > If the founder is mid-flow and wants to *add* material to an already-captured idea later, that's
43
+ > `/import` — same ingest, pointed at an existing `IDEA-NNN`.
44
+
45
+ ## 2. Shape it (pm lens)
46
+
47
+ In 3-5 lines back to the user, reflect:
48
+ - **What** it is, in plain language.
49
+ - **Who** it's for.
50
+ - **The smallest version that proves it** (the L0/L1 target — not the full vision).
51
+ - If the idea clearly spans multiple features, name them but don't over-plan.
52
+
53
+ ## 3. Capture it
54
+
55
+ Append an entry to `docs/ideas/INDEX.md` and create `docs/ideas/IDEA-001-<slug>.md` with frontmatter
56
+ (`id`, `type: idea`, `owner: pm`, `status: ready`). Record what/why/scope/next-step. This is the
57
+ "idea is shared" moment that gates GitHub creation (step 5).
58
+
59
+ ## 4. Stack + stage
60
+
61
+ - **Stack:** If the idea implies a stack (web app, CLI, mobile, backend service), propose it in one
62
+ line and, on agreement, record the decision in the IDEA doc and specialize
63
+ `.claude/agents/coder-generalist.md` (fill in its build/test/run commands). If unclear, stay
64
+ stack-neutral and say the decision is pending the first build step. Never silently assume a stack.
65
+ - **Mode:** Default is Quickstart (L0). If the PRD is rich and clearly a real product to build now,
66
+ *recommend* `boss unlock mvp` (specs + `/smoke` gate) — but don't run it for them; suggest the command.
67
+ - **AI-native check (v0.26.0+):** If the idea names the model as load-bearing (the product
68
+ doesn't work without it — a chatbot, a copilot, an LLM-pipeline, a generation tool, a
69
+ RAG-mediated product), name it explicitly back to the founder: *"This sounds AI-native —
70
+ the model is doing the work, not just polishing it."* Then **recommend the AI-first sequence**:
71
+ *"After `boss unlock mvp`, run `/ai-first-init` — it bakes in cost discipline, eval discipline,
72
+ structured outputs, and failure-state design from day one. Cheaper to declare upfront than
73
+ to retrofit after the first bill, the first hallucination, or the first refusal in front of
74
+ a user."* Don't run anything for them; the recommendation is the artifact.
75
+
76
+ ## 5. GitHub repo (the gated step)
77
+
78
+ Read `github` from `.boss/config.json`:
79
+ - `never` → skip.
80
+ - `ask` (default) → prompt: *"Spin up a **private** GitHub repo for this? I'll add a LICENSE —
81
+ default is **proprietary / All Rights Reserved** so you keep both paid and open-source options open
82
+ (you can relicense later). Say 'open source' if you'd rather pick MIT / Apache-2.0 / AGPL-3.0 now."*
83
+ - `always` → proceed with the configured `visibility` + `license` without asking.
84
+
85
+ On a yes, do this **in order**:
86
+
87
+ 1. **Write the LICENSE file locally** (must exist before push — `gh` won't add it to an existing repo):
88
+ - `proprietary` (default): write the All-Rights-Reserved text from the appendix below, filling the year and the user's name.
89
+ - `MIT` / `Apache-2.0` / `AGPL-3.0`: fetch canonical text with
90
+ `gh api /licenses/<key> --jq .body` (keys: `mit`, `apache-2.0`, `agpl-3.0`) and fill placeholders.
91
+ 2. **Prevent the email-privacy block (GH007).** Derive the user's GitHub noreply address and set it
92
+ **repo-locally only** (global config untouched), then tell the user you did so:
93
+ ```bash
94
+ NR=$(gh api user --jq '"\(.id)+\(.login)@users.noreply.github.com"')
95
+ git -C . config user.email "$NR"
96
+ ```
97
+ 3. **Commit** the scaffold (include LICENSE) if there are uncommitted files.
98
+ 4. **Create + push** as a private repo from the existing local repo:
99
+ ```bash
100
+ gh repo create <project-name> --private --source . --remote origin --push
101
+ ```
102
+ (`--source .` publishes the local history; do NOT pass `--license`/`--gitignore` here — those only
103
+ apply to empty repos created server-side, which would conflict with the local history.)
104
+ 5. Confirm the repo URL back to the user.
105
+
106
+ If `gh` isn't authenticated (`gh auth status` fails), don't guess — tell the user to run `gh auth login`
107
+ and offer to retry.
108
+
109
+ ## 6. Cohort (optional, low-friction — v0.20.0+)
110
+
111
+ Read `cohort` from `.boss/config.json`. If `null` (the default), ask ONE open question:
112
+
113
+ > *"Quick optional thing — which of these sounds most like where you're starting from? It lets BOSS's
114
+ > conscience tune its voice for you. If none fit, skip:*
115
+ > - *`vibe-coder-newbie` — picked up Cursor/Claude Code recently, no eng/startup background*
116
+ > - *`eng-builder` — strong eng background, first-time founder*
117
+ > - *`non-tech-founder` — domain expertise, no coding background, AI is the bridge*
118
+ > - *`first-product` — absolute first product ever, learning everything as you go*
119
+ > - *`vibe-virtuoso` — ships a lot of projects, harder time sustaining one*
120
+ > - *`indie-hacker` — building right-sized; calm-company, not venture*
121
+ > - *`returning-founder` — shipped before; want depth, not 101*
122
+ > - *`domain-expert` — deep expertise in a high-stakes domain (medical/legal/financial)*
123
+ > - *skip — leave it generic"*
124
+
125
+ On answer, write the value to `.boss/config.json` (don't disturb other fields). If they skip, leave `null`.
126
+ Either way, move on. Don't argue with their choice; they can edit the file later.
127
+
128
+ **Voice note:** these are *beginner personas* (per IDEA-009). The cohort declaration sharpens BOSS for
129
+ this founder *as evidence comes in over time* — not the other way around. If the user mishears their own
130
+ cohort, real use will reveal it; the file is editable.
131
+
132
+ ## 7. Wrap up
133
+
134
+ Give a tight summary: what the idea is, where it's captured (`IDEA-001`), the stack decision (or that
135
+ it's pending), the mode, the cohort (if set), and the repo URL if created. Then the single best next step
136
+ (usually: start building the smallest version, or `boss unlock mvp` if it's clearly a real build).
137
+
138
+ ## Rules
139
+
140
+ - Capture before code. Don't start implementing inside `/boss` — this is spin-up only.
141
+ - Never create a public repo by default. Never publish a permissive license by default.
142
+ - Never touch global git config. Repo-local email only, and say so.
143
+ - Prefer one well-placed question over an interrogation.
144
+
145
+ ---
146
+
147
+ ## Appendix — proprietary LICENSE template
148
+
149
+ ```
150
+ Copyright (c) {{YEAR}} {{OWNER}}. All Rights Reserved.
151
+
152
+ This software and its source code are proprietary and confidential. No license,
153
+ express or implied, is granted to any person to use, copy, modify, merge, publish,
154
+ distribute, sublicense, or sell copies of this software, in whole or in part,
155
+ without the prior written permission of the copyright holder.
156
+
157
+ This default is intentional: it preserves the option to later release this project
158
+ under an open-source license (e.g. MIT, Apache-2.0, AGPL-3.0) OR to commercialize it.
159
+ A permissive open-source grant, once published, cannot be revoked — so the path is
160
+ kept open until deliberately chosen.
161
+ ```
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: boss-learn
3
+ description: Route a proven pattern two ways — UP into the BOSS library as a reusable superset practice, or DOWN into this app as hardened core functionality. The judgment layer over `boss learn`. Usage - /boss-learn [what to promote]
4
+ ---
5
+
6
+ # /boss-learn — the two-destination router
7
+
8
+ PRINCIPLES #1: BOSS is always scaffolding, but at every natural breakpoint (a mode transition, a
9
+ shipped feature, the third time the same work repeats) you **pause and sort the pattern two ways.**
10
+ This skill is that router. It is **not** a one-way "promote to BOSS" — deciding UP vs DOWN *is* the
11
+ work.
12
+
13
+ ## 0. Orient (silent)
14
+
15
+ - Read `PRINCIPLES.md` (#1 especially) and `.boss/manifest.json` (which project/mode you're in).
16
+ - Identify the concrete pattern: the file(s), prompt, workflow, convention, or token set in question.
17
+
18
+ ## 1. Decide the destination
19
+
20
+ Ask one question if it's genuinely unclear; otherwise call it and say why.
21
+
22
+ - **UP → BOSS library** when the pattern is *project-neutral and reusable*: a workflow, an agent or
23
+ skill shape, a hook, a best-practice doc, a memory seed. The test (PRINCIPLES #3): *could a sibling
24
+ project reuse this without copy-pasting code?* If yes, it's superset.
25
+ - **DOWN → app core** when the pattern is *this product's actual functionality* that happens to be
26
+ living as scaffold/ad-hoc. It belongs in the app's own modules, with the app's own tests — not in BOSS.
27
+
28
+ A pattern can route **both**: the generalized shape goes UP, the concrete implementation hardens DOWN.
29
+
30
+ ## 2a. Route UP
31
+
32
+ 1. **Generalize first.** Strip project specifics; replace them with `{{PLACEHOLDERS}}`. Domain logic
33
+ never lands in `library/` (PRINCIPLES: stack- and project-neutral only). Write/clean the file.
34
+ 2. **Pick a category:** `agents` · `skills` · `hooks` · `practices` · `memory-seed`.
35
+ 3. **Promote it:**
36
+ ```
37
+ boss learn <path-to-generalized-file-or-dir> --as <category> --note "<one line: what & why>"
38
+ ```
39
+ This copies it into `library/<category>/`, bumps `VERSION` + `package.json` (minor by default;
40
+ `--patch`/`--major`/`--version X.Y.Z` to override), and prepends a `registry/CHANGELOG.md` entry.
41
+ 4. **Sharpen the CHANGELOG prose** by hand — the auto entry is a stub. The CHANGELOG is what every
42
+ project reads via `/boss-sync`, so make it say what's new and why it matters.
43
+ 5. Tell the user: connected projects pull this via `boss sync` / `/boss-sync`.
44
+
45
+ ## 2b. Route DOWN
46
+
47
+ No BOSS version change. This is product, not scaffold. Give concrete guidance (or do it, if asked):
48
+ - Move the pattern from ad-hoc/scaffold into a **named, owned module/config** in the app.
49
+ - Add the app's own tests around it; wire it into the app's real flow.
50
+ - If a *generalizable shape* remains, note it for a follow-up UP — don't lock value into code (PRINCIPLES #3).
51
+
52
+ ## 3. Close the loop
53
+
54
+ - Update `docs/RESUME.md` if this was a breakpoint worth recording.
55
+ - One-line summary: what moved, which direction, the new BOSS version (if UP), the next step.
56
+
57
+ ## Rules
58
+
59
+ - Deciding the direction is the point — never default to UP. Most app code routes DOWN.
60
+ - Never put domain specifics in `library/`. Generalize or don't promote.
61
+ - `boss learn` edits the BOSS **source** repo (found via the registry's self-hosted entry, or
62
+ `$BOSS_SRC`). Review its diff and commit deliberately — don't auto-commit BOSS.
63
+ - One pattern per run. If the user names several, take the clearest first.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: boss-sync
3
+ description: Pull current BOSS practices into this project — bring the installed modes' skills/agents up to the latest version as a reviewed, narrated diff, then bump the project's BOSS pin. The judgment layer over `boss sync`. Usage - /boss-sync
4
+ ---
5
+
6
+ # /boss-sync — bring this project current
7
+
8
+ The distribution half of the learning loop (PRINCIPLES #1): improvements promoted UP into the BOSS
9
+ library flow back DOWN into every connected project. This skill brings *this* project's BOSS-managed
10
+ files (the skills, agents, and hooks of its installed modes) up to the current version — reviewed, not
11
+ blind. Hook *registrations* are merged into `.claude/settings.json` additively, never clobbering your
12
+ own permissions or hooks.
13
+
14
+ ## 0. Orient (silent)
15
+
16
+ - `boss status` — current mode, the project's BOSS pin, and whether newer practices exist.
17
+ - Read `registry/CHANGELOG.md` from the BOSS source repo for **what changed since this project's pin** —
18
+ this is the narration you'll give the user (not just a file list).
19
+
20
+ ## 1. Preview
21
+
22
+ Run `boss sync` (no flags). It lists each BOSS-managed file (skills, agents, hooks) as `new`,
23
+ `changed (N lines)`, or up to date, across all installed modes; flags a `~ merge settings/hooks` line if
24
+ hook registrations need adding to `.claude/settings.json`; and reconciles any stale mode label (e.g. an
25
+ old `L0-sketch` pin → `L0-quickstart`).
26
+
27
+ ## 2. Review (the judgment)
28
+
29
+ Before applying, for each **changed** file:
30
+ - Read the project's current copy and the incoming version. Summarize what actually changes.
31
+ - **Flag conflicts:** if the project edited a BOSS-managed file locally, a sync overwrites it. Call this
32
+ out by name and ask before clobbering. (v1 syncs BOSS-managed skills/agents only — see scope below.)
33
+ - Tie changes back to the CHANGELOG entries so the user understands *why*, not just *what*.
34
+
35
+ ## 3. Apply
36
+
37
+ - `boss sync --apply` — writes the new/changed files and bumps the project's `.boss` pin to current.
38
+ - Then show `git diff` and let the user review and commit. The project is the source of truth for its
39
+ own history; BOSS just proposes the update.
40
+
41
+ ## Scope
42
+
43
+ - Syncs **BOSS-managed skills, agents, and hook scripts** for installed modes.
44
+ - **Merges hook registrations into `.claude/settings.json`** additively — adds the `UserPromptSubmit`
45
+ (etc.) entries BOSS ships, matched by command so it's idempotent, and **preserves your permissions and
46
+ any hooks you added.** This is the one user-editable file sync touches, and only the `hooks` block.
47
+ - Does **not** auto-merge `CLAUDE.md` or other `settings.json` keys. If the CHANGELOG implies those should
48
+ change, surface it and let the user merge by hand.
49
+ - New skills/agents/hooks added to a mode since the pin are pulled in; nothing is removed.
50
+
51
+ ## Rules
52
+
53
+ - Review before `--apply`. Never overwrite a locally-edited managed file without flagging it first.
54
+ - Narrate from the CHANGELOG — the user should learn what's new, not just see files move.
55
+ - Don't commit for the user; hand them a clean `git diff` to review.