@isaacriehm/cairn-core 0.26.0 → 0.31.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/dist/.tsbuildinfo +1 -1
- package/dist/gc/config-drift.d.ts +60 -0
- package/dist/gc/config-drift.js +262 -0
- package/dist/gc/config-drift.js.map +1 -0
- package/dist/gc/index.d.ts +2 -0
- package/dist/gc/index.js +1 -0
- package/dist/gc/index.js.map +1 -1
- package/dist/gc/sweep.js +11 -0
- package/dist/gc/sweep.js.map +1 -1
- package/dist/gc/types.d.ts +2 -2
- package/dist/hooks/post-tool-use/sot-align.d.ts +4 -0
- package/dist/hooks/post-tool-use/sot-align.js +26 -3
- package/dist/hooks/post-tool-use/sot-align.js.map +1 -1
- package/dist/hooks/sot-align-common.d.ts +10 -0
- package/dist/hooks/sot-align-common.js +32 -0
- package/dist/hooks/sot-align-common.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/brand-setup.js +8 -3
- package/dist/init/brand-setup.js.map +1 -1
- package/dist/init/curator/emit.d.ts +10 -0
- package/dist/init/curator/emit.js +29 -17
- package/dist/init/curator/emit.js.map +1 -1
- package/dist/init/curator/index.d.ts +2 -0
- package/dist/init/curator/index.js +2 -0
- package/dist/init/curator/index.js.map +1 -1
- package/dist/init/curator/walker.d.ts +7 -0
- package/dist/init/curator/walker.js +17 -4
- package/dist/init/curator/walker.js.map +1 -1
- package/dist/init/index.d.ts +1 -1
- package/dist/init/index.js +1 -1
- package/dist/init/index.js.map +1 -1
- package/dist/init/phases/4-seed.js +7 -2
- package/dist/init/phases/4-seed.js.map +1 -1
- package/dist/init/seed.d.ts +7 -0
- package/dist/init/seed.js +24 -16
- package/dist/init/seed.js.map +1 -1
- package/dist/init/topic-index/index.d.ts +8 -0
- package/dist/init/topic-index/index.js +17 -8
- package/dist/init/topic-index/index.js.map +1 -1
- package/dist/invariants/prune.d.ts +6 -4
- package/dist/invariants/prune.js +40 -7
- package/dist/invariants/prune.js.map +1 -1
- package/dist/mcp/schemas.d.ts +26 -0
- package/dist/mcp/schemas.js +23 -0
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/tools/in-scope.js +7 -1
- package/dist/mcp/tools/in-scope.js.map +1 -1
- package/dist/mcp/tools/index.js +3 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/invariant-get.js +37 -28
- package/dist/mcp/tools/invariant-get.js.map +1 -1
- package/dist/mcp/tools/resolve-attention.d.ts +1 -1
- package/dist/mcp/tools/resolve-attention.js +92 -0
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/mcp/tools/resync.d.ts +19 -0
- package/dist/mcp/tools/resync.js +109 -0
- package/dist/mcp/tools/resync.js.map +1 -0
- package/dist/migrate/migrations/0005-demote-autofilled-brand.d.ts +11 -3
- package/dist/migrate/migrations/0005-demote-autofilled-brand.js +67 -21
- package/dist/migrate/migrations/0005-demote-autofilled-brand.js.map +1 -1
- package/dist/migrate/migrations/0006-prune-sot-align-invariants.d.ts +17 -15
- package/dist/migrate/migrations/0006-prune-sot-align-invariants.js +23 -17
- package/dist/migrate/migrations/0006-prune-sot-align-invariants.js.map +1 -1
- package/dist/migrate/migrations/0008-clean-adoption-scaffolding.d.ts +39 -0
- package/dist/migrate/migrations/0008-clean-adoption-scaffolding.js +206 -0
- package/dist/migrate/migrations/0008-clean-adoption-scaffolding.js.map +1 -0
- package/dist/migrate/registry.js +2 -0
- package/dist/migrate/registry.js.map +1 -1
- package/dist/resync/archive.d.ts +12 -0
- package/dist/resync/archive.js +29 -0
- package/dist/resync/archive.js.map +1 -0
- package/dist/resync/index.d.ts +73 -0
- package/dist/resync/index.js +389 -0
- package/dist/resync/index.js.map +1 -0
- package/dist/resync/recluster.d.ts +59 -0
- package/dist/resync/recluster.js +66 -0
- package/dist/resync/recluster.js.map +1 -0
- package/dist/session-start/build.js +47 -30
- package/dist/session-start/build.js.map +1 -1
- package/dist/session-start/templates.js +4 -4
- package/dist/session-start/templates.js.map +1 -1
- package/package.json +2 -2
- package/templates/.cairn/config/sensors.yaml +1 -1
- package/templates/.cairn/config/workflow.md +5 -12
- package/templates/.cairn/git-hooks/commit-msg +0 -2
- package/templates/.cairn/git-hooks/post-commit +0 -2
- package/templates/.cairn/ground/brand/overview.md +2 -2
- package/templates/.cairn/ground/brand/voice.md +2 -2
- package/templates/.cairn/ground/product/positioning.md +2 -2
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0008 — clean leaked adoption scaffolding from a project's committed `.cairn/`.
|
|
3
|
+
*
|
|
4
|
+
* The shipped templates leaked Cairn-internal strings into every adopter's
|
|
5
|
+
* committed files that the seed never scrubbed:
|
|
6
|
+
* - workflow.md : a "Project-extension placeholder" meta-comment describing
|
|
7
|
+
* the template's OWN substitution (false the moment init
|
|
8
|
+
* ran) + a dangling `docs/SYSTEM_OVERVIEW.md` pointer (a
|
|
9
|
+
* Cairn-internal doc that never ships to adopters).
|
|
10
|
+
* - sensors.yaml : the "honest-agent invariants stack" framing — internal
|
|
11
|
+
* jargon that means nothing in an adopter's repo.
|
|
12
|
+
* - .gitignore : `PLUGIN_ARCHITECTURE §7/§17`, `docs/FILESYSTEM_LAYOUT.md`,
|
|
13
|
+
* `spec §2.2` — references to Cairn-internal docs that
|
|
14
|
+
* dangle in the adopter's tree.
|
|
15
|
+
* - git-hooks : `Spec: PLUGIN_ARCHITECTURE §17 Layer 1` refs in the
|
|
16
|
+
* commit-msg + post-commit hooks.
|
|
17
|
+
* - personas.yaml: a `DOCS_SPEC.md §3.4` shape ref written by an older
|
|
18
|
+
* brand-setup path (the template itself is clean).
|
|
19
|
+
*
|
|
20
|
+
* Plus synthetic, template-author timestamps in workflow.md + the brand /
|
|
21
|
+
* product files (`2026-05-02T…`, `2026-05-04T…`). A fake `verified-at` is one
|
|
22
|
+
* the freshness system can't trust, so we replace each synthetic stamp with
|
|
23
|
+
* the file's real git first-commit author-date — the true adoption time,
|
|
24
|
+
* identical on every clone. If git can't resolve it (untracked / ghost) the
|
|
25
|
+
* stamp is LEFT rather than fabricated (no clock value → no per-clone churn).
|
|
26
|
+
*
|
|
27
|
+
* The templates now ship clean; this converges existing repos to them.
|
|
28
|
+
*
|
|
29
|
+
* `safe` (not `review`): deterministic, zero-semantic cosmetic edits. The
|
|
30
|
+
* comment scrubs carry none of the matched anchor text (idempotent), and the
|
|
31
|
+
* timestamp swap is content-derived — whoever runs it first commits the
|
|
32
|
+
* canonical clean file and every other clone's `detect()` short-circuits, so
|
|
33
|
+
* there is no churn. Auto-applies on session open (cf. 0001/0004).
|
|
34
|
+
*
|
|
35
|
+
* Ships in 0.27.0 → `introducedIn` 0.27.0; every prior adopter re-evaluates on
|
|
36
|
+
* upgrade. `detect()` carries correctness.
|
|
37
|
+
*/
|
|
38
|
+
import { execFileSync } from "node:child_process";
|
|
39
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
40
|
+
import { cairnDir } from "@isaacriehm/cairn-state";
|
|
41
|
+
/** The leaked workflow.md block: a rule line, the placeholder meta-comment, a rule line. */
|
|
42
|
+
const LEAKED_BLOCK = /#[ ]*─{10,}\n# Project-extension placeholder\.[\s\S]*?#[ ]*─{10,}\n/;
|
|
43
|
+
/** Dangling pointer at a Cairn-internal doc that never ships to adopters. */
|
|
44
|
+
const DANGLING_DOC_REF = /\n+If you're looking for the daily flow, see `docs\/SYSTEM_OVERVIEW\.md` §4\.\n/;
|
|
45
|
+
/** Clean operator-facing workflow.md replacement — matches the shipped template. */
|
|
46
|
+
const CLEAN_BLOCK = [
|
|
47
|
+
"# ──────────────────────────────────────────────────────────────────────────────",
|
|
48
|
+
"# Project workflow extension — keyed by this project's slug. Carries the",
|
|
49
|
+
"# `off_limits` denylist (paths Cairn must never touch) and the trust posture.",
|
|
50
|
+
"# Seeded at adoption; extend `off_limits` with your own paths.",
|
|
51
|
+
"# ──────────────────────────────────────────────────────────────────────────────",
|
|
52
|
+
"",
|
|
53
|
+
].join("\n");
|
|
54
|
+
/** Exact synthetic literals the templates used to ship — only these are swapped. */
|
|
55
|
+
const SYNTHETIC_STAMPS = ["2026-05-02T13:19:00Z", "2026-05-04T00:00:00Z"];
|
|
56
|
+
const FILES = [
|
|
57
|
+
{
|
|
58
|
+
rel: ["config", "workflow.md"],
|
|
59
|
+
scrubs: [
|
|
60
|
+
{ re: LEAKED_BLOCK, with: CLEAN_BLOCK, label: "placeholder meta-comment" },
|
|
61
|
+
{ re: DANGLING_DOC_REF, with: "\n", label: "dangling docs/ pointer" },
|
|
62
|
+
],
|
|
63
|
+
fixTimestamps: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
rel: ["config", "sensors.yaml"],
|
|
67
|
+
scrubs: [
|
|
68
|
+
{
|
|
69
|
+
re: / Layer A of the honest-agent invariants stack\./,
|
|
70
|
+
with: "",
|
|
71
|
+
label: "internal jargon (sensors.yaml)",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
rel: [".gitignore"],
|
|
77
|
+
scrubs: [
|
|
78
|
+
{ re: / Marked\n# GITIGNORED in docs\/FILESYSTEM_LAYOUT\.md\./, with: "", label: "FILESYSTEM_LAYOUT ref" },
|
|
79
|
+
{ re: / Spec: PLUGIN_ARCHITECTURE §7\./, with: "", label: "PLUGIN_ARCHITECTURE §7 ref" },
|
|
80
|
+
{ re: / \(per PLUGIN_ARCHITECTURE §7\)/, with: "", label: "PLUGIN_ARCHITECTURE §7 paren ref" },
|
|
81
|
+
{ re: / Per PLUGIN_ARCHITECTURE §17 Layer 1\./, with: "", label: "PLUGIN_ARCHITECTURE §17 ref" },
|
|
82
|
+
{ re: / in spec §2\.2/, with: "", label: "spec §2.2 ref" },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
rel: ["git-hooks", "commit-msg"],
|
|
87
|
+
scrubs: [
|
|
88
|
+
{ re: /# Spec: PLUGIN_ARCHITECTURE §17 Layer 1\.\n#\n/, with: "", label: "commit-msg spec ref" },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
rel: ["git-hooks", "post-commit"],
|
|
93
|
+
scrubs: [
|
|
94
|
+
{
|
|
95
|
+
re: /# Spec: PLUGIN_ARCHITECTURE §17 Layer 1 \(bypass tracking\)\.\n#\n/,
|
|
96
|
+
with: "",
|
|
97
|
+
label: "post-commit spec ref",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
rel: ["ground", "product", "personas.yaml"],
|
|
103
|
+
scrubs: [
|
|
104
|
+
{ re: /\n# See DOCS_SPEC\.md §3\.4 for shape\./, with: "", label: "personas DOCS_SPEC ref" },
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{ rel: ["ground", "brand", "overview.md"], fixTimestamps: true },
|
|
108
|
+
{ rel: ["ground", "brand", "voice.md"], fixTimestamps: true },
|
|
109
|
+
{ rel: ["ground", "product", "positioning.md"], fixTimestamps: true },
|
|
110
|
+
];
|
|
111
|
+
function readMaybe(abs) {
|
|
112
|
+
if (!existsSync(abs))
|
|
113
|
+
return null;
|
|
114
|
+
try {
|
|
115
|
+
return readFileSync(abs, "utf8");
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function hasSyntheticStamp(text) {
|
|
122
|
+
return SYNTHETIC_STAMPS.some((s) => text.includes(s));
|
|
123
|
+
}
|
|
124
|
+
/** Does this file still need any scrub or timestamp fix? */
|
|
125
|
+
function fileNeeds(spec, raw) {
|
|
126
|
+
if (spec.scrubs?.some((s) => s.re.test(raw)))
|
|
127
|
+
return true;
|
|
128
|
+
if (spec.fixTimestamps === true && hasSyntheticStamp(raw))
|
|
129
|
+
return true;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The author-date of the commit that first ADDED `repoRelPath` — the real
|
|
134
|
+
* adoption time, stable across clones (author date, not committer date).
|
|
135
|
+
* Null when git is unavailable or the file is untracked (e.g. ghost mode).
|
|
136
|
+
*/
|
|
137
|
+
function gitAddDateIso(repoRoot, repoRelPath) {
|
|
138
|
+
try {
|
|
139
|
+
const out = execFileSync("git", ["log", "--diff-filter=A", "--follow", "--format=%aI", "-1", "--", repoRelPath], { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
140
|
+
const first = out.split("\n")[0]?.trim() ?? "";
|
|
141
|
+
return first.length > 0 ? first : null;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export const cleanAdoptionScaffolding = {
|
|
148
|
+
id: "0008-clean-adoption-scaffolding",
|
|
149
|
+
introducedIn: "0.27.0",
|
|
150
|
+
describe: "Scrub leaked template scaffolding from a project's committed .cairn/ — internal-doc refs (PLUGIN_ARCHITECTURE/FILESYSTEM_LAYOUT/DOCS_SPEC/SYSTEM_OVERVIEW), the false-after-adoption 'Project-extension placeholder' comment, the 'honest-agent invariants stack' jargon — and replace synthetic template-author timestamps with each file's real git add-date so verified-at is trustworthy",
|
|
151
|
+
class: "safe",
|
|
152
|
+
detect(repoRoot) {
|
|
153
|
+
for (const spec of FILES) {
|
|
154
|
+
const raw = readMaybe(cairnDir(repoRoot, ...spec.rel));
|
|
155
|
+
if (raw !== null && fileNeeds(spec, raw))
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
},
|
|
160
|
+
apply(repoRoot) {
|
|
161
|
+
const cleaned = [];
|
|
162
|
+
for (const spec of FILES) {
|
|
163
|
+
const abs = cairnDir(repoRoot, ...spec.rel);
|
|
164
|
+
const raw = readMaybe(abs);
|
|
165
|
+
if (raw === null)
|
|
166
|
+
continue;
|
|
167
|
+
let next = raw;
|
|
168
|
+
for (const scrub of spec.scrubs ?? []) {
|
|
169
|
+
if (scrub.re.test(next)) {
|
|
170
|
+
next = next.replace(scrub.re, scrub.with);
|
|
171
|
+
cleaned.push(scrub.label);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (spec.fixTimestamps === true && hasSyntheticStamp(next)) {
|
|
175
|
+
// The git add-date is the real adoption time. In committed mode the
|
|
176
|
+
// file is tracked at `.cairn/<rel>`; in ghost mode it lives out-of-repo
|
|
177
|
+
// and is untracked, so this lookup naturally returns null → stamp left.
|
|
178
|
+
const repoRel = [".cairn", ...spec.rel].join("/");
|
|
179
|
+
const addDate = gitAddDateIso(repoRoot, repoRel);
|
|
180
|
+
if (addDate !== null) {
|
|
181
|
+
for (const synth of SYNTHETIC_STAMPS) {
|
|
182
|
+
next = next.split(synth).join(addDate);
|
|
183
|
+
}
|
|
184
|
+
cleaned.push(`${spec.rel[spec.rel.length - 1]} timestamp`);
|
|
185
|
+
}
|
|
186
|
+
// git unresolved → leave the stamp; never fabricate a clock value.
|
|
187
|
+
}
|
|
188
|
+
if (next !== raw) {
|
|
189
|
+
try {
|
|
190
|
+
writeFileSync(abs, next, "utf8");
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
return {
|
|
194
|
+
changed: false,
|
|
195
|
+
detail: `failed to rewrite ${spec.rel.join("/")}: ${err instanceof Error ? err.message : String(err)}`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (cleaned.length === 0) {
|
|
201
|
+
return { changed: false, detail: "no leaked adoption scaffolding found" };
|
|
202
|
+
}
|
|
203
|
+
return { changed: true, detail: `cleaned: ${cleaned.join(" + ")}` };
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=0008-clean-adoption-scaffolding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0008-clean-adoption-scaffolding.js","sourceRoot":"","sources":["../../../src/migrate/migrations/0008-clean-adoption-scaffolding.ts"],"names":[],"mappings":"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"}
|
package/dist/migrate/registry.js
CHANGED
|
@@ -12,6 +12,7 @@ import { dropGlobSettings } from "./migrations/0004-drop-glob-settings.js";
|
|
|
12
12
|
import { demoteAutofilledBrand } from "./migrations/0005-demote-autofilled-brand.js";
|
|
13
13
|
import { pruneSotAlignInvariants } from "./migrations/0006-prune-sot-align-invariants.js";
|
|
14
14
|
import { collapseComponentDirs } from "./migrations/0007-collapse-component-dirs.js";
|
|
15
|
+
import { cleanAdoptionScaffolding } from "./migrations/0008-clean-adoption-scaffolding.js";
|
|
15
16
|
export const MIGRATIONS = [
|
|
16
17
|
dropDeadConfigFields,
|
|
17
18
|
backfillGitignore,
|
|
@@ -20,5 +21,6 @@ export const MIGRATIONS = [
|
|
|
20
21
|
demoteAutofilledBrand,
|
|
21
22
|
pruneSotAlignInvariants,
|
|
22
23
|
collapseComponentDirs,
|
|
24
|
+
cleanAdoptionScaffolding,
|
|
23
25
|
];
|
|
24
26
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/migrate/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/migrate/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iDAAiD,CAAC;AAE3F,MAAM,CAAC,MAAM,UAAU,GAAyB;IAC9C,oBAAoB;IACpB,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,qBAAqB;IACrB,uBAAuB;IACvB,qBAAqB;IACrB,wBAAwB;CACzB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pre-resync archive helper. Every resync mutation (config edits,
|
|
3
|
+
* source-rematch frontmatter rewrites, topic-index re-cluster) snapshots the
|
|
4
|
+
* file it is about to overwrite into `.cairn/ground/.archive/` first, so the
|
|
5
|
+
* operator can recover the prior state (Q23). Recoverable, never hard-deleted.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Copy a repo file to `.cairn/ground/.archive/<base>.pre-resync.<ts>.bak`.
|
|
9
|
+
* Returns the repo-relative path of the backup, or null when the source is
|
|
10
|
+
* absent (fresh repo — nothing to back up) or the copy fails.
|
|
11
|
+
*/
|
|
12
|
+
export declare function archiveFile(srcAbs: string, repoRoot: string, base: string, nowIso: string): string | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pre-resync archive helper. Every resync mutation (config edits,
|
|
3
|
+
* source-rematch frontmatter rewrites, topic-index re-cluster) snapshots the
|
|
4
|
+
* file it is about to overwrite into `.cairn/ground/.archive/` first, so the
|
|
5
|
+
* operator can recover the prior state (Q23). Recoverable, never hard-deleted.
|
|
6
|
+
*/
|
|
7
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { archiveDir } from "@isaacriehm/cairn-state";
|
|
10
|
+
/**
|
|
11
|
+
* Copy a repo file to `.cairn/ground/.archive/<base>.pre-resync.<ts>.bak`.
|
|
12
|
+
* Returns the repo-relative path of the backup, or null when the source is
|
|
13
|
+
* absent (fresh repo — nothing to back up) or the copy fails.
|
|
14
|
+
*/
|
|
15
|
+
export function archiveFile(srcAbs, repoRoot, base, nowIso) {
|
|
16
|
+
if (!existsSync(srcAbs))
|
|
17
|
+
return null;
|
|
18
|
+
const dir = archiveDir(repoRoot);
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
const name = `${base}.pre-resync.${nowIso.replace(/[:.]/g, "-")}.bak`;
|
|
21
|
+
try {
|
|
22
|
+
copyFileSync(srcAbs, join(dir, name));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return join(".cairn", "ground", ".archive", name);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/resync/archive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,QAAgB,EAChB,IAAY,EACZ,MAAc;IAEd,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,IAAI,eAAe,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC;IACtE,IAAI,CAAC;QACH,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cairn resync` — operator-initiated incremental re-discovery (Stage 3).
|
|
3
|
+
*
|
|
4
|
+
* Stage 1's config-drift sensor SURFACES the gap between declared config and
|
|
5
|
+
* the grown tree; resync is the operator-initiated verb that RESOLVES it. This
|
|
6
|
+
* v1 closes the deterministic half of the loop: it re-runs the config-drift
|
|
7
|
+
* detector and turns each finding into a concrete `config.yaml` edit —
|
|
8
|
+
*
|
|
9
|
+
* - `config_uncovered_dir` → add the dir to the owning workspace's
|
|
10
|
+
* `componentDirs`
|
|
11
|
+
* - `config_uncovered_ext` → add the file type to that workspace's
|
|
12
|
+
* `extensions`
|
|
13
|
+
* - `config_gitignore_drift` → add the ignored path to top-level
|
|
14
|
+
* `off_limits`
|
|
15
|
+
* - `config_orphan_path` → drop the dead `componentDir`
|
|
16
|
+
*
|
|
17
|
+
* Safety (Q23): `--dry-run` (the default) mutates nothing — it returns the
|
|
18
|
+
* proposed edits for the operator to review. Apply archives the pre-resync
|
|
19
|
+
* `config.yaml` to `.cairn/ground/.archive/` first, edits via the comment-
|
|
20
|
+
* preserving yaml Document API, and is idempotent on a clean delta (re-run
|
|
21
|
+
* after apply proposes nothing). The edit is a `review`-class mutation of
|
|
22
|
+
* committed config the operator commits; derived state stays gitignored +
|
|
23
|
+
* per-clone, so there is no new multi-dev conflict surface (Q22).
|
|
24
|
+
*
|
|
25
|
+
* Deferred to the LLM half (Q3/Q16, opt-in, quota-gated): hash-rematch of moved
|
|
26
|
+
* entities, Haiku re-cluster of topic-index/canonical-map over genuinely-new
|
|
27
|
+
* prose, and re-curation of new areas into DEC/INV drafts. `domain_summary`
|
|
28
|
+
* (Q15) is an init-time seed for the brand bodies, not live agent context, so
|
|
29
|
+
* resync does not refresh it.
|
|
30
|
+
*/
|
|
31
|
+
export { runResyncRecluster, type ResyncReclusterOptions, type ResyncReclusterResult, } from "./recluster.js";
|
|
32
|
+
export type { ProseBlock, SemanticJudge, SemanticVerdict } from "../init/topic-index/resolve.js";
|
|
33
|
+
export type ResyncProposalKind = "add_component_dir" | "add_extension" | "add_off_limits" | "drop_component_dir" | "repoint_source";
|
|
34
|
+
export interface ResyncProposal {
|
|
35
|
+
kind: ResyncProposalKind;
|
|
36
|
+
/** Target workspace ("" = single-app). Absent for off_limits / repoint. */
|
|
37
|
+
workspace?: string;
|
|
38
|
+
/** The dir / extension / glob added or dropped, or the new source_file. */
|
|
39
|
+
value: string;
|
|
40
|
+
/** Originating config-drift finding kind (or "stale_source" for rematch). */
|
|
41
|
+
from: string;
|
|
42
|
+
/** Human-readable one-liner. */
|
|
43
|
+
detail: string;
|
|
44
|
+
/** repoint_source — the entity being re-pointed. */
|
|
45
|
+
entityId?: string;
|
|
46
|
+
/** repoint_source — repo-relative path of the entity `.md`. */
|
|
47
|
+
entityPath?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ResyncResult {
|
|
50
|
+
dryRun: boolean;
|
|
51
|
+
proposals: ResyncProposal[];
|
|
52
|
+
applied: boolean;
|
|
53
|
+
/** Repo-relative path of the pre-resync config backup, or null. */
|
|
54
|
+
archivedConfig: string | null;
|
|
55
|
+
/** Repo-relative paths of pre-resync entity backups (source rematch). */
|
|
56
|
+
archivedEntities: string[];
|
|
57
|
+
/** Findings that produced no actionable proposal, with why. */
|
|
58
|
+
skipped: {
|
|
59
|
+
finding: string;
|
|
60
|
+
path: string;
|
|
61
|
+
reason: string;
|
|
62
|
+
}[];
|
|
63
|
+
}
|
|
64
|
+
export interface RunResyncOptions {
|
|
65
|
+
repoRoot: string;
|
|
66
|
+
/** Preview only — mutate nothing. Default true (safe). */
|
|
67
|
+
dryRun?: boolean;
|
|
68
|
+
/** Limit to findings whose path is at/under this repo-relative dir. */
|
|
69
|
+
area?: string;
|
|
70
|
+
/** Injected ISO for the archive filename (determinism in tests). */
|
|
71
|
+
nowIso?: string;
|
|
72
|
+
}
|
|
73
|
+
export declare function runResync(opts: RunResyncOptions): ResyncResult;
|