@isaacriehm/cairn-core 0.3.2 → 0.3.4
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/dist/.tsbuildinfo +1 -1
- package/dist/init/brand-derive.d.ts +32 -0
- package/dist/init/brand-derive.js +158 -0
- package/dist/init/brand-derive.js.map +1 -0
- package/dist/init/brand-setup.js +9 -0
- package/dist/init/brand-setup.js.map +1 -1
- package/dist/init/phases/5-brand.d.ts +10 -4
- package/dist/init/phases/5-brand.js +36 -10
- package/dist/init/phases/5-brand.js.map +1 -1
- package/package.json +1 -1
- package/templates/.cairn/ground/brand/overview.md +41 -9
- package/templates/.cairn/ground/brand/voice.md +36 -4
- package/templates/.cairn/ground/capabilities/mcp-tools.yaml +27 -2
- package/templates/.cairn/ground/capabilities/skills.yaml +23 -1
- package/templates/.cairn/ground/capabilities/snippets.yaml +27 -0
- package/templates/.cairn/ground/product/personas.yaml +35 -1
- package/templates/.cairn/ground/product/positioning.md +43 -5
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand inference — Haiku-derived overview / voice / personas / avoid
|
|
3
|
+
* from project signals (README + CLAUDE.md / AGENTS.md tone +
|
|
4
|
+
* mapper's domain_summary). Called by Phase 5-brand auto-fill so the
|
|
5
|
+
* adopted project gets meaningful brand drafts instead of mechanical
|
|
6
|
+
* defaults. Falls back to the mechanical defaults when the call fails
|
|
7
|
+
* — the result shape always matches `BrandAnswers`.
|
|
8
|
+
*/
|
|
9
|
+
import type { BrandAnswers } from "./brand-setup.js";
|
|
10
|
+
interface DerivedBrand {
|
|
11
|
+
overview: string;
|
|
12
|
+
voice: string;
|
|
13
|
+
avoid: string;
|
|
14
|
+
personas: {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
}[];
|
|
18
|
+
}
|
|
19
|
+
interface DeriveArgs {
|
|
20
|
+
repoRoot: string;
|
|
21
|
+
projectSlug: string;
|
|
22
|
+
domainSummary: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function deriveBrandFromProject(args: DeriveArgs): Promise<DerivedBrand | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Convert derived brand to the `BrandAnswers` shape consumed by
|
|
27
|
+
* `applyBrandAnswers`. Combines voice + avoid since the brand voice
|
|
28
|
+
* file already takes both. Personas collapse to the first entry's
|
|
29
|
+
* description (multi-persona support → v0.4 schema extension).
|
|
30
|
+
*/
|
|
31
|
+
export declare function derivedToBrandAnswers(d: DerivedBrand): BrandAnswers;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand inference — Haiku-derived overview / voice / personas / avoid
|
|
3
|
+
* from project signals (README + CLAUDE.md / AGENTS.md tone +
|
|
4
|
+
* mapper's domain_summary). Called by Phase 5-brand auto-fill so the
|
|
5
|
+
* adopted project gets meaningful brand drafts instead of mechanical
|
|
6
|
+
* defaults. Falls back to the mechanical defaults when the call fails
|
|
7
|
+
* — the result shape always matches `BrandAnswers`.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { runClaude } from "../claude/index.js";
|
|
12
|
+
import { logger } from "../logger.js";
|
|
13
|
+
const log = logger("init.brand-derive");
|
|
14
|
+
const TIMEOUT_MS = 30_000;
|
|
15
|
+
const README_CHARS = 800;
|
|
16
|
+
const RULES_CHARS = 1_000;
|
|
17
|
+
const SYSTEM_PROMPT = `You write SHORT brand-identity drafts for a software project, given:
|
|
18
|
+
- the project slug
|
|
19
|
+
- a one-sentence domain summary (what the project does)
|
|
20
|
+
- the README first 800 chars (if any)
|
|
21
|
+
- the CLAUDE.md / AGENTS.md tone signals (if any)
|
|
22
|
+
|
|
23
|
+
Return STRICT JSON matching the schema below. No markdown, no
|
|
24
|
+
preamble. Each field is a tight, scannable paragraph the operator
|
|
25
|
+
will refine — not marketing copy.
|
|
26
|
+
|
|
27
|
+
Field guidance:
|
|
28
|
+
- overview: 1 paragraph, ≤120 words. What the product is + its
|
|
29
|
+
personality + tone + what it avoids. Ground every claim in
|
|
30
|
+
the input signals; don't speculate beyond them.
|
|
31
|
+
- voice: 1 paragraph, ≤80 words. How the brand TALKS (register,
|
|
32
|
+
sentence shape, vocabulary). Match the existing CLAUDE.md /
|
|
33
|
+
AGENTS.md tone if those files set a register; otherwise default
|
|
34
|
+
to short, direct, project-aware.
|
|
35
|
+
- avoid: 1 paragraph, ≤60 words. What's off-limits — generic
|
|
36
|
+
marketing language, speculative claims about behavior the code
|
|
37
|
+
doesn't implement, anything contradicting cited DECs / §INVs.
|
|
38
|
+
- personas: 1-3 entries, each with {name (kebab-case),
|
|
39
|
+
description (≤120 chars)}. Default \`name=primary\` when only
|
|
40
|
+
one user type is evident.
|
|
41
|
+
|
|
42
|
+
Never invent product features that aren't in the input signals.
|
|
43
|
+
Never reference real companies, real customers, or real people.`;
|
|
44
|
+
const OUTPUT_SCHEMA = {
|
|
45
|
+
type: "object",
|
|
46
|
+
required: ["overview", "voice", "avoid", "personas"],
|
|
47
|
+
properties: {
|
|
48
|
+
overview: { type: "string", minLength: 1 },
|
|
49
|
+
voice: { type: "string", minLength: 1 },
|
|
50
|
+
avoid: { type: "string", minLength: 1 },
|
|
51
|
+
personas: {
|
|
52
|
+
type: "array",
|
|
53
|
+
minItems: 1,
|
|
54
|
+
maxItems: 3,
|
|
55
|
+
items: {
|
|
56
|
+
type: "object",
|
|
57
|
+
required: ["name", "description"],
|
|
58
|
+
properties: {
|
|
59
|
+
name: { type: "string", minLength: 1 },
|
|
60
|
+
description: { type: "string", minLength: 1 },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
function readSignalFile(repoRoot, name, cap) {
|
|
67
|
+
const path = join(repoRoot, name);
|
|
68
|
+
if (!existsSync(path))
|
|
69
|
+
return null;
|
|
70
|
+
try {
|
|
71
|
+
const raw = readFileSync(path, "utf8");
|
|
72
|
+
return raw.length > cap ? raw.slice(0, cap) : raw;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function buildUserPrompt(args) {
|
|
79
|
+
const readme = readSignalFile(args.repoRoot, "README.md", README_CHARS);
|
|
80
|
+
const agents = readSignalFile(args.repoRoot, "AGENTS.md", RULES_CHARS);
|
|
81
|
+
const claudeMd = readSignalFile(args.repoRoot, "CLAUDE.md", RULES_CHARS);
|
|
82
|
+
const lines = [];
|
|
83
|
+
lines.push(`Project slug: ${args.projectSlug}`);
|
|
84
|
+
lines.push("");
|
|
85
|
+
lines.push("Domain summary (mapper output):");
|
|
86
|
+
lines.push(args.domainSummary);
|
|
87
|
+
lines.push("");
|
|
88
|
+
if (readme !== null) {
|
|
89
|
+
lines.push("README.md (first 800 chars):");
|
|
90
|
+
lines.push(readme);
|
|
91
|
+
lines.push("");
|
|
92
|
+
}
|
|
93
|
+
if (agents !== null) {
|
|
94
|
+
lines.push("AGENTS.md (first 1000 chars — tone signal):");
|
|
95
|
+
lines.push(agents);
|
|
96
|
+
lines.push("");
|
|
97
|
+
}
|
|
98
|
+
if (claudeMd !== null) {
|
|
99
|
+
lines.push("CLAUDE.md (first 1000 chars — tone signal):");
|
|
100
|
+
lines.push(claudeMd);
|
|
101
|
+
lines.push("");
|
|
102
|
+
}
|
|
103
|
+
return lines.join("\n");
|
|
104
|
+
}
|
|
105
|
+
export async function deriveBrandFromProject(args) {
|
|
106
|
+
try {
|
|
107
|
+
const result = await runClaude({
|
|
108
|
+
tier: "haiku",
|
|
109
|
+
prompt: buildUserPrompt(args),
|
|
110
|
+
system: SYSTEM_PROMPT,
|
|
111
|
+
jsonSchema: OUTPUT_SCHEMA,
|
|
112
|
+
timeoutMs: TIMEOUT_MS,
|
|
113
|
+
});
|
|
114
|
+
const parsed = result.parsed;
|
|
115
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
116
|
+
return null;
|
|
117
|
+
const v = parsed;
|
|
118
|
+
const overview = typeof v["overview"] === "string" ? v["overview"] : null;
|
|
119
|
+
const voice = typeof v["voice"] === "string" ? v["voice"] : null;
|
|
120
|
+
const avoid = typeof v["avoid"] === "string" ? v["avoid"] : null;
|
|
121
|
+
const rawPersonas = Array.isArray(v["personas"]) ? v["personas"] : null;
|
|
122
|
+
if (overview === null || voice === null || avoid === null || rawPersonas === null) {
|
|
123
|
+
log.warn({ hasOverview: overview !== null, hasVoice: voice !== null, hasAvoid: avoid !== null, hasPersonas: rawPersonas !== null }, "brand-derive: missing fields in Haiku response");
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const personas = [];
|
|
127
|
+
for (const entry of rawPersonas) {
|
|
128
|
+
if (typeof entry !== "object" || entry === null)
|
|
129
|
+
continue;
|
|
130
|
+
const e = entry;
|
|
131
|
+
if (typeof e["name"] === "string" && typeof e["description"] === "string") {
|
|
132
|
+
personas.push({ name: e["name"], description: e["description"] });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (personas.length === 0)
|
|
136
|
+
return null;
|
|
137
|
+
return { overview, voice, avoid, personas };
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
log.warn({ err: String(err) }, "brand-derive: Haiku call failed");
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Convert derived brand to the `BrandAnswers` shape consumed by
|
|
146
|
+
* `applyBrandAnswers`. Combines voice + avoid since the brand voice
|
|
147
|
+
* file already takes both. Personas collapse to the first entry's
|
|
148
|
+
* description (multi-persona support → v0.4 schema extension).
|
|
149
|
+
*/
|
|
150
|
+
export function derivedToBrandAnswers(d) {
|
|
151
|
+
return {
|
|
152
|
+
whatItDoes: d.overview,
|
|
153
|
+
mainUsers: d.personas.map((p) => `${p.name}: ${p.description}`).join(" · "),
|
|
154
|
+
voice: d.voice,
|
|
155
|
+
avoid: d.avoid,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=brand-derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand-derive.js","sourceRoot":"","sources":["../../src/init/brand-derive.ts"],"names":[],"mappings":"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"}
|
package/dist/init/brand-setup.js
CHANGED
|
@@ -79,6 +79,15 @@ export function applyBrandAnswers(repoRoot, answers) {
|
|
|
79
79
|
const ok = rewriteWithBody(join(repoRoot, rel), answers.whatItDoes, warnings, rel);
|
|
80
80
|
if (ok)
|
|
81
81
|
updated.push(rel);
|
|
82
|
+
// Also pre-fill brand/overview.md with the same domain summary —
|
|
83
|
+
// gives the operator a populated starting point instead of an
|
|
84
|
+
// empty `(operator: replace this paragraph...)` placeholder.
|
|
85
|
+
// Operator can diverge overview vs. positioning later; until
|
|
86
|
+
// then they share content.
|
|
87
|
+
const overviewRel = ".cairn/ground/brand/overview.md";
|
|
88
|
+
const overviewOk = rewriteWithBody(join(repoRoot, overviewRel), answers.whatItDoes, warnings, overviewRel);
|
|
89
|
+
if (overviewOk)
|
|
90
|
+
updated.push(overviewRel);
|
|
82
91
|
}
|
|
83
92
|
if (answers.mainUsers.length > 0) {
|
|
84
93
|
const rel = ".cairn/ground/product/personas.yaml";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brand-setup.js","sourceRoot":"","sources":["../../src/init/brand-setup.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"brand-setup.js","sourceRoot":"","sources":["../../src/init/brand-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Phase 5-brand — adopt brand DEC drafts inline.
|
|
3
3
|
*
|
|
4
|
-
* Emits ONE A/B/C choice. `auto-fill` substitutes positioning +
|
|
5
|
-
* from the mapper's domain summary
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Emits ONE A/B/C choice. `auto-fill` substitutes positioning +
|
|
5
|
+
* brand-overview + voice + personas from the mapper's domain summary
|
|
6
|
+
* + sensible defaults; `skip` leaves status: draft for later editing;
|
|
7
|
+
* `manual` hands off to the operator (drafts stay draft, summary
|
|
8
|
+
* surfaces the file paths to edit).
|
|
9
|
+
*
|
|
10
|
+
* Auto-fill writes a populated draft to every brand/product file.
|
|
11
|
+
* Operator can refine + flip status to `accepted` when ready;
|
|
12
|
+
* doctor reports draft brand files as informational, not warning,
|
|
13
|
+
* so CI passes during the operator-paced review.
|
|
8
14
|
*/
|
|
9
15
|
import type { PhaseResult, PhaseState } from "./types.js";
|
|
10
16
|
export declare function runPhase5Brand(state: PhaseState): Promise<PhaseResult>;
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Phase 5-brand — adopt brand DEC drafts inline.
|
|
3
3
|
*
|
|
4
|
-
* Emits ONE A/B/C choice. `auto-fill` substitutes positioning +
|
|
5
|
-
* from the mapper's domain summary
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Emits ONE A/B/C choice. `auto-fill` substitutes positioning +
|
|
5
|
+
* brand-overview + voice + personas from the mapper's domain summary
|
|
6
|
+
* + sensible defaults; `skip` leaves status: draft for later editing;
|
|
7
|
+
* `manual` hands off to the operator (drafts stay draft, summary
|
|
8
|
+
* surfaces the file paths to edit).
|
|
9
|
+
*
|
|
10
|
+
* Auto-fill writes a populated draft to every brand/product file.
|
|
11
|
+
* Operator can refine + flip status to `accepted` when ready;
|
|
12
|
+
* doctor reports draft brand files as informational, not warning,
|
|
13
|
+
* so CI passes during the operator-paced review.
|
|
8
14
|
*/
|
|
9
15
|
import { applyBrandAnswers } from "../brand-setup.js";
|
|
16
|
+
import { deriveBrandFromProject, derivedToBrandAnswers } from "../brand-derive.js";
|
|
10
17
|
import { advancePhase } from "./orchestrator.js";
|
|
18
|
+
const DEFAULT_VOICE = "Direct, technical, project-aware. Match the existing tone in CLAUDE.md / AGENTS.md if those files set a register; otherwise default to short sentences, full English, no marketing language.";
|
|
19
|
+
const DEFAULT_AVOID = "Marketing fluff (\"world-class\", \"revolutionary\", \"game-changing\"). Speculative claims about behavior the code does not implement. Anything that contradicts an in-scope DEC or §INV.";
|
|
20
|
+
function deriveDefaultUsers(state) {
|
|
21
|
+
const detect = state.outputs["1-detect"];
|
|
22
|
+
const slug = detect?.project_slug ?? "this project";
|
|
23
|
+
return `Developers and operators working on ${slug}. Refine when adding consumer-facing or external personas.`;
|
|
24
|
+
}
|
|
11
25
|
export async function runPhase5Brand(state) {
|
|
12
26
|
// Pending operator answer → execute the chosen path.
|
|
13
27
|
if (state.answer !== undefined && state.answer.length > 0) {
|
|
@@ -16,12 +30,24 @@ export async function runPhase5Brand(state) {
|
|
|
16
30
|
if (choice === "auto-fill") {
|
|
17
31
|
const mapper = state.outputs["3-mapper"];
|
|
18
32
|
if (mapper !== undefined) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
33
|
+
const detect = state.outputs["1-detect"];
|
|
34
|
+
const projectSlug = detect?.project_slug ?? "this-project";
|
|
35
|
+
// Try Haiku-derived brand from README + AGENTS.md / CLAUDE.md
|
|
36
|
+
// tone signals + mapper domain summary. Falls back to the
|
|
37
|
+
// mechanical defaults if the call fails.
|
|
38
|
+
const derived = await deriveBrandFromProject({
|
|
39
|
+
repoRoot: state.repoRoot,
|
|
40
|
+
projectSlug,
|
|
41
|
+
domainSummary: mapper.output.domain_summary,
|
|
42
|
+
});
|
|
43
|
+
const answers = derived !== null
|
|
44
|
+
? derivedToBrandAnswers(derived)
|
|
45
|
+
: {
|
|
46
|
+
whatItDoes: mapper.output.domain_summary,
|
|
47
|
+
mainUsers: deriveDefaultUsers(state),
|
|
48
|
+
voice: DEFAULT_VOICE,
|
|
49
|
+
avoid: DEFAULT_AVOID,
|
|
50
|
+
};
|
|
25
51
|
result = applyBrandAnswers(state.repoRoot, answers);
|
|
26
52
|
}
|
|
27
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"5-brand.js","sourceRoot":"","sources":["../../../src/init/phases/5-brand.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"5-brand.js","sourceRoot":"","sources":["../../../src/init/phases/5-brand.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isaacriehm/cairn-core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Cairn core — state + context layer. Curated `.cairn/ground/` (decisions, §INV invariants, canonical-map, brand, quality-grades), MCP server, init wizard, hook runners, sensors, GC drift sweep.",
|
|
5
5
|
"author": "Isaac Riehm",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,14 +11,46 @@ source-commits:
|
|
|
11
11
|
# Brand overview
|
|
12
12
|
|
|
13
13
|
<!--
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
WHAT THIS FILE IS
|
|
15
|
+
|
|
16
|
+
A one-paragraph product personality summary. Injected at every
|
|
17
|
+
SessionStart so Claude knows what your product looks and sounds like
|
|
18
|
+
before it makes design decisions or writes operator-facing text.
|
|
19
|
+
|
|
20
|
+
WHEN TO FILL IT IN
|
|
21
|
+
|
|
22
|
+
Adoption pre-fills the body below from the project mapper output (one
|
|
23
|
+
sentence describing what the product does). Edit it to add personality
|
|
24
|
+
+ tone + what to avoid. Flip `status: draft` → `status: accepted` once
|
|
25
|
+
filled.
|
|
26
|
+
|
|
27
|
+
FORMAT
|
|
28
|
+
|
|
29
|
+
≤200 tokens. Cover three things:
|
|
30
|
+
1. Product personality — adjectives that describe the brand
|
|
31
|
+
2. Tone — how the brand talks
|
|
32
|
+
3. Avoid — what's off-limits (jargon, comparisons, claims)
|
|
33
|
+
|
|
34
|
+
Two examples to anchor on:
|
|
35
|
+
|
|
36
|
+
Example A (fictional consumer service):
|
|
37
|
+
> FoxGlove Florist hand-arranges seasonal bouquets for local
|
|
38
|
+
> delivery. Personality: warm, craft-focused, slightly nostalgic.
|
|
39
|
+
> Tone: confident but unfussy; talk about flowers like ingredients,
|
|
40
|
+
> not luxury items. Avoid: superlatives ("the best"), urgency
|
|
41
|
+
> language ("act now"), price comparisons. Visual identity is
|
|
42
|
+
> muted — sage + cream, no neon.
|
|
43
|
+
|
|
44
|
+
Example B (fictional B2B SaaS):
|
|
45
|
+
> Northstar is a developer-facing observability tool for distributed
|
|
46
|
+
> queues. Personality: opinionated, terse, engineer-to-engineer.
|
|
47
|
+
> Tone: assumes deep technical context, leads with the answer,
|
|
48
|
+
> skips preamble. Avoid: marketing fluff ("revolutionary",
|
|
49
|
+
> "game-changing"), generic AI hype, screenshot-driven feature
|
|
50
|
+
> lists, comparisons against other "monitoring" products.
|
|
51
|
+
|
|
52
|
+
Detailed visual identity (colors, typography, logo) goes in
|
|
53
|
+
sibling files: `colors.yaml`, `typography.yaml`, `logo.md`.
|
|
22
54
|
-->
|
|
23
55
|
|
|
24
|
-
(
|
|
56
|
+
(adoption auto-fill writes the project's domain summary here; edit to add personality + tone + avoid)
|
|
@@ -11,10 +11,42 @@ source-commits:
|
|
|
11
11
|
# Brand voice
|
|
12
12
|
|
|
13
13
|
<!--
|
|
14
|
-
|
|
15
|
-
knows how to talk in this project. Keep tight — < 200 tokens.
|
|
14
|
+
WHAT THIS FILE IS
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
How the brand TALKS. Tone, vocabulary, sentence rhythm, default
|
|
17
|
+
register. Read at every SessionStart so Claude matches your voice
|
|
18
|
+
in chat replies, commit messages, PR descriptions, marketing copy,
|
|
19
|
+
and any operator-facing text it generates.
|
|
20
|
+
|
|
21
|
+
WHEN TO FILL IT IN
|
|
22
|
+
|
|
23
|
+
Adoption pre-fills the body with a sensible default derived from your
|
|
24
|
+
existing CLAUDE.md / AGENTS.md tone. Edit to add specifics. Flip
|
|
25
|
+
`status: draft` → `status: accepted` once it matches reality.
|
|
26
|
+
|
|
27
|
+
FORMAT
|
|
28
|
+
|
|
29
|
+
≤200 tokens. Cover four things:
|
|
30
|
+
1. Default register (formal / casual / technical / playful)
|
|
31
|
+
2. Sentence shape (short fragments? full sentences? lists?)
|
|
32
|
+
3. Vocabulary preferences (industry terms YES / NO)
|
|
33
|
+
4. Pet peeves (phrases that immediately feel "off-brand")
|
|
34
|
+
|
|
35
|
+
Two examples to anchor on:
|
|
36
|
+
|
|
37
|
+
Example A (fictional consumer service):
|
|
38
|
+
> Casual, friendly, no jargon. Full sentences but never
|
|
39
|
+
> corporate. Use everyday words: "we'll deliver", not "we shall
|
|
40
|
+
> facilitate delivery". Avoid: "premium", "world-class", "passion
|
|
41
|
+
> for quality" — empty signals that read as filler. Sign emails
|
|
42
|
+
> with first name only.
|
|
43
|
+
|
|
44
|
+
Example B (fictional B2B SaaS):
|
|
45
|
+
> Technical, terse, engineer-to-engineer. Drop articles when it
|
|
46
|
+
> reads cleanly ("hook fires" not "the hook fires"). Lead with
|
|
47
|
+
> the answer; preamble dies. Use precise technical terms (HTTP
|
|
48
|
+
> 429 not "rate-limited"). Avoid: "AI-powered", "game-changing",
|
|
49
|
+
> emoji-heavy lists.
|
|
18
50
|
-->
|
|
19
51
|
|
|
20
|
-
(
|
|
52
|
+
(adoption auto-fill writes a default voice profile here; edit to match how your team actually talks)
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
# MCP servers registered alongside Cairn in .mcp.json.
|
|
2
|
-
#
|
|
3
|
-
#
|
|
2
|
+
#
|
|
3
|
+
# WHAT THIS FILE IS
|
|
4
|
+
#
|
|
5
|
+
# Inventory of the OTHER MCP servers this project uses (not cairn
|
|
6
|
+
# itself — cairn auto-registers via the plugin bundle). Includes
|
|
7
|
+
# server name + one-line capability summary. Read at SessionStart
|
|
8
|
+
# so the agent knows what tools it can reach without re-listing
|
|
9
|
+
# every tool exhaustively.
|
|
10
|
+
#
|
|
11
|
+
# WHEN TO FILL IT IN
|
|
12
|
+
#
|
|
13
|
+
# Operator-paced. Add an entry every time you wire up a new MCP
|
|
14
|
+
# server (Notion, Stripe, internal tools, etc.). Flip an entry's
|
|
15
|
+
# status when the server's capabilities shift.
|
|
16
|
+
#
|
|
17
|
+
# FORMAT
|
|
18
|
+
#
|
|
19
|
+
# Two examples to anchor on:
|
|
20
|
+
#
|
|
21
|
+
# mcp_tools:
|
|
22
|
+
# - name: stripe
|
|
23
|
+
# description: Stripe payments + customers + subscriptions. Use when the agent needs to look up a charge by id or check a customer's billing state.
|
|
24
|
+
# status: accepted
|
|
25
|
+
# - name: notion
|
|
26
|
+
# description: Read-only Notion workspace query. Use for cross-referencing PRDs that live in Notion, never for writes.
|
|
27
|
+
# status: accepted
|
|
28
|
+
|
|
4
29
|
mcp_tools: []
|
|
@@ -1,3 +1,25 @@
|
|
|
1
1
|
# Installed skill packs available in this session.
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
|
+
# WHAT THIS FILE IS
|
|
4
|
+
#
|
|
5
|
+
# Inventory of project-level skills the agent can invoke (the
|
|
6
|
+
# `.claude/skills/` directory of the host project). Each entry is
|
|
7
|
+
# name + one-line trigger description. Adoption seeds entries from
|
|
8
|
+
# whatever's already in `.claude/skills/`; operator extends.
|
|
9
|
+
#
|
|
10
|
+
# WHEN TO FILL IT IN
|
|
11
|
+
#
|
|
12
|
+
# Auto-populated at adoption + on `cairn fix` re-scans. Edit by
|
|
13
|
+
# hand only when adding a new project-local skill or removing one.
|
|
14
|
+
#
|
|
15
|
+
# FORMAT
|
|
16
|
+
#
|
|
17
|
+
# Two examples to anchor on:
|
|
18
|
+
#
|
|
19
|
+
# skills:
|
|
20
|
+
# - name: deploy-staging
|
|
21
|
+
# description: Push current branch to the staging GKE cluster + run smoke tests. Auto-invoke on "deploy", "ship", "push to staging".
|
|
22
|
+
# - name: db-migrate
|
|
23
|
+
# description: Generate + apply a Drizzle migration with backup snapshot. Auto-invoke when schema changes are mentioned.
|
|
24
|
+
|
|
3
25
|
skills: []
|
|
@@ -1,2 +1,29 @@
|
|
|
1
1
|
# Blessed implementations for security-sensitive patterns.
|
|
2
|
+
#
|
|
3
|
+
# WHAT THIS FILE IS
|
|
4
|
+
#
|
|
5
|
+
# A catalog of pattern → canonical-implementation pointers for code
|
|
6
|
+
# the operator wants Claude to NEVER reinvent. Each entry says "if
|
|
7
|
+
# you need to do X, copy from this exact location". Read at
|
|
8
|
+
# SessionStart so the agent skips improvising auth / signing /
|
|
9
|
+
# input-validation / etc.
|
|
10
|
+
#
|
|
11
|
+
# WHEN TO FILL IT IN
|
|
12
|
+
#
|
|
13
|
+
# Operator-paced. Add an entry every time you catch the agent
|
|
14
|
+
# hand-rolling something that has an existing blessed implementation
|
|
15
|
+
# in your codebase.
|
|
16
|
+
#
|
|
17
|
+
# FORMAT
|
|
18
|
+
#
|
|
19
|
+
# Two examples to anchor on:
|
|
20
|
+
#
|
|
21
|
+
# snippets:
|
|
22
|
+
# - pattern: jwt-signing
|
|
23
|
+
# canonical: src/auth/sign.ts:signSession
|
|
24
|
+
# why: Single source of HS256 secret + iat. Hand-rolled JWT signing has historically leaked the secret in test fixtures.
|
|
25
|
+
# - pattern: html-escape
|
|
26
|
+
# canonical: src/util/escape.ts:escape
|
|
27
|
+
# why: Uses the project's content-security-policy-aware escape; ad-hoc replace() chains miss attribute-context cases.
|
|
28
|
+
|
|
2
29
|
snippets: []
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
-
# Product personas — who this is for. Read at every SessionStart
|
|
1
|
+
# Product personas — who this is for. Read at every SessionStart so
|
|
2
|
+
# the agent frames suggestions for the right audience.
|
|
3
|
+
#
|
|
4
|
+
# WHAT THIS FILE IS
|
|
5
|
+
#
|
|
6
|
+
# YAML list of named user types. Each persona is one named role with
|
|
7
|
+
# a one-line description (≤120 chars). 1–3 personas is the sweet
|
|
8
|
+
# spot; >3 dilutes signal.
|
|
9
|
+
#
|
|
10
|
+
# WHEN TO FILL IT IN
|
|
11
|
+
#
|
|
12
|
+
# Adoption pre-fills a single `primary` persona derived from project
|
|
13
|
+
# signals (mapper output + README). Edit to refine + add secondary
|
|
14
|
+
# personas. Flip `status: draft` → `status: accepted` once filled.
|
|
15
|
+
#
|
|
16
|
+
# FORMAT
|
|
17
|
+
#
|
|
18
|
+
# Two examples to anchor on:
|
|
19
|
+
#
|
|
20
|
+
# Example A (fictional consumer service — FoxGlove Florist):
|
|
21
|
+
# status: accepted
|
|
22
|
+
# personas:
|
|
23
|
+
# - name: gift-sender
|
|
24
|
+
# description: Adult ordering flowers for someone else (birthday, anniversary, sympathy). Wants warm but unfussy presentation.
|
|
25
|
+
# - name: wedding-planner
|
|
26
|
+
# description: Event coordinator booking florals 6+ weeks ahead. Cares about delivery windows + change-tolerance.
|
|
27
|
+
#
|
|
28
|
+
# Example B (fictional B2B SaaS — Northstar):
|
|
29
|
+
# status: accepted
|
|
30
|
+
# personas:
|
|
31
|
+
# - name: backend-engineer
|
|
32
|
+
# description: Owns the queue infrastructure. Reads dashboards daily, replays deadletters weekly, never wants to leave the terminal.
|
|
33
|
+
# - name: sre-on-call
|
|
34
|
+
# description: Gets paged at 3am. Wants per-queue p99 latency + a one-click deadletter snapshot, no setup.
|
|
35
|
+
|
|
2
36
|
status: draft
|
|
3
37
|
personas: []
|
|
@@ -11,11 +11,49 @@ source-commits:
|
|
|
11
11
|
# Product positioning
|
|
12
12
|
|
|
13
13
|
<!--
|
|
14
|
-
|
|
15
|
-
what the product is and isn't. Keep it short — < 300 tokens. Cover: who
|
|
16
|
-
this is for, the core value, what's deliberately out of scope.
|
|
14
|
+
WHAT THIS FILE IS
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
A tight statement of what the product is, who it's for, and
|
|
17
|
+
deliberately what it ISN'T. Injected at every SessionStart so the
|
|
18
|
+
agent stays inside-the-fence on feature suggestions and avoids
|
|
19
|
+
proposing work outside the product's intended scope.
|
|
20
|
+
|
|
21
|
+
WHEN TO FILL IT IN
|
|
22
|
+
|
|
23
|
+
Adoption pre-fills the body with the project's domain summary from
|
|
24
|
+
the mapper. Edit to add target audience + non-goals. Flip
|
|
25
|
+
`status: draft` → `status: accepted` once filled.
|
|
26
|
+
|
|
27
|
+
FORMAT
|
|
28
|
+
|
|
29
|
+
≤300 tokens. Cover four things:
|
|
30
|
+
1. What it IS (one-sentence elevator pitch)
|
|
31
|
+
2. Who it's FOR (target operator / user)
|
|
32
|
+
3. Core value (the one job it does well)
|
|
33
|
+
4. What's deliberately OUT of scope
|
|
34
|
+
|
|
35
|
+
Two examples to anchor on:
|
|
36
|
+
|
|
37
|
+
Example A (fictional consumer service):
|
|
38
|
+
> FoxGlove Florist hand-arranges seasonal bouquets for same-day
|
|
39
|
+
> local delivery in the Pacific Northwest.
|
|
40
|
+
> For: residential customers ordering for special occasions
|
|
41
|
+
> (birthdays, sympathy, weddings).
|
|
42
|
+
> Core value: locally-grown flowers, hand-tied arrangements,
|
|
43
|
+
> deliveries within 4 hours of order.
|
|
44
|
+
> Out of scope: nationwide shipping, corporate event florals,
|
|
45
|
+
> artificial / silk arrangements, plant subscriptions.
|
|
46
|
+
|
|
47
|
+
Example B (fictional B2B SaaS):
|
|
48
|
+
> Northstar is a developer-facing observability tool that
|
|
49
|
+
> traces queue depth + worker latency across BullMQ + Sidekiq
|
|
50
|
+
> deployments.
|
|
51
|
+
> For: backend engineers + SREs running async-job systems at
|
|
52
|
+
> 1k–100k jobs/sec scale.
|
|
53
|
+
> Core value: per-queue p99 latency dashboards + deadletter
|
|
54
|
+
> replay without re-deploying.
|
|
55
|
+
> Out of scope: log aggregation, APM tracing, alerting (use
|
|
56
|
+
> PagerDuty), front-end RUM.
|
|
19
57
|
-->
|
|
20
58
|
|
|
21
|
-
(
|
|
59
|
+
(adoption auto-fill writes the project's domain summary here; edit to add audience + core value + out-of-scope)
|