@dzhechkov/harness-core 0.7.12 → 0.8.2

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 (105) hide show
  1. package/.dz-manifest.json +210 -70
  2. package/README.md +34 -1
  3. package/dist/book-kb.d.ts.map +1 -1
  4. package/dist/book-kb.js +17 -0
  5. package/dist/book-kb.js.map +1 -1
  6. package/dist/feature-adr-checkpoints.d.ts +61 -0
  7. package/dist/feature-adr-checkpoints.d.ts.map +1 -1
  8. package/dist/feature-adr-checkpoints.js +116 -2
  9. package/dist/feature-adr-checkpoints.js.map +1 -1
  10. package/dist/index.d.ts +16 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +13 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/loop-blobs.generated.js +2 -2
  15. package/dist/loop-blobs.generated.js.map +1 -1
  16. package/dist/mutation-gate.d.ts +31 -8
  17. package/dist/mutation-gate.d.ts.map +1 -1
  18. package/dist/mutation-gate.js +57 -16
  19. package/dist/mutation-gate.js.map +1 -1
  20. package/dist/named-lock.d.ts.map +1 -1
  21. package/dist/named-lock.js +11 -9
  22. package/dist/named-lock.js.map +1 -1
  23. package/dist/native-dep-probe.d.ts +11 -0
  24. package/dist/native-dep-probe.d.ts.map +1 -0
  25. package/dist/native-dep-probe.js +100 -0
  26. package/dist/native-dep-probe.js.map +1 -0
  27. package/dist/operations.d.ts.map +1 -1
  28. package/dist/operations.js +82 -1
  29. package/dist/operations.js.map +1 -1
  30. package/dist/parser-safe-region.d.ts +47 -0
  31. package/dist/parser-safe-region.d.ts.map +1 -0
  32. package/dist/parser-safe-region.js +47 -0
  33. package/dist/parser-safe-region.js.map +1 -0
  34. package/dist/patterns.d.ts.map +1 -1
  35. package/dist/patterns.js +10 -1
  36. package/dist/patterns.js.map +1 -1
  37. package/dist/profile.d.ts +202 -0
  38. package/dist/profile.d.ts.map +1 -0
  39. package/dist/profile.js +536 -0
  40. package/dist/profile.js.map +1 -0
  41. package/dist/publish.d.ts +5 -3
  42. package/dist/publish.d.ts.map +1 -1
  43. package/dist/publish.js +46 -8
  44. package/dist/publish.js.map +1 -1
  45. package/dist/qe-rounds.d.ts +75 -0
  46. package/dist/qe-rounds.d.ts.map +1 -0
  47. package/dist/qe-rounds.js +174 -0
  48. package/dist/qe-rounds.js.map +1 -0
  49. package/dist/registry.d.ts.map +1 -1
  50. package/dist/registry.js +5 -1
  51. package/dist/registry.js.map +1 -1
  52. package/dist/run-records.d.ts.map +1 -1
  53. package/dist/run-records.js +8 -1
  54. package/dist/run-records.js.map +1 -1
  55. package/dist/setup.d.ts +35 -4
  56. package/dist/setup.d.ts.map +1 -1
  57. package/dist/setup.js +86 -23
  58. package/dist/setup.js.map +1 -1
  59. package/dist/sign.d.ts +29 -24
  60. package/dist/sign.d.ts.map +1 -1
  61. package/dist/sign.js +183 -61
  62. package/dist/sign.js.map +1 -1
  63. package/dist/store-location.d.ts +56 -0
  64. package/dist/store-location.d.ts.map +1 -0
  65. package/dist/store-location.js +56 -0
  66. package/dist/store-location.js.map +1 -0
  67. package/dist/store-lock.d.ts +1 -0
  68. package/dist/store-lock.d.ts.map +1 -1
  69. package/dist/store-lock.js +7 -1
  70. package/dist/store-lock.js.map +1 -1
  71. package/dist/store-merge.d.ts +55 -0
  72. package/dist/store-merge.d.ts.map +1 -0
  73. package/dist/store-merge.js +77 -0
  74. package/dist/store-merge.js.map +1 -0
  75. package/dist/teach-target.d.ts +61 -0
  76. package/dist/teach-target.d.ts.map +1 -0
  77. package/dist/teach-target.js +105 -0
  78. package/dist/teach-target.js.map +1 -0
  79. package/dist/vector-tier.d.ts.map +1 -1
  80. package/dist/vector-tier.js +63 -20
  81. package/dist/vector-tier.js.map +1 -1
  82. package/package.json +13 -13
  83. package/sbom.json +424 -70
  84. package/src/book-kb.ts +17 -0
  85. package/src/feature-adr-checkpoints.ts +111 -2
  86. package/src/index.ts +39 -1
  87. package/src/loop-blobs.generated.ts +2 -2
  88. package/src/mutation-gate.ts +74 -17
  89. package/src/named-lock.ts +10 -8
  90. package/src/native-dep-probe.ts +118 -0
  91. package/src/operations.ts +77 -1
  92. package/src/parser-safe-region.ts +65 -0
  93. package/src/patterns.ts +10 -1
  94. package/src/profile.ts +593 -0
  95. package/src/publish.ts +43 -7
  96. package/src/qe-rounds.ts +226 -0
  97. package/src/registry.ts +5 -1
  98. package/src/run-records.ts +9 -1
  99. package/src/setup.ts +87 -23
  100. package/src/sign.ts +180 -60
  101. package/src/store-location.ts +76 -0
  102. package/src/store-lock.ts +8 -1
  103. package/src/store-merge.ts +91 -0
  104. package/src/teach-target.ts +126 -0
  105. package/src/vector-tier.ts +58 -9
@@ -0,0 +1,536 @@
1
+ /**
2
+ * Operator profile (feature operator-profile, ADR-001) — WHO the assistant is talking to,
3
+ * stored per USER and delivered as a marked block in `~/.claude/CLAUDE.md`.
4
+ *
5
+ * The profile is a FILE the runtime loads, not a rule the agent remembers: a rule in agent
6
+ * memory is layer 4 of the cost-of-detection ladder and failed three times in this repo before
7
+ * this feature existed. The block lives at layer 2 — loaded once per session, in EVERY project
8
+ * on the machine, including projects with no `.dz/` at all.
9
+ *
10
+ * Two axes (ADR Decision 2): a global register plus named domains that move it. `deepDomains`
11
+ * upgrade to full pro; `weakDomains` make a plain sentence MANDATORY, not merely default — the
12
+ * weak list is the load-bearing one, because there NOT explaining is the failure mode.
13
+ *
14
+ * Boundaries baked into every rendered block (ADR Decision 3), at every register:
15
+ * - the register governs dialogue and owner-facing surfaces only — never ADRs, commit messages,
16
+ * code comments, QE reports or npm READMEs;
17
+ * - the register changes FORM, never FACTS — numbers, caveats, risks and refutations survive
18
+ * every level. Without that sentence "simpler please" is a hole in the Integrity Rule.
19
+ *
20
+ * The store is per-user under `homedir()` — NEVER under a project root (`.dz/config.json` is
21
+ * committed in this very repo; a personal file there leaks by construction) — and mode 0600
22
+ * (the key-custody lesson of 2026-07-15 was a 0644 world-readable key).
23
+ *
24
+ * Nothing in this module throws on bad input: a missing file, unreadable JSON or a wrong shape
25
+ * is an honest verdict (`problem`), never an exception.
26
+ *
27
+ * @packageDocumentation
28
+ */
29
+ import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
30
+ import { homedir } from 'node:os';
31
+ import { dirname, join } from 'node:path';
32
+ /** Marker pair delimiting the profile block inside `~/.claude/CLAUDE.md`. The redaction in
33
+ * feature-adr-checkpoints.ts keeps its OWN copies of these literals (that file stays import-free
34
+ * so the workflow can mirror it inline); `test/profile-redaction.test.ts` pins the two pairs equal. */
35
+ export const PROFILE_MARKER_START = '<!-- dz:profile:start -->';
36
+ export const PROFILE_MARKER_END = '<!-- dz:profile:end -->';
37
+ /** The accepted register values, for refusal messages (teach-target precedent: an unknown value
38
+ * is refused NAMING the accepted set, never silently defaulted). */
39
+ export const REGISTERS = ['pro', 'pro-lite', 'plain'];
40
+ /** Owner-word aliases for each register (the owner answers «профи», the store keeps 'pro').
41
+ * Matching is case-insensitive and treats '-', '_' and spaces as one separator. */
42
+ const REGISTER_ALIASES = {
43
+ 'pro': 'pro',
44
+ 'профи': 'pro',
45
+ 'expert': 'pro',
46
+ 'pro lite': 'pro-lite',
47
+ 'prolite': 'pro-lite',
48
+ 'профи лайт': 'pro-lite',
49
+ 'plain': 'plain',
50
+ 'просто': 'plain',
51
+ 'simple': 'plain',
52
+ };
53
+ /** The owner-facing echo of a stored register — `show`/`set` print both directions. */
54
+ export function registerOwnerWord(register) {
55
+ switch (register) {
56
+ case 'pro': return 'профи';
57
+ case 'pro-lite': return 'профи лайт';
58
+ case 'plain': return 'просто';
59
+ }
60
+ }
61
+ /** Parse a register from the owner's own words. Returns null for anything not in the accepted
62
+ * set — the CALLER refuses, naming {@link REGISTERS}; this function never throws and never
63
+ * silently defaults. */
64
+ export function parseRegister(raw) {
65
+ if (typeof raw !== 'string')
66
+ return null;
67
+ const key = raw.trim().toLowerCase().replace(/[-_\s]+/g, ' ');
68
+ const direct = REGISTER_ALIASES[key];
69
+ if (direct !== undefined)
70
+ return direct;
71
+ // canonical spellings with the separator collapsed ('pro-lite' → 'pro lite' handled above)
72
+ return null;
73
+ }
74
+ /**
75
+ * Parse a human-typed, comma-separated domain list — the `init` onboarding answer
76
+ * («networking (CCIE; NSX), cloud architecture»). Rules, each from a way people actually type:
77
+ * - split on commas OUTSIDE parentheses ("networking (CCIE, NSX)" is ONE domain, not two);
78
+ * - an optional trailing parenthetical is the note: `networking (CCIE; NSX)` → tag `networking`,
79
+ * note `CCIE; NSX`;
80
+ * - the tag is kebab-cased (lowercased, whitespace runs → `-`) so `Cloud Architecture` and
81
+ * `cloud architecture` are the same domain;
82
+ * - an empty/blank answer means NONE — an empty array, never an error (onboarding must not force
83
+ * an answer).
84
+ * Never throws.
85
+ */
86
+ export function parseDomainList(raw) {
87
+ if (typeof raw !== 'string' || raw.trim() === '')
88
+ return [];
89
+ const pieces = [];
90
+ let depth = 0;
91
+ let current = '';
92
+ for (const ch of raw) {
93
+ if (ch === '(')
94
+ depth++;
95
+ else if (ch === ')')
96
+ depth = Math.max(0, depth - 1);
97
+ if (ch === ',' && depth === 0) {
98
+ pieces.push(current);
99
+ current = '';
100
+ }
101
+ else
102
+ current += ch;
103
+ }
104
+ pieces.push(current);
105
+ const out = [];
106
+ for (const piece of pieces) {
107
+ const trimmed = piece.trim();
108
+ if (trimmed === '')
109
+ continue;
110
+ const m = /^(.*?)\s*\(([^()]*)\)\s*$/.exec(trimmed);
111
+ const rawTag = (m ? m[1] : trimmed) ?? '';
112
+ const note = m ? (m[2] ?? '').trim() : '';
113
+ const tag = rawTag.trim().toLowerCase().replace(/\s+/g, '-');
114
+ if (tag === '')
115
+ continue; // "(CCIE)" alone names nothing — skip, never throw
116
+ out.push(note === '' ? { tag } : { tag, note });
117
+ }
118
+ return out;
119
+ }
120
+ /** The domains as the text a person would have typed — the re-init prompt default, so an Enter
121
+ * keeps what is already stored. */
122
+ export function domainListText(domains) {
123
+ return domains.map((d) => (d.note ? `${d.tag} (${d.note})` : d.tag)).join(', ');
124
+ }
125
+ /** Parse a yes/no answer in the owner's words. Returns null for anything unrecognised — the
126
+ * caller re-asks or takes the documented default OUT LOUD; this function never guesses (the
127
+ * measured failure: a domains line fed to a y/n question silently became `teaches: no`). */
128
+ export function parseYesNo(raw) {
129
+ const t = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
130
+ if (['y', 'yes', 'да', 'true', 'on'].includes(t))
131
+ return true;
132
+ if (['n', 'no', 'нет', 'false', 'off'].includes(t))
133
+ return false;
134
+ return null;
135
+ }
136
+ /** Absolute path of the profile store: `<home>/.dz/profile.json`. Resolves under `homedir()`
137
+ * and NEVER under a project root — there is deliberately no projectRoot parameter (AR-2:
138
+ * `.dz/config.json` is committed in this repo, so personal data there is a leak by construction).
139
+ * `home` exists as an explicit override so tests run against a scratch HOME. */
140
+ export function profileStorePath(home) {
141
+ return join(home ?? homedir(), '.dz', 'profile.json');
142
+ }
143
+ /** Absolute path of the delivery target: `<home>/.claude/CLAUDE.md`. */
144
+ export function claudeMdPath(home) {
145
+ return join(home ?? homedir(), '.claude', 'CLAUDE.md');
146
+ }
147
+ function validDomainList(v) {
148
+ if (!Array.isArray(v))
149
+ return null;
150
+ const out = [];
151
+ for (const item of v) {
152
+ if (item === null || typeof item !== 'object')
153
+ return null;
154
+ const tag = item.tag;
155
+ if (typeof tag !== 'string' || tag.trim() === '')
156
+ return null;
157
+ const note = item.note;
158
+ if (note !== undefined && typeof note !== 'string')
159
+ return null;
160
+ out.push(note === undefined ? { tag } : { tag, note });
161
+ }
162
+ return out;
163
+ }
164
+ /** Validate an arbitrary value into an OperatorProfile, or say precisely why not.
165
+ *
166
+ * TOTAL by construction (round-6 finding): the shape checks below can themselves throw on hostile
167
+ * input — `JSON.stringify(2n)` in a verdict message is a TypeError, a getter or Proxy can throw on
168
+ * property access — and validateProfile is called OUTSIDE the try of every no-throw caller
169
+ * (readProfile, writeProfile, syncProfileBlock), because it is the boundary those trys rely on.
170
+ * So the boundary itself may never leak: any internal throw becomes a refusal verdict. */
171
+ export function validateProfile(v) {
172
+ try {
173
+ return validateProfileShape(v);
174
+ }
175
+ catch (e) {
176
+ // The catch path may not throw either (round-7 finding): `String(e)` / `e.message` invoke
177
+ // conversion and access hooks on the THROWN value, and a hostile getter can throw an
178
+ // unstringifiable one (`Object.create(null)`) — formatting it under a fixed fallback keeps
179
+ // the boundary total all the way down.
180
+ let detail = 'unformattable error';
181
+ try {
182
+ // Coerce INSIDE the try, and only accept an actual string: a hostile `message` getter can
183
+ // RETURN an unstringifiable object without throwing, which would otherwise blow up at
184
+ // template interpolation below.
185
+ const d = e instanceof Error ? e.message : e;
186
+ detail = typeof d === 'string' ? d : String(d);
187
+ }
188
+ catch { /* keep the fixed fallback */ }
189
+ return { profile: null, problem: `invalid shape: validation threw (${detail})` };
190
+ }
191
+ }
192
+ function validateProfileShape(v) {
193
+ if (v === null || typeof v !== 'object')
194
+ return { profile: null, problem: 'invalid shape: not an object' };
195
+ const o = v;
196
+ if (o.version !== 1)
197
+ return { profile: null, problem: `invalid shape: version must be 1, got ${JSON.stringify(o.version)}` };
198
+ if (typeof o.updatedAt !== 'string')
199
+ return { profile: null, problem: 'invalid shape: updatedAt must be a string' };
200
+ if (typeof o.language !== 'string' || o.language.trim() === '')
201
+ return { profile: null, problem: 'invalid shape: language must be a non-empty string' };
202
+ if (o.register !== 'pro' && o.register !== 'pro-lite' && o.register !== 'plain') {
203
+ return { profile: null, problem: `invalid shape: register must be one of ${REGISTERS.join(' | ')}, got ${JSON.stringify(o.register)}` };
204
+ }
205
+ const deep = validDomainList(o.deepDomains);
206
+ if (deep === null)
207
+ return { profile: null, problem: 'invalid shape: deepDomains must be an array of { tag, note? }' };
208
+ const weak = validDomainList(o.weakDomains);
209
+ if (weak === null)
210
+ return { profile: null, problem: 'invalid shape: weakDomains must be an array of { tag, note? }' };
211
+ if (typeof o.teaches !== 'boolean')
212
+ return { profile: null, problem: 'invalid shape: teaches must be a boolean' };
213
+ // No profile field may contain a block marker literal. A field has no legitimate reason to hold
214
+ // one, and a marker smuggled into a value poisons everything downstream: the first sync writes it
215
+ // INSIDE the generated block, and every later sync (and checkProfileDrift) then reads it as the
216
+ // legacy nested state and refuses — a self-inflicted permanent malfunction (round-4 cross-family
217
+ // finding, `dz profile set language '<!-- dz:profile:start -->'`). Refusal at the ONE validation
218
+ // seam covers every entry path: init, set, --json, and a hand-edited store file.
219
+ // `updatedAt` is included (round-5 P2-1): renderProfileBlock puts it into the heading when it
220
+ // does not parse as a date, so a hand-edited store with a marker there poisons the block exactly
221
+ // like language/tags/notes would.
222
+ const fieldStrings = [o.updatedAt, o.language,
223
+ ...deep.flatMap((d) => [d.tag, d.note ?? '']),
224
+ ...weak.flatMap((d) => [d.tag, d.note ?? ''])];
225
+ for (const f of fieldStrings) {
226
+ if (f.includes(PROFILE_MARKER_START) || f.includes(PROFILE_MARKER_END)) {
227
+ return { profile: null, problem: 'invalid shape: a field value may not contain a profile block marker' };
228
+ }
229
+ }
230
+ return {
231
+ profile: {
232
+ version: 1,
233
+ updatedAt: o.updatedAt,
234
+ language: o.language,
235
+ register: o.register,
236
+ deepDomains: deep,
237
+ weakDomains: weak,
238
+ teaches: o.teaches,
239
+ },
240
+ problem: null,
241
+ };
242
+ }
243
+ /** Read + validate the store. Missing file, unreadable JSON and a wrong shape are three DIFFERENT
244
+ * problems, all reported, none thrown. */
245
+ export function readProfile(home) {
246
+ const path = profileStorePath(home);
247
+ if (!existsSync(path))
248
+ return { profile: null, path, problem: 'missing' };
249
+ let raw;
250
+ try {
251
+ raw = readFileSync(path, 'utf-8');
252
+ }
253
+ catch (e) {
254
+ return { profile: null, path, problem: `unreadable: ${e instanceof Error ? e.message : String(e)}` };
255
+ }
256
+ let parsed;
257
+ try {
258
+ parsed = JSON.parse(raw);
259
+ }
260
+ catch (e) {
261
+ return { profile: null, path, problem: `unreadable JSON: ${e instanceof Error ? e.message : String(e)}` };
262
+ }
263
+ const { profile, problem } = validateProfile(parsed);
264
+ return { profile, path, problem };
265
+ }
266
+ /** Write the store at mode 0600 (creating `<home>/.dz/` at 0700 if needed). The chmod runs even
267
+ * when the file pre-existed: `writeFileSync`'s mode applies only at creation. */
268
+ export function writeProfile(profile, home) {
269
+ // EVERY write revalidates. The round-4 live probe proved why: the marker-literal refusal was first
270
+ // placed in validateProfile alone, and `dz profile set language '<!-- dz:profile:start -->'` still
271
+ // sailed through with exit 0 — the CLI mutates an already-validated object and writes it here,
272
+ // never re-entering validateProfile. A guard on a path a writer can skip is not a guard.
273
+ const { profile: ok, problem } = validateProfile(profile);
274
+ if (ok === null)
275
+ return { path: profileStorePath(home), problem: problem ?? 'invalid profile' };
276
+ const path = profileStorePath(home);
277
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
278
+ writeFileSync(path, JSON.stringify(ok, null, 2) + '\n', { mode: 0o600 });
279
+ chmodSync(path, 0o600);
280
+ return { path };
281
+ }
282
+ const LANGUAGE_NAMES = {
283
+ ru: 'Russian', en: 'English', de: 'German', fr: 'French', es: 'Spanish', zh: 'Chinese',
284
+ };
285
+ function languageName(code) {
286
+ return LANGUAGE_NAMES[code.trim().toLowerCase()] ?? code;
287
+ }
288
+ function domainLine(domains) {
289
+ return domains.map((d) => (d.note ? `${d.tag} (${d.note})` : d.tag)).join(' · ');
290
+ }
291
+ function registerLine(register) {
292
+ switch (register) {
293
+ case 'pro':
294
+ return '**Default register: pro** — full professional register: name the concept and move on; scaffolding reads as patronising.';
295
+ case 'pro-lite':
296
+ return '**Default register: pro-lite** — name the concept AND give one plain sentence of what it means here.';
297
+ case 'plain':
298
+ return '**Default register: plain** — everyday words first; introduce the technical term once, in parentheses, after the plain explanation.';
299
+ }
300
+ }
301
+ /**
302
+ * Render the block CONTENT (without the markers — {@link wrapProfileBlock} adds them).
303
+ *
304
+ * Invariants, each pinned by a test:
305
+ * - both fixed rules (artifact scope; form-not-facts) appear at EVERY register — they are not
306
+ * user settings (ADR Decision 3);
307
+ * - deep and weak domains render visibly DIFFERENT instructions: deep = full pro, no
308
+ * scaffolding; weak = one plain sentence EVERY time, unprompted — mandatory, not default.
309
+ */
310
+ export function renderProfileBlock(profile) {
311
+ const day = /^\d{4}-\d{2}-\d{2}/.exec(profile.updatedAt)?.[0] ?? profile.updatedAt;
312
+ const parts = [];
313
+ parts.push(`## Operator profile (generated by \`dz profile sync\` ${day} — edit with \`dz profile set\`, not by hand)`);
314
+ parts.push(`**Dialogue language: ${languageName(profile.language)}.** Artifacts keep their own conventions (see the scope rule below).`);
315
+ parts.push(registerLine(profile.register));
316
+ if (profile.deepDomains.length > 0) {
317
+ parts.push(`**Deep domains — go full pro here, no scaffolding:**\n${domainLine(profile.deepDomains)}.\n` +
318
+ 'Reach for analogies from these first: they land instantly and they are usually the shortest true explanation.');
319
+ }
320
+ if (profile.weakDomains.length > 0) {
321
+ parts.push(`**Weak domains — one plain sentence EVERY time, unprompted, without waiting to be asked:**\n${domainLine(profile.weakDomains)}.\n` +
322
+ 'The plain sentence here is MANDATORY, not merely a default: not explaining is the failure mode, not over-explaining.');
323
+ }
324
+ // Self-containment is a FIXED rule (owner acceptance, CF-7, 2026-08-28): the live failure it
325
+ // encodes was a term treated as established because it had been explained two hours earlier in
326
+ // the SAME conversation — but the earlier text had scrolled away, and in a fresh session it
327
+ // would never have existed. The rule is about the TERM and the TEXT, not the domain or the
328
+ // conversation history; the weak-domains instruction above stays as the priority signal on top.
329
+ parts.push('**An explanation is SELF-CONTAINED.** Every term introduced gets its gloss at first use IN THIS PASSAGE, ' +
330
+ 'regardless of whether it was explained earlier in the conversation. Do not assume a term is established ' +
331
+ 'because it was covered before — the earlier text has scrolled away, and in a new session it never existed.');
332
+ if (profile.teaches) {
333
+ parts.push('**The operator teaches — explanations must be RE-TELLABLE.** Give the formulation they could carry into a ' +
334
+ 'lecture, not just one that satisfies them in the moment. This makes self-containment STRICT: an explanation ' +
335
+ 'the reader cannot re-tell without the surrounding chat is not finished.');
336
+ }
337
+ // The three-point shape the owner judged clearer at the live acceptance step (CF-7) — named,
338
+ // so the instruction is actionable rather than vague.
339
+ parts.push('**The shape of a good pro-lite explanation:**\n' +
340
+ '1. the term is defined at first use, inline, not deferred;\n' +
341
+ '2. WHY before HOW — the reason the thing exists precedes its mechanism;\n' +
342
+ '3. the conclusion is stated in words, not left for the reader to derive.');
343
+ parts.push('**Scope of the register.** It governs DIALOGUE and owner-facing surfaces: answers, checkpoint questions, ' +
344
+ 'status reports, decision pages. It does NOT govern artifacts written for future readers — ADRs, commit messages, ' +
345
+ 'code comments, QE reports, npm READMEs — those keep their own conventions and audience. An ADR is not simplified ' +
346
+ 'because the current operator asked for a lower register.');
347
+ parts.push('**The register changes FORM, never the FACTS.** Numbers, caveats, risks and refutations survive every level. ' +
348
+ 'Simplifying is not licence to drop a measurement or soften a bad result.');
349
+ parts.push('**Escape hatches, effective immediately for the session:** «проще» / «подробнее» / «как профи» / «я это знаю». ' +
350
+ 'A register corrected twice in one session is evidence the profile is wrong — say so and propose the durable fix ' +
351
+ '(`dz profile set`) rather than absorbing it silently.');
352
+ return parts.join('\n\n');
353
+ }
354
+ /** Wrap rendered content in the marker pair, ready to merge into a target file. */
355
+ export function wrapProfileBlock(content) {
356
+ return `${PROFILE_MARKER_START}\n${content}\n${PROFILE_MARKER_END}`;
357
+ }
358
+ /** Extract the CONTENT between the markers of `fileContent`, or null when no complete block
359
+ * exists. Only the FIRST block is considered (sync never writes a second one). */
360
+ export function extractProfileBlock(fileContent) {
361
+ const start = fileContent.indexOf(PROFILE_MARKER_START);
362
+ if (start === -1)
363
+ return null;
364
+ const afterStart = start + PROFILE_MARKER_START.length;
365
+ const end = fileContent.indexOf(PROFILE_MARKER_END, afterStart);
366
+ if (end === -1)
367
+ return null;
368
+ return fileContent.slice(afterStart, end).replace(/^\n/, '').replace(/\n$/, '');
369
+ }
370
+ /** Pure marked-block merge (the `installDriverDocs` pattern from setup.ts, upgraded from
371
+ * append-if-absent to replace-in-place). Foreign content — everything outside the marker pair —
372
+ * is preserved BYTE-FOR-BYTE; `changed: false` means the file already carries exactly this
373
+ * content (idempotence). `existing: null` means the target file does not exist yet.
374
+ *
375
+ * `malformed: true` (with the input returned untouched) means the file is in a state this merge
376
+ * refuses to write over. `malformedKind` names which of the two known states it is:
377
+ *
378
+ * - `'dangling-start'` — a START marker with no END marker after it. The first version APPENDED
379
+ * a complete fresh block in that case — and the NEXT sync then paired the OLD dangling start
380
+ * with the NEW block's end and deleted everything between them, damaged foreign text included
381
+ * (the second-sync corruption, cross-family finding 2026-08-28).
382
+ * - `'nested-markers'` — ANOTHER start marker between the chosen start and its end. This is the
383
+ * LEGACY residue of exactly that pre-fix append: dangling start … foreign text … appended
384
+ * complete block. Pairing the old start with the appended block's end would delete the foreign
385
+ * text (second cross-family finding, 2026-08-28), and the `dangling-start` refusal above does
386
+ * not fire because an end marker DOES exist after the start.
387
+ *
388
+ * Both states are REFUSED, never repaired automatically: nothing is written, no further nesting
389
+ * can ever be created, and the caller reports the named verdict. A stray END marker with no
390
+ * start before it stays harmless (the block we append is complete, and every later replace
391
+ * anchors at OUR start marker), so it does not refuse. */
392
+ export function mergeProfileBlock(existing, content) {
393
+ const block = wrapProfileBlock(content);
394
+ if (existing === null) {
395
+ return { merged: block + '\n', changed: true, hadBlock: false };
396
+ }
397
+ const start = existing.indexOf(PROFILE_MARKER_START);
398
+ const end = start === -1 ? -1 : existing.indexOf(PROFILE_MARKER_END, start + PROFILE_MARKER_START.length);
399
+ if (start !== -1 && end === -1) {
400
+ return { merged: existing, changed: false, hadBlock: false, malformed: true, malformedKind: 'dangling-start' };
401
+ }
402
+ if (start !== -1) {
403
+ const nested = existing.indexOf(PROFILE_MARKER_START, start + PROFILE_MARKER_START.length);
404
+ if (nested !== -1 && nested < end) {
405
+ return { merged: existing, changed: false, hadBlock: false, malformed: true, malformedKind: 'nested-markers' };
406
+ }
407
+ }
408
+ if (start === -1) {
409
+ // No block at all — append one.
410
+ const sep = existing === '' || existing.endsWith('\n') ? '\n' : '\n\n';
411
+ return { merged: existing + sep + block + '\n', changed: true, hadBlock: false };
412
+ }
413
+ const before = existing.slice(0, start);
414
+ const after = existing.slice(end + PROFILE_MARKER_END.length);
415
+ const merged = before + block + after;
416
+ return { merged, changed: merged !== existing, hadBlock: true };
417
+ }
418
+ /** Write the rendered block into `<home>/.claude/CLAUDE.md`: idempotent, foreign content
419
+ * byte-for-byte, timestamped backup before every MODIFYING write of an existing file.
420
+ * Never throws — an I/O failure (and a malformed block, named as `malformed block:`) is a
421
+ * `problem` verdict.
422
+ *
423
+ * Modes (the delivered COPIES carry the same personal profile as the 0600 store, so none of
424
+ * them may be left to the ambient umask — the key-custody lesson again, one file over):
425
+ * - a target this function CREATES is 0600, and a `.claude/` dir it creates is 0700;
426
+ * - a PRE-EXISTING target keeps its owner bits exactly and loses only group/other bits
427
+ * (`mode & 0o700`). We deliberately do not force 0600 on a file the user owns — their owner
428
+ * permissions are their call — but leaving non-owner read on a file we just wrote the profile
429
+ * into would be the 0644 world-readable-key defect verbatim, so that much IS tightened;
430
+ * - every backup is a fresh file of ours and is written 0600 unconditionally. */
431
+ export function syncProfileBlock(profile, home, now) {
432
+ const target = claudeMdPath(home);
433
+ // This is a PUBLIC write path, so it revalidates just like writeProfile does (round-5 P2-2 —
434
+ // the same seam lesson one function over): a consumer calling it directly with an in-memory
435
+ // profile carrying a marker literal would otherwise render that marker INSIDE the generated
436
+ // block — the first sync writes the nested state, the second refuses it. Invalid → verdict,
437
+ // no write, no backup.
438
+ const { profile: valid, problem: invalid } = validateProfile(profile);
439
+ if (valid === null) {
440
+ return { target, changed: false, backup: null, problem: invalid ?? 'invalid profile' };
441
+ }
442
+ try {
443
+ const existing = existsSync(target) ? readFileSync(target, 'utf-8') : null;
444
+ const merge = mergeProfileBlock(existing, renderProfileBlock(valid));
445
+ if (merge.malformed === true) {
446
+ const detail = merge.malformedKind === 'nested-markers'
447
+ ? `carries a NESTED ${PROFILE_MARKER_START} between a start marker and its end — likely legacy state from a pre-fix sync that appended a block after a dangling start; delete the stray markers or complete the block by hand`
448
+ : `carries ${PROFILE_MARKER_START} with no ${PROFILE_MARKER_END} after it — delete or complete the dangling marker by hand`;
449
+ return {
450
+ target,
451
+ changed: false,
452
+ backup: null,
453
+ problem: `malformed block: ${target} ${detail} — nothing was touched (foreign bytes stay byte-identical); then re-run \`dz profile sync\``,
454
+ };
455
+ }
456
+ if (!merge.changed)
457
+ return { target, changed: false, backup: null, problem: null };
458
+ let backup = null;
459
+ if (existing !== null) {
460
+ const stamp = (now ?? new Date()).toISOString().replace(/[:.]/g, '-');
461
+ backup = `${target}.dz-profile-backup-${stamp}`;
462
+ writeFileSync(backup, existing, { mode: 0o600 });
463
+ chmodSync(backup, 0o600); // writeFileSync's mode applies only at creation
464
+ }
465
+ if (existing === null) {
466
+ mkdirSync(dirname(target), { recursive: true, mode: 0o700 });
467
+ writeFileSync(target, merge.merged, { mode: 0o600 });
468
+ chmodSync(target, 0o600);
469
+ }
470
+ else {
471
+ const prevMode = statSync(target).mode & 0o777;
472
+ writeFileSync(target, merge.merged);
473
+ const tightened = prevMode & 0o700;
474
+ if (tightened !== prevMode)
475
+ chmodSync(target, tightened);
476
+ }
477
+ return { target, changed: true, backup, problem: null };
478
+ }
479
+ catch (e) {
480
+ return { target, changed: false, backup: null, problem: e instanceof Error ? e.message : String(e) };
481
+ }
482
+ }
483
+ /** Does the block currently in `<home>/.claude/CLAUDE.md` match what `profile.json` would
484
+ * render? Compares CONTENT (a hand-edited block that still says the same bytes is in sync;
485
+ * anything else is drift). */
486
+ export function checkProfileDrift(home) {
487
+ const { profile, path, problem } = readProfile(home);
488
+ if (profile === null) {
489
+ return problem === 'missing'
490
+ ? { verdict: 'no-profile', detail: `no profile at ${path} — run \`dz profile init\`` }
491
+ : { verdict: 'invalid-profile', detail: `${path}: ${problem ?? 'invalid'}` };
492
+ }
493
+ const target = claudeMdPath(home);
494
+ if (!existsSync(target))
495
+ return { verdict: 'no-target', detail: `${target} does not exist — run \`dz profile sync\`` };
496
+ let fileContent;
497
+ try {
498
+ fileContent = readFileSync(target, 'utf-8');
499
+ }
500
+ catch (e) {
501
+ return { verdict: 'no-target', detail: `${target}: ${e instanceof Error ? e.message : String(e)}` };
502
+ }
503
+ // The nested-markers legacy state extracts a "block" (a start … end pair exists), so it would
504
+ // read as ordinary drift — whose advice is `dz profile sync`, the exact command that refuses on
505
+ // this file. Name the damage instead, so the operator repairs the right thing.
506
+ {
507
+ const s = fileContent.indexOf(PROFILE_MARKER_START);
508
+ const e = s === -1 ? -1 : fileContent.indexOf(PROFILE_MARKER_END, s + PROFILE_MARKER_START.length);
509
+ const nested = s === -1 || e === -1 ? -1 : fileContent.indexOf(PROFILE_MARKER_START, s + PROFILE_MARKER_START.length);
510
+ if (nested !== -1 && nested < e) {
511
+ return { verdict: 'malformed-block', detail: `${target} carries a NESTED ${PROFILE_MARKER_START} between a start marker and its end (likely legacy state from a pre-fix sync) — delete the stray markers or complete the block by hand, then run \`dz profile sync\`` };
512
+ }
513
+ }
514
+ const inFile = extractProfileBlock(fileContent);
515
+ if (inFile === null) {
516
+ // A start marker WITHOUT an end after it is not "no block" — it is damage `dz profile sync`
517
+ // refuses to write over (see mergeProfileBlock). Name it, so the operator repairs the right thing.
518
+ if (fileContent.includes(PROFILE_MARKER_START)) {
519
+ return { verdict: 'malformed-block', detail: `${target} carries ${PROFILE_MARKER_START} with no ${PROFILE_MARKER_END} after it — delete or complete the dangling marker by hand, then run \`dz profile sync\`` };
520
+ }
521
+ return { verdict: 'no-block', detail: `${target} carries no ${PROFILE_MARKER_START} block — run \`dz profile sync\`` };
522
+ }
523
+ const expected = renderProfileBlock(profile);
524
+ if (inFile === expected)
525
+ return { verdict: 'in-sync', detail: 'block matches profile.json' };
526
+ return { verdict: 'drift', detail: `block in ${target} differs from what profile.json renders — run \`dz profile sync\`` };
527
+ }
528
+ /** Whole-days age of the profile, or null when updatedAt does not parse. */
529
+ export function profileAgeDays(profile, now) {
530
+ const t = Date.parse(profile.updatedAt);
531
+ if (!Number.isFinite(t))
532
+ return null;
533
+ const ms = (now ?? new Date()).getTime() - t;
534
+ return Math.floor(ms / 86_400_000);
535
+ }
536
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"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"}
package/dist/publish.d.ts CHANGED
@@ -102,9 +102,11 @@ export declare function discoverPackages(monorepoRoot: string): {
102
102
  * published npm tarball (a `dz install` would not deliver them).
103
103
  *
104
104
  * A pack with no `files` array publishes everything, so nothing is missing. When a
105
- * `files` array is present, npm only ships the listed paths; a skill dir (`<name>/SKILL.md`)
106
- * is covered iff its directory name appears in `files`. Returns the sorted list of
107
- * uncovered skill directory names (empty = complete).
105
+ * `files` array is present, npm only ships the listed paths. A skill dir (`<name>/SKILL.md`)
106
+ * is covered iff either its directory is selected, or EVERY regular file currently under that
107
+ * skill has an exact/ancestor entry. Merely listing `SKILL.md` is not enough: that would let a
108
+ * closed per-file allowlist silently drop a referenced script. Returns the sorted list of
109
+ * incomplete skill directory names (empty = complete).
108
110
  */
109
111
  export declare function findUnpackagedSkills(packDir: string): string[];
110
112
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACxF;AAED,2BAA2B;AAC3B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAQD,0CAA0C;AAC1C,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5D;AA8BD;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC1D,gGAAgG;IAChG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC/D,mGAAmG;IACnG,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAsBtC;AAYD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQvD;AAYD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;AAEnD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAO5E;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,kBAAkB,CAiBjG;AAED,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAGhF;AAED,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAavG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAuD9D;AAiBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAmB3F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkBzG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG3E;AAkCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAgBrE;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAClE;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IAC/G;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACjD,+FAA+F;IAC/F,UAAU,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACxC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAClE,GACL,aAAa,CA2Of"}