devlyn-cli 4.3.25 → 4.3.28

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 (41) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +27 -27
  4. package/bin/devlyn.js +42 -94
  5. package/bin/harness-activation.js +4 -8
  6. package/bin/harness-context.js +395 -0
  7. package/bin/harness-run.js +148 -0
  8. package/bin/instruction-templates.json +2 -0
  9. package/bin/instructions.js +71 -159
  10. package/bin/skill-history.json +8 -0
  11. package/config/skills/_shared/runtime-principles.md +1 -1
  12. package/config/skills/_shared/storage-checkout.py +1 -0
  13. package/config/skills/_shared/storage-client.py +349 -14
  14. package/config/skills/_shared/task-complete.py +99 -24
  15. package/config/skills/_shared/task-completion.md +7 -3
  16. package/config/skills/devlyn-ideate/SKILL.md +2 -2
  17. package/config/skills/devlyn-ideate/references/loop.md +2 -2
  18. package/config/skills/devlyn-ideate/scripts/queue.py +10 -3
  19. package/harness/AGENTS.md +2 -2
  20. package/harness/CLAUDE.md +2 -2
  21. package/native/claude/.claude-plugin/plugin.json +1 -1
  22. package/native/claude/skills/_shared/runtime-principles.md +1 -1
  23. package/native/claude/skills/_shared/storage-checkout.py +1 -0
  24. package/native/claude/skills/_shared/storage-client.py +349 -14
  25. package/native/claude/skills/_shared/task-complete.py +99 -24
  26. package/native/claude/skills/_shared/task-completion.md +7 -3
  27. package/native/claude/skills/devlyn-ideate/SKILL.md +2 -2
  28. package/native/claude/skills/devlyn-ideate/references/loop.md +2 -2
  29. package/native/claude/skills/devlyn-ideate/scripts/queue.py +10 -3
  30. package/native/codex/.agents/plugins/marketplace.json +1 -1
  31. package/native/codex/plugins/devlyn/.codex-plugin/plugin.json +1 -1
  32. package/native/codex/plugins/devlyn/skills/_shared/runtime-principles.md +1 -1
  33. package/native/codex/plugins/devlyn/skills/_shared/storage-checkout.py +1 -0
  34. package/native/codex/plugins/devlyn/skills/_shared/storage-client.py +349 -14
  35. package/native/codex/plugins/devlyn/skills/_shared/task-complete.py +99 -24
  36. package/native/codex/plugins/devlyn/skills/_shared/task-completion.md +7 -3
  37. package/native/codex/plugins/devlyn/skills/devlyn-ideate/SKILL.md +2 -2
  38. package/native/codex/plugins/devlyn/skills/devlyn-ideate/references/loop.md +2 -2
  39. package/native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/queue.py +10 -3
  40. package/package.json +2 -2
  41. package/release.json +51 -41
@@ -8,6 +8,7 @@ const cleanupHistory = require('./cleanup-history.json');
8
8
  const BEGIN = '<!-- devlyn:instructions:begin';
9
9
  const END = '<!-- devlyn:instructions:end -->';
10
10
  const LEGACY = /^devlyn-cli installs |^# Devlyn Agent Instructions\r?$|^This contract serves one goal: any capable engine|^Engine roles: orchestrator =/m;
11
+ const VOID_ELEMENT = /^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i;
11
12
  const normalize = (text) => text.replace(/\r\n/g, '\n');
12
13
  const digest = (text) => crypto.createHash('sha256').update(text).digest('hex');
13
14
 
@@ -39,33 +40,15 @@ function matchedEnd(text, start, template) {
39
40
  // A digest is ownership evidence; a familiar heading alone is not.
40
41
  function legacyRanges(text, templates) {
41
42
  const bom = text.startsWith('\uFEFF') ? 1 : 0;
42
- const starts = [...new Set([0, ...(text.startsWith('\uFEFF') ? [1] : []),
43
+ const starts = [...new Set([0, ...(bom ? [1] : []),
43
44
  ...instructionParagraphs(text.slice(bom))
44
45
  .filter((p) => p.level === 1 && /^# (?:Codex )?Project Instructions\r?\n/.test(p.text))
45
- .map((p) => p.start + bom)])].sort((a, b) => a - b);
46
+ .map((p) => p.start + bom)])];
46
47
  const ranges = [];
47
48
  for (const start of starts) {
48
49
  for (const template of templates) {
49
- let end = matchedEnd(text, start, template);
50
- let custom = '';
51
- if (end === null && template.body) {
52
- const prefix = text.slice(start, starts.find((offset) => offset > start));
53
- const body = instructionParagraphs(prefix).find((p) => p.level === 2 && /^## North Star\r?\n/.test(p.text));
54
- const header = template.preamble.slice(0, template.preamble.indexOf('\n\n') + 2);
55
- if (body && normalize(prefix).startsWith(header)) {
56
- const bodyStart = start + body.start;
57
- end = matchedEnd(text, bodyStart, template.body);
58
- // Remove only an exact original preamble; preserve an edited one in full.
59
- const preambleEnd = matchedEnd(text, start, { length: template.preamble.length, sha256: digest(template.preamble) });
60
- custom = text.slice(preambleEnd ?? start, bodyStart);
61
- }
62
- }
63
- if (end !== null) {
64
- const existing = ranges.find((range) => range.start === start && range.end === end);
65
- if (!existing) ranges.push({ start, end, custom });
66
- // Releases may share a body. Prefer the exact owned preamble, if found.
67
- else if (custom.length < existing.custom.length) existing.custom = custom;
68
- }
50
+ const end = matchedEnd(text, start, template);
51
+ if (end !== null && !ranges.some((range) => range.start === start && range.end === end)) ranges.push({ start, end });
69
52
  }
70
53
  }
71
54
  return ranges;
@@ -102,7 +85,7 @@ function instructionParagraphs(text) {
102
85
  if (!comment) markup += line.slice(cursor);
103
86
  const opening = /^ {0,3}<([a-z][\w:-]*)\b[^>]*>/i.exec(markup);
104
87
  if (!html && opening && !/\/>$/.test(opening[0])
105
- && !/^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(opening[1])) {
88
+ && !VOID_ELEMENT.test(opening[1])) {
106
89
  html = { tag: opening[1].toLowerCase(), depth: 0 };
107
90
  }
108
91
  if (html) {
@@ -130,42 +113,14 @@ function instructionParagraphs(text) {
130
113
  return paragraphs;
131
114
  }
132
115
 
133
- // Recognize direct adjacent imports in Markdown text, including inline imports.
134
- // Leaf tokens keep code, escapes and ordinary HTML from removing our only block.
135
- function importsAgentsMd(text) {
136
- // Match the complete native path token before dropping its optional fragment.
137
- const matchesImport = (value) => [...value.matchAll(/(?:^|\s)@((?:[^\s\\]|\\ )+)/g)].some((match) => {
138
- const file = match[1].split('#', 1)[0];
139
- return file === 'AGENTS.md' || file === './AGENTS.md';
140
- });
141
- const containsImport = (tokens) => tokens.some((token) => {
142
- if (['code', 'codespan'].includes(token.type)) return false;
143
- if (token.type === 'html') {
144
- const raw = token.raw || '';
145
- // Native Claude scans text left after complete comments in a comment-shaped HTML token.
146
- return raw.trimStart().startsWith('<!--') && raw.includes('-->')
147
- && matchesImport(raw.replace(/<!--[\s\S]*?-->/g, ''));
148
- }
149
- if (token.tokens) return containsImport(token.tokens);
150
- if (token.items) return containsImport(token.items);
151
- return token.type === 'text' && matchesImport(token.text);
152
- });
153
- // Claude strips this bounded frontmatter prefix before expanding imports.
154
- const body = text.replace(/^\uFEFF/, '').replace(/^---\s*\n([\s\S]*?)---\s*\n?/, '');
155
- return containsImport(new Lexer({ gfm: false }).lex(body));
156
- }
157
-
158
- function customInstructions(text, name, template, managed = false) {
159
- const known = new Set([
160
- ...(legacyTemplates.paragraphs[name] || []),
161
- ...instructionParagraphs(template).map((p) => p.key),
162
- ]);
116
+ function customInstructions(text, name) {
117
+ const known = new Set(legacyTemplates.paragraphs[name] || []);
163
118
  const bom = text.startsWith('\uFEFF') ? '\uFEFF' : '';
164
119
  const paragraphs = instructionParagraphs(text.slice(bom.length));
165
120
  const keep = new Set();
166
- let legacy = managed;
121
+ let legacy = false;
167
122
  for (const [index, paragraph] of paragraphs.entries()) {
168
- if (!managed && paragraph.level === 1) {
123
+ if (paragraph.level === 1) {
169
124
  const next = paragraphs.findIndex((p, i) => i > index && p.level === 1);
170
125
  const section = paragraphs.slice(index, next < 0 ? undefined : next);
171
126
  legacy = /^# (?:Codex )?Project Instructions\r?\n|^# Devlyn Agent Instructions\r?\n/.test(paragraph.text)
@@ -196,9 +151,42 @@ function removeEvaluatorBlocks(text) {
196
151
  }
197
152
 
198
153
  // Devlyn defaults in an instruction file: a managed block, or stock paragraphs of a template
199
- // that a release before managed blocks copied in whole (the evidence migration replaces).
154
+ // that a release before managed blocks copied in whole.
200
155
  function holdsDevlynDefaults(name, text) {
201
- return text.includes(BEGIN) || customInstructions(text, name, '') !== text;
156
+ return text.includes(BEGIN) || customInstructions(text, name) !== text;
157
+ }
158
+
159
+ // An example quotes a block: Markdown reads its marker as part of something else, or an element
160
+ // opened before it is still open. An owner's stray tag can only keep a block, never lose text.
161
+ function quoted(text) {
162
+ const open = new Map();
163
+ for (const token of new Lexer({ gfm: false }).lex(normalize(text.replace(/^\uFEFF/, '')))) {
164
+ if (token.type !== 'html') continue;
165
+ if (token.raw.startsWith(BEGIN)) return [...open.values()].some((depth) => depth > 0);
166
+ for (const [tag, close, element] of token.raw.replace(/<!--[\s\S]*?-->/g, '').matchAll(/<(\/?)([a-z][\w:-]*)\b[^>]*>/gi)) {
167
+ if (tag.endsWith('/>') || VOID_ELEMENT.test(element)) continue;
168
+ const name = element.toLowerCase();
169
+ open.set(name, (open.get(name) || 0) + (close ? -1 : 1));
170
+ }
171
+ }
172
+ return true;
173
+ }
174
+
175
+ // The range a release provably wrote, or null: one block whose bytes still match its own digest
176
+ // and that no example quotes, or one whole template without markers. Anything else is the owner's.
177
+ function devlynCopy(name, text, template) {
178
+ if (text.includes(BEGIN) || text.includes(END)) {
179
+ const starts = [...text.matchAll(/^(\uFEFF?)<!-- devlyn:instructions:begin sha256=([a-f0-9]{64}) -->\r?\n/gm)];
180
+ const ends = [...text.matchAll(/^<!-- devlyn:instructions:end -->(?:\r?\n|$)/gm)];
181
+ if (starts.length !== 1 || ends.length !== 1 || text.split(BEGIN).length !== 2 || text.split(END).length !== 2) return null;
182
+ const [start] = starts, [end] = ends;
183
+ const body = start.index + start[0].length;
184
+ if (end.index < body || digest(normalize(text.slice(body, end.index))) !== start[2] || quoted(text)) return null;
185
+ return { start: start.index + start[1].length, end: end.index + end[0].length };
186
+ }
187
+ const normalized = normalize(template);
188
+ const ranges = legacyRanges(text, [{ length: normalized.length, sha256: digest(normalized) }, ...(legacyTemplates[name] || [])]);
189
+ return ranges.length === 1 && !LEGACY.test(text.slice(0, ranges[0].start) + text.slice(ranges[0].end)) ? ranges[0] : null;
202
190
  }
203
191
 
204
192
  function retainFile(file, bytes) {
@@ -220,129 +208,53 @@ function retainFile(file, bytes) {
220
208
  }
221
209
  }
222
210
 
223
- // `withBlock` false removes the devlyn defaults the file holds, keeping everything else. `write` false writes nothing
224
- // and returns whether the file needs an update, a merge included.
225
- function updateInstructions(name, initial = '', withBlock = true, write = true, directory = process.cwd(), evaluatorOnly = false) {
226
- const projectPackage = path.join(directory, 'package.json');
227
- if (fs.existsSync(path.join(directory, 'bin', 'devlyn.js')) && fs.existsSync(projectPackage)
228
- && JSON.parse(fs.readFileSync(projectPackage, 'utf8'))?.name === 'devlyn-cli') {
229
- console.log(` → Skipping ${name}; shipped instruction template in devlyn-cli source checkout`);
230
- return false;
231
- }
232
- const templateName = path.basename(name);
233
- const templatePath = path.join(__dirname, '..', templateName);
234
- const template = ['CLAUDE.md', 'AGENTS.md'].includes(templateName) ? fs.readFileSync(templatePath, 'utf8') : '';
211
+ // Removes the devlyn defaults the file holds, keeping everything else. `write` false writes nothing and returns
212
+ // whether the file needs the removal. `evaluatorOnly` removes only appended evaluator blocks.
213
+ function removeInstructions(name, write = true, directory = process.cwd()) {
214
+ const templatePath = path.join(__dirname, '..', name);
215
+ const template = ['CLAUDE.md', 'AGENTS.md'].includes(name) ? fs.readFileSync(templatePath, 'utf8') : '';
235
216
  if (template.includes(BEGIN) || template.includes(END)) {
236
217
  throw new Error(`Packaged instruction template contains managed markers: ${templatePath}`);
237
218
  }
238
219
  const dest = path.join(directory, name);
239
220
  const stat = fs.lstatSync(dest, { throwIfNoEntry: false });
221
+ if (!stat) return false;
240
222
  const sourceStat = template ? fs.statSync(templatePath) : null;
241
- if (stat?.isFile() && stat.dev === sourceStat?.dev && stat.ino === sourceStat?.ino) {
242
- console.log(` → Using source ${name}; packaged template left unchanged`);
243
- return false;
244
- }
245
- const exists = Boolean(stat);
223
+ if (stat.isFile() && stat.dev === sourceStat?.dev && stat.ino === sourceStat?.ino) return false; // The shipped template itself.
246
224
  // Do not replace a shared instruction symlink or follow it outside the project.
247
- if (stat && !stat.isFile()) {
248
- throw new InstructionError(`Instruction file must be a regular file; preserved: ${dest}. Move it aside and rerun, then merge your shared rules outside the managed block.`);
249
- }
250
- const before = exists ? fs.readFileSync(dest) : Buffer.alloc(0);
251
- let current = initial;
225
+ if (!stat.isFile()) throw new InstructionError(`Instruction file must be a regular file; preserved: ${dest}.`);
226
+ const before = fs.readFileSync(dest);
227
+ let current;
252
228
  try {
253
- if (exists) current = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(before);
229
+ current = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(before);
254
230
  } catch (cause) {
255
- throw new InstructionError(`${name} must be UTF-8; original preserved. Convert its encoding and rerun installation.`, { cause });
256
- }
257
- current = removeEvaluatorBlocks(current);
258
- const eol = current.match(/\r?\n/)?.[0] || '\n';
259
- const block = managedBlock(template, eol);
260
- const inserted = withBlock ? block : '';
261
- const recovery = path.join(directory, '.devlyn', 'instructions');
262
- const conflict = (reason) => {
263
- if (!write) return true;
264
- const incoming = path.join(recovery, `${encodeURIComponent(name)}.${digest(block)}.incoming`);
265
- const backup = path.join(recovery, `${encodeURIComponent(name)}.${digest(before)}.backup`);
266
- const guide = path.join(recovery, `${encodeURIComponent(name)}.${digest(before)}.${digest(block)}.merge.md`);
267
- retainFile(backup, before);
268
- retainFile(incoming, Buffer.from(block));
269
- retainFile(guide, Buffer.from(`# Merge ${name}\n\n`
270
- + `Installation stopped: ${reason}. The original file is unchanged.\n\n`
271
- + `- Backup before this install attempt: ${backup}\n- New Devlyn defaults: ${incoming}\n- File to update: ${dest}\n\n`
272
- + `1. Compare the backup and new defaults side by side. Identify all project-specific additions and edits; do not discard them.\n`
273
- + `2. Update ${name} with exactly one complete managed block from the new defaults. Keep project-specific rules outside that block; they take precedence. Resolve conflicting rules explicitly. Do not copy the new defaults over the whole file.\n`
274
- + `3. Review the result, then rerun the same install command (for example, npx devlyn-cli). Other selected agents may still need installation.\n\n`
275
- + `To undo this manual merge, restore that backup to ${dest}. Earlier backups are retained too.\n`));
276
- throw new InstructionError(`${name} needs merge (${reason}).\n`
277
- + `Original preserved: ${dest}\nBackup: ${backup}\nNew defaults: ${incoming}\n`
278
- + `Merge instructions: ${guide}\n`
279
- + `Keep custom rules outside the managed block, then rerun the same install command.\n`
280
- + `Installation is incomplete; earlier selected agents may already have been updated.`);
281
- };
282
- let content;
283
- if (evaluatorOnly) {
284
- content = current;
285
- } else if (current.includes(BEGIN) || current.includes(END)) {
286
- const starts = [...current.matchAll(/^\uFEFF?<!-- devlyn:instructions:begin sha256=([a-f0-9]{64}) -->\r?\n/gm)];
287
- const ends = [...current.matchAll(/^<!-- devlyn:instructions:end -->(?:\r?\n|$)/gm)];
288
- if (starts.length !== 1 || ends.length !== 1
289
- || current.split(BEGIN).length !== 2 || current.split(END).length !== 2) {
290
- return conflict('ambiguous managed markers');
291
- }
292
- const start = starts[0];
293
- const end = ends[0];
294
- const bodyStart = start.index + start[0].length;
295
- if (end.index < bodyStart) return conflict('reversed managed markers');
296
- const previous = current.slice(bodyStart, end.index);
297
- const custom = digest(normalize(previous)) === start[1] ? ''
298
- : customInstructions(previous, templateName,
299
- 'Project-specific instructions outside this managed block take precedence over these defaults.\n\n' + template, true);
300
- const after = current.slice(end.index + end[0].length);
301
- content = current.slice(0, start.index + (start[0].startsWith('\uFEFF') ? 1 : 0))
302
- + custom + (custom ? eol : '') + inserted + after;
303
- } else {
304
- const normalized = normalize(template);
305
- const bodyStart = normalized.indexOf('## North Star\n');
306
- const preamble = normalized.slice(0, bodyStart);
307
- const body = normalized.slice(bodyStart);
308
- const ranges = legacyRanges(current, [
309
- ...(normalized ? [{ length: normalized.length, sha256: digest(normalized),
310
- ...(bodyStart > 0 ? { preamble, body: { length: body.length, sha256: digest(body) } } : {}) }] : []),
311
- ...(legacyTemplates[templateName] || []),
312
- ]);
313
- if (ranges.length === 1 && !LEGACY.test(current.slice(0, ranges[0].start)
314
- + ranges[0].custom + current.slice(ranges[0].end))) {
315
- const { start, end, custom } = ranges[0];
316
- content = current.slice(0, start) + custom + inserted + current.slice(end);
317
- } else {
318
- const custom = customInstructions(current, templateName, template);
319
- content = custom + (custom && inserted ? eol + eol : '') + inserted;
320
- }
231
+ throw new InstructionError(`${name} must be UTF-8; original preserved.`, { cause });
321
232
  }
233
+ let content = removeEvaluatorBlocks(current);
234
+ const copy = template ? devlynCopy(name, content, template) : null;
235
+ if (copy) content = content.slice(0, copy.start) + content.slice(copy.end);
322
236
  const bytes = Buffer.from(content);
323
237
  if (bytes.equals(before)) return false;
324
238
  if (!write) return true;
325
- if (exists) {
326
- const backup = path.join(recovery, `${encodeURIComponent(name)}.${digest(before)}.backup`);
327
- retainFile(backup, before);
328
- console.log(` → Saved previous ${name}: ${backup}`);
329
- }
239
+ const backup = path.join(directory, '.devlyn', 'instructions', `${encodeURIComponent(name)}.${digest(before)}.backup`);
240
+ retainFile(backup, before);
241
+ console.log(` → Saved previous ${name}: ${backup}`);
242
+ const empty = content.replace(/^\uFEFF/, '') === '';
330
243
  const temp = `${dest}.${crypto.randomUUID()}.tmp`;
331
244
  try {
332
- fs.writeFileSync(temp, bytes, { flag: 'wx', mode: exists ? stat.mode & 0o777 : 0o644 });
333
- if (exists) fs.chmodSync(temp, stat.mode & 0o777);
334
- if (fs.existsSync(dest) !== exists || (exists && !fs.readFileSync(dest).equals(before))) {
335
- throw new InstructionError(`${name} changed during installation; preserved it. Rerun installation.`);
245
+ fs.writeFileSync(temp, bytes, { flag: 'wx', mode: stat.mode & 0o777 });
246
+ fs.chmodSync(temp, stat.mode & 0o777);
247
+ if (!fs.existsSync(dest) || !fs.readFileSync(dest).equals(before)) {
248
+ throw new InstructionError(`${name} changed during removal; preserved it.`);
336
249
  }
337
- if (!withBlock && content === '') fs.unlinkSync(dest);
250
+ if (empty) fs.unlinkSync(dest);
338
251
  else fs.renameSync(temp, dest);
339
252
  } finally {
340
253
  if (fs.existsSync(temp)) fs.unlinkSync(temp);
341
254
  }
342
- console.log(!withBlock && content === '' ? ` ✕ ${name} (removed)` : !exists ? ` → Created ${name}`
343
- : ` → ${withBlock ? 'Updated Devlyn defaults in' : 'Removed Devlyn defaults from'} ${name}; project-specific instructions preserved`);
255
+ console.log(empty ? ` ✕ ${name} (removed)` : ` → Removed Devlyn defaults from ${name}; project-specific instructions preserved`);
344
256
  return true;
345
257
  }
346
258
 
347
- module.exports = { updateInstructions, InstructionError, instructionParagraphs, holdsDevlynDefaults, importsAgentsMd,
259
+ module.exports = { removeInstructions, InstructionError, instructionParagraphs, holdsDevlynDefaults,
348
260
  managedBody, managedBlock, sessionDefaults };
@@ -90,6 +90,7 @@
90
90
  "6d1a5458b23196b6f6fde6b7e9dc097ed173cb5914de439e512a032ca1892812",
91
91
  "6e70044cab5a3fb1f78b7148c2111e4298ce8f5f8e902220430ca316bb61255d",
92
92
  "6fa2b5e089dcd00613c6e9800d2e763da9e5b2c80e6a7ef5d54d5ad7113e8399",
93
+ "701c6a010a526429642123a2be1a56d724cd47b7e5000f78c5bde7d66c3b133b",
93
94
  "713921f9a442770fc4de24b990dee6a4a5358a0d69bc26af80c33dc6f15a7274",
94
95
  "71fb125e20420d6f3fcd3396093fcdc8d552bab9626c3cbd962351e0d19adac8",
95
96
  "725395f70eec7e2ceae1f3aa122893433923b098a1e0d6202dd410979ef4eea0",
@@ -160,11 +161,13 @@
160
161
  "d201802016f06626bd9fa4074d61a54ab9f70b7febfccc0ea0c70605d1f1b811",
161
162
  "d2273f7404df92436c4c2ebcf38bdf1e5dbc65c5d1544f95dd1332c123ef17df",
162
163
  "d22bbe15dff66d4801320ea81d7952af50615a7ed57ffe7033545589b8d946bd",
164
+ "d243bff7bb0a780d933dc66ed5a899d0d4e2a00e9dcdde66beeb518247c859a6",
163
165
  "d3b40b9f0e15bf90ca557c0198a8fe5ff1d046b9aaa54b181c743d8e006f9c34",
164
166
  "d424feceffc005f220e33a19cac73f33bd40d120cc14da33725b8a990704bcf6",
165
167
  "d7388e36d76647a89ce52de615271928cf9fc78f980df399d2bc2e6d6675ec82",
166
168
  "d85fa24b9b2c439742c9a62d5d4e07a031a1cfe6024bbc06f98eff7063424179",
167
169
  "dac3da11ea5686382f5c9892a0b8e4ec25e625e5946283d8e2ad944aa84e1df2",
170
+ "db2a57a81fc9ffddb7f7f2b7a59ac4821563c345e2a47f825eade308f2707040",
168
171
  "db867d1fd98058bb20e41e942abd95f08fbaa9465928025f69f0a0308fa71514",
169
172
  "dd0bfdfd2db0b5f9ddef75d1b9ce3247698739fc551d292366dccd506fef6a36",
170
173
  "ddb0c8dac58e95298330ab54e4d1fe4a108c968d9af713f267b4f8f4c6808507",
@@ -358,6 +361,7 @@
358
361
  "5824f07e455fe1c3942bf595a12e935258d4c0a851ca1bf741db915603d1c4e0",
359
362
  "59261610d60ca0f94cc8fa33af61f8ddafd8e5616f9358591547dd23fcdc6328",
360
363
  "5954e371659ae1010757f0eec4b80dd65a899f9fcf76d4d84d9a75476a963218",
364
+ "6374290c74a8c17979e8c128905e106d38bd810c0451f0e9240c30e0f7ecabb0",
361
365
  "65770e3f20c3a3afd2822e9acdcfc80b827f84a7737010b79332da70d431b05d",
362
366
  "65c781764633b912e5947362eba0837c8027461a904975401d79ad4fe8714084",
363
367
  "694c8920e50d92cba46dbb27eb44dd88035a89ed625d3cbf9f2bce9366d44c96",
@@ -365,6 +369,7 @@
365
369
  "6b403afbf5a117cc08603d3648b9dded4f9ac4ca02fc1d8e1f0035615148bb5c",
366
370
  "6c3e2e4b84b0b4f81aed3759704da7c14f3cbabf3beeb0d1654feda3a15a8675",
367
371
  "6d9df58c117165e9d297aa6be0df8d076bac1ed49dc29ae93906af1969798ab1",
372
+ "6e2b54571bfbc1fab571b81564fb0625ed83333fc12277c473fdf5a231f7d40c",
368
373
  "6e7228610628fc4bca31dc0b0aaf5eb4445e1f123f2c54bd13921c5cd01129fe",
369
374
  "75cecbce4d1f4adbba608cef498ae7e421ea75512c6bf9282b66cd94d821f672",
370
375
  "7f451e48e391643b34f6249244bc47d93d6303875e7b092771e3af0718343bc1",
@@ -804,6 +809,9 @@
804
809
  "4.3.23",
805
810
  "4.3.24",
806
811
  "4.3.25",
812
+ "4.3.26",
813
+ "4.3.27",
814
+ "4.3.28",
807
815
  "4.3.3",
808
816
  "4.3.4",
809
817
  "4.3.5",
@@ -17,7 +17,7 @@ Seven rules govern every change. Cite them by name when a decision touches one.
17
17
  3. **No guesswork** — verify with the actual files, logs, diffs, and run output before forming conclusions. State the falsifiable prediction BEFORE the experiment; record raw results AFTER. Retroactive prediction edits are dishonest.
18
18
  4. **Worldclass** — zero CRITICAL, zero HIGH security/design findings on the shippable path. Any review is one pass in which every reviewer, including each one the user requires, reads the source the checks ran on; fix each finding or reject it with a reason, re-check the fixes and the invariants they touch, and repeat the full review only while a CRITICAL or HIGH finding remains.
19
19
  5. **Best practice** — idiomatic for the language and framework. Use standard primitives; do not hand-roll what the library already provides.
20
- 6. **Optimized** — use efficient code and avoid unnecessary work without sacrificing correctness or the user's requirements.
20
+ 6. **Optimized** — efficient on the resource that matters (the user's time, tokens, attention, runtime) without weakening correctness or requirements. An extra check or process step must beat the simpler path.
21
21
  7. **Production ready** — error states are explicit and visible; behavior under failure is what the user expects, not silent corruption.
22
22
 
23
23
  Three discipline rules govern HOW the principles are applied:
@@ -52,6 +52,7 @@ def validate_closure(value):
52
52
  require(type(value) is dict, 'positive reservation closure missing')
53
53
  tag = value.get('established_by')
54
54
  shapes = {'released': {'established_by': ('released',), 'reservation': 'reservation'},
55
+ 'authority_migrated': {'established_by': ('authority_migrated',), 'operation_id': 'str'},
55
56
  'authority_expired': {'established_by': ('authority_expired',), 'operation_id': 'str'},
56
57
  'never_admitted': {'established_by': ('never_admitted',), 'operation_id': 'str'},
57
58
  'legacy_unreserved': {'established_by': ('legacy_unreserved',), 'receipt_version': 'u32'}}