@isaacriehm/cairn-core 0.15.0 → 0.15.1
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/claude-rule.d.ts +50 -0
- package/dist/init/claude-rule.js +101 -0
- package/dist/init/claude-rule.js.map +1 -0
- package/dist/init/index.d.ts +2 -0
- package/dist/init/index.js +1 -0
- package/dist/init/index.js.map +1 -1
- package/dist/init/multi-dev/install.js +31 -0
- package/dist/init/multi-dev/install.js.map +1 -1
- package/package.json +2 -2
- package/templates/.claude/rules/cairn.md +18 -12
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-absent onboarding wiring.
|
|
3
|
+
*
|
|
4
|
+
* The Cairn surface (SessionStart banner, MCP tools, scoped rule
|
|
5
|
+
* injection) is delivered by the Claude Code plugin, which is installed
|
|
6
|
+
* per-machine — cloning an adopted repo does NOT install it. The only
|
|
7
|
+
* repo-committed, plugin-independent fallback is
|
|
8
|
+
* `.claude/rules/cairn.md`, which tells a plugin-less agent to install
|
|
9
|
+
* the plugin.
|
|
10
|
+
*
|
|
11
|
+
* But Claude Code does not auto-load `.claude/rules/*.md` on its own —
|
|
12
|
+
* something has to import it. The one file Claude Code always loads with
|
|
13
|
+
* zero plugin is the root memory file (`CLAUDE.md`). So the fallback rule
|
|
14
|
+
* is only effective if that memory file `@`-imports it. Writing the rule
|
|
15
|
+
* without wiring the import (the prior behavior) left it orphaned: a
|
|
16
|
+
* teammate who cloned an adopted repo without the plugin saw nothing.
|
|
17
|
+
*
|
|
18
|
+
* `ensureCairnRuleImport` wires the import idempotently;
|
|
19
|
+
* `installCairnRuleAndImport` writes the rule template AND wires the
|
|
20
|
+
* import, for the adoption path.
|
|
21
|
+
*/
|
|
22
|
+
/** The repo-root-relative @import line Claude Code resolves. */
|
|
23
|
+
export declare const CAIRN_RULE_IMPORT = "@.claude/rules/cairn.md";
|
|
24
|
+
export interface EnsureImportResult {
|
|
25
|
+
/** True when the import line was added (false = already present). */
|
|
26
|
+
changed: boolean;
|
|
27
|
+
/** Repo-relative memory file that carries the import. */
|
|
28
|
+
file: string;
|
|
29
|
+
/** True when the memory file had to be created. */
|
|
30
|
+
created: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Ensure the project's auto-loaded memory file `@`-imports
|
|
34
|
+
* `.claude/rules/cairn.md`. Targets `CLAUDE.md` (the file Claude Code
|
|
35
|
+
* always auto-loads); falls back to `AGENTS.md` only when `CLAUDE.md` is
|
|
36
|
+
* absent but `AGENTS.md` exists. Creates `CLAUDE.md` if neither exists.
|
|
37
|
+
* Idempotent.
|
|
38
|
+
*/
|
|
39
|
+
export declare function ensureCairnRuleImport(repoRoot: string): EnsureImportResult;
|
|
40
|
+
export interface InstallRuleResult extends EnsureImportResult {
|
|
41
|
+
/** True when the rule file was written/updated. */
|
|
42
|
+
ruleWritten: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Adoption-side: write `.claude/rules/cairn.md` from the bundled template
|
|
46
|
+
* (if missing or stale) and wire the `@`-import so plugin-less clones see
|
|
47
|
+
* the install notice. Best-effort — a missing template is logged and the
|
|
48
|
+
* import is still ensured.
|
|
49
|
+
*/
|
|
50
|
+
export declare function installCairnRuleAndImport(repoRoot: string): InstallRuleResult;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-absent onboarding wiring.
|
|
3
|
+
*
|
|
4
|
+
* The Cairn surface (SessionStart banner, MCP tools, scoped rule
|
|
5
|
+
* injection) is delivered by the Claude Code plugin, which is installed
|
|
6
|
+
* per-machine — cloning an adopted repo does NOT install it. The only
|
|
7
|
+
* repo-committed, plugin-independent fallback is
|
|
8
|
+
* `.claude/rules/cairn.md`, which tells a plugin-less agent to install
|
|
9
|
+
* the plugin.
|
|
10
|
+
*
|
|
11
|
+
* But Claude Code does not auto-load `.claude/rules/*.md` on its own —
|
|
12
|
+
* something has to import it. The one file Claude Code always loads with
|
|
13
|
+
* zero plugin is the root memory file (`CLAUDE.md`). So the fallback rule
|
|
14
|
+
* is only effective if that memory file `@`-imports it. Writing the rule
|
|
15
|
+
* without wiring the import (the prior behavior) left it orphaned: a
|
|
16
|
+
* teammate who cloned an adopted repo without the plugin saw nothing.
|
|
17
|
+
*
|
|
18
|
+
* `ensureCairnRuleImport` wires the import idempotently;
|
|
19
|
+
* `installCairnRuleAndImport` writes the rule template AND wires the
|
|
20
|
+
* import, for the adoption path.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
import { basename, dirname, join } from "node:path";
|
|
25
|
+
import { getLogger } from "@isaacriehm/cairn-state";
|
|
26
|
+
const log = getLogger();
|
|
27
|
+
/** The repo-root-relative @import line Claude Code resolves. */
|
|
28
|
+
export const CAIRN_RULE_IMPORT = "@.claude/rules/cairn.md";
|
|
29
|
+
const IMPORT_MARKER = "<!-- cairn: plugin-absent onboarding — loads the install notice for clones without the Cairn plugin -->";
|
|
30
|
+
/**
|
|
31
|
+
* Ensure the project's auto-loaded memory file `@`-imports
|
|
32
|
+
* `.claude/rules/cairn.md`. Targets `CLAUDE.md` (the file Claude Code
|
|
33
|
+
* always auto-loads); falls back to `AGENTS.md` only when `CLAUDE.md` is
|
|
34
|
+
* absent but `AGENTS.md` exists. Creates `CLAUDE.md` if neither exists.
|
|
35
|
+
* Idempotent.
|
|
36
|
+
*/
|
|
37
|
+
export function ensureCairnRuleImport(repoRoot) {
|
|
38
|
+
const claudeAbs = join(repoRoot, "CLAUDE.md");
|
|
39
|
+
const agentsAbs = join(repoRoot, "AGENTS.md");
|
|
40
|
+
let targetAbs = claudeAbs;
|
|
41
|
+
let rel = "CLAUDE.md";
|
|
42
|
+
if (!existsSync(claudeAbs) && existsSync(agentsAbs)) {
|
|
43
|
+
targetAbs = agentsAbs;
|
|
44
|
+
rel = "AGENTS.md";
|
|
45
|
+
}
|
|
46
|
+
const existed = existsSync(targetAbs);
|
|
47
|
+
const content = existed ? readFileSync(targetAbs, "utf8") : "";
|
|
48
|
+
if (content.includes(CAIRN_RULE_IMPORT)) {
|
|
49
|
+
return { changed: false, file: rel, created: false };
|
|
50
|
+
}
|
|
51
|
+
const importBlock = `${IMPORT_MARKER}\n${CAIRN_RULE_IMPORT}\n`;
|
|
52
|
+
const next = existed
|
|
53
|
+
? `${content.replace(/\s*$/, "")}\n\n${importBlock}`
|
|
54
|
+
: `# ${basename(repoRoot)}\n\n${importBlock}`;
|
|
55
|
+
writeFileSync(targetAbs, next, "utf8");
|
|
56
|
+
log.debug({ repoRoot, file: rel, created: !existed }, "wired cairn rule import");
|
|
57
|
+
return { changed: true, file: rel, created: !existed };
|
|
58
|
+
}
|
|
59
|
+
/* -------------------------------------------------------------------------- */
|
|
60
|
+
/* Template install (adoption path) */
|
|
61
|
+
/* -------------------------------------------------------------------------- */
|
|
62
|
+
const RULE_REL = join(".claude", "rules", "cairn.md");
|
|
63
|
+
/** Locate the bundled `.claude/rules/cairn.md` template. */
|
|
64
|
+
function findRuleTemplate() {
|
|
65
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
66
|
+
const candidates = [
|
|
67
|
+
// dist/init/ → cairn-core/templates
|
|
68
|
+
join(here, "..", "..", "templates", ".claude", "rules", "cairn.md"),
|
|
69
|
+
// src/init/ → cairn-core/templates (dev / ts-node)
|
|
70
|
+
join(here, "..", "..", "..", "templates", ".claude", "rules", "cairn.md"),
|
|
71
|
+
// plugin bundle mirror: here/templates
|
|
72
|
+
join(here, "templates", ".claude", "rules", "cairn.md"),
|
|
73
|
+
];
|
|
74
|
+
return candidates.find((p) => existsSync(p)) ?? null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Adoption-side: write `.claude/rules/cairn.md` from the bundled template
|
|
78
|
+
* (if missing or stale) and wire the `@`-import so plugin-less clones see
|
|
79
|
+
* the install notice. Best-effort — a missing template is logged and the
|
|
80
|
+
* import is still ensured.
|
|
81
|
+
*/
|
|
82
|
+
export function installCairnRuleAndImport(repoRoot) {
|
|
83
|
+
let ruleWritten = false;
|
|
84
|
+
const targetAbs = join(repoRoot, RULE_REL);
|
|
85
|
+
const template = findRuleTemplate();
|
|
86
|
+
if (template !== null) {
|
|
87
|
+
const desired = readFileSync(template, "utf8");
|
|
88
|
+
const current = existsSync(targetAbs) ? readFileSync(targetAbs, "utf8") : null;
|
|
89
|
+
if (current !== desired) {
|
|
90
|
+
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
91
|
+
writeFileSync(targetAbs, desired, "utf8");
|
|
92
|
+
ruleWritten = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
log.warn({ repoRoot }, "cairn rule template not found; wiring import only");
|
|
97
|
+
}
|
|
98
|
+
const imp = ensureCairnRuleImport(repoRoot);
|
|
99
|
+
return { ...imp, ruleWritten };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=claude-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-rule.js","sourceRoot":"","sources":["../../src/init/claude-rule.ts"],"names":[],"mappings":"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"}
|
package/dist/init/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { detectAll, detectAvailableSensors, detectEnvironment, detectHookCapability, detectOriginUrl, detectProjectSlug, detectStackSignatures, detectStartCommand, } from "./detect.js";
|
|
2
2
|
export { installInitCancelHandlers, startProgress, startSpinner, withSpinner, } from "./visual.js";
|
|
3
3
|
export { applyBrandAnswers, runBrandSetup } from "./brand-setup.js";
|
|
4
|
+
export { ensureCairnRuleImport, installCairnRuleAndImport, CAIRN_RULE_IMPORT, } from "./claude-rule.js";
|
|
5
|
+
export type { EnsureImportResult, InstallRuleResult } from "./claude-rule.js";
|
|
4
6
|
export type { BrandAnswers, RunBrandSetupOptions, } from "./brand-setup.js";
|
|
5
7
|
export { deriveBrandFromProject, derivedToBrandAnswers, } from "./brand-derive.js";
|
|
6
8
|
export { defaultBaselineLanguages, findLatestBaselineAudit, runBaselineAudit, } from "./baseline-audit.js";
|
package/dist/init/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { detectAll, detectAvailableSensors, detectEnvironment, detectHookCapability, detectOriginUrl, detectProjectSlug, detectStackSignatures, detectStartCommand, } from "./detect.js";
|
|
2
2
|
export { installInitCancelHandlers, startProgress, startSpinner, withSpinner, } from "./visual.js";
|
|
3
3
|
export { applyBrandAnswers, runBrandSetup } from "./brand-setup.js";
|
|
4
|
+
export { ensureCairnRuleImport, installCairnRuleAndImport, CAIRN_RULE_IMPORT, } from "./claude-rule.js";
|
|
4
5
|
export { deriveBrandFromProject, derivedToBrandAnswers, } from "./brand-derive.js";
|
|
5
6
|
export { defaultBaselineLanguages, findLatestBaselineAudit, runBaselineAudit, } from "./baseline-audit.js";
|
|
6
7
|
export { discoverDocs, runDocsIngestion, runStage1FileFilter, } from "./ingest-docs.js";
|
package/dist/init/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/init/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/init/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
|
+
import { installCairnRuleAndImport } from "../claude-rule.js";
|
|
18
19
|
const PREPARE_SCRIPT_FRAGMENT = "cairn join || true";
|
|
19
20
|
export function installMultiDev(args) {
|
|
20
21
|
const repoRoot = args.repoRoot;
|
|
@@ -56,6 +57,36 @@ export function installMultiDev(args) {
|
|
|
56
57
|
status: "ok",
|
|
57
58
|
detail: `detected ${hostKinds.join(", ")}`,
|
|
58
59
|
});
|
|
60
|
+
// Plugin-absent onboarding. Write `.claude/rules/cairn.md` and wire the
|
|
61
|
+
// `@`-import into the auto-loaded memory file (CLAUDE.md) so teammates
|
|
62
|
+
// who clone this repo WITHOUT the Cairn plugin still see the install
|
|
63
|
+
// notice on their first turn. Without the import the rule is orphaned —
|
|
64
|
+
// Claude Code does not auto-load `.claude/rules/*` on its own, so the
|
|
65
|
+
// fallback never fires (the failure that motivated this).
|
|
66
|
+
if (args.dryRun === true) {
|
|
67
|
+
steps.push({
|
|
68
|
+
step: "wire-cairn-rule-import",
|
|
69
|
+
status: "skipped",
|
|
70
|
+
detail: "dry-run",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
try {
|
|
75
|
+
const res = installCairnRuleAndImport(repoRoot);
|
|
76
|
+
steps.push({
|
|
77
|
+
step: "wire-cairn-rule-import",
|
|
78
|
+
status: "ok",
|
|
79
|
+
detail: `rule ${res.ruleWritten ? "written" : "current"}; import ${res.changed ? `added to ${res.file}` : "already present"}`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
steps.push({
|
|
84
|
+
step: "wire-cairn-rule-import",
|
|
85
|
+
status: "error",
|
|
86
|
+
detail: `failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
59
90
|
return { hostKinds, preparePatched: false, manualHints, steps };
|
|
60
91
|
}
|
|
61
92
|
export function patchPackageJsonPrepare(pkgPath, dryRun) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/init/multi-dev/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/init/multi-dev/install.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.15.
|
|
3
|
+
"version": "0.15.1",
|
|
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",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"simple-git": "^3.36.0",
|
|
40
40
|
"yaml": "^2.8.4",
|
|
41
41
|
"zod": "^4.4.3",
|
|
42
|
-
"@isaacriehm/cairn-state": "0.15.
|
|
42
|
+
"@isaacriehm/cairn-state": "0.15.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/cli-progress": "^3.11.6",
|
|
@@ -4,25 +4,31 @@ This project is adopted by [Cairn](https://github.com/isaacriehm/cairn).
|
|
|
4
4
|
The `.cairn/` directory carries decisions, invariants, brand, canonical-map,
|
|
5
5
|
and sensor configuration that govern code changes here.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## FIRST: check the plugin is installed
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
`cairn-direction` / `cairn-attention` skills
|
|
11
|
-
the plugin. Surface on the first reply:
|
|
9
|
+
Look for `mcp__plugin_cairn_cairn__cairn_*` MCP tools (or the
|
|
10
|
+
`cairn-direction` / `cairn-attention` skills).
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
**If they are absent, STOP. Do not edit code yet.** This project enforces
|
|
13
|
+
recorded decisions and invariants through the Cairn plugin; mutating
|
|
14
|
+
source without it skips attestation and silently drifts the codebase from
|
|
15
|
+
its ground state. Lead your first reply with exactly this:
|
|
16
|
+
|
|
17
|
+
> **This project uses Cairn, but the plugin isn't installed in your Claude
|
|
18
|
+
> Code.** Install it once per machine:
|
|
14
19
|
>
|
|
15
20
|
> ```
|
|
16
21
|
> /plugin marketplace add isaacriehm/cairn
|
|
17
22
|
> /plugin install cairn@isaacriehm-cairn
|
|
18
23
|
> ```
|
|
19
24
|
>
|
|
20
|
-
> Then `/exit` and reopen
|
|
25
|
+
> Then `/exit` and reopen — Cairn bootstraps automatically on the next
|
|
26
|
+
> session. (CLI-only contributors: `npm i -g @isaacriehm/cairn && cairn join`.)
|
|
27
|
+
|
|
28
|
+
Hold further code changes until the operator confirms the plugin is present.
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
mutations without Cairn skip attestation and bypass the
|
|
24
|
-
decisions/invariants the project enforces.
|
|
30
|
+
## When the plugin IS installed
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
Defer entirely to its SessionStart context block, `cairn-direction`, and
|
|
33
|
+
`cairn-attention` surfaces. This file is only the fallback for the
|
|
34
|
+
plugin-absent case.
|