instar 1.2.36 → 1.2.37
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/core/AutoUpdater.d.ts.map +1 -1
- package/dist/core/AutoUpdater.js +25 -1
- package/dist/core/AutoUpdater.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +91 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/version-skew.d.ts +77 -0
- package/dist/core/version-skew.d.ts.map +1 -0
- package/dist/core/version-skew.js +144 -0
- package/dist/core/version-skew.js.map +1 -0
- package/dist/lifeline/RestartOrchestrator.d.ts +1 -1
- package/dist/lifeline/RestartOrchestrator.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts +14 -0
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +60 -0
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/lifeline/rateLimitState.d.ts +1 -1
- package/dist/lifeline/rateLimitState.d.ts.map +1 -1
- package/dist/lifeline/rateLimitState.js +16 -11
- package/dist/lifeline/rateLimitState.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +20 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/instar-dev-precommit.js +128 -0
- package/src/data/builtin-manifest.json +64 -64
- package/src/templates/scripts/instar-watchdog.sh +80 -3
- package/upgrades/1.2.37.md +53 -0
- package/upgrades/side-effects/auto-updater-lifeline-coordination.md +199 -0
package/package.json
CHANGED
|
@@ -330,6 +330,134 @@ if (staged.includes(spec) && !staged.includes(eli16Rel)) {
|
|
|
330
330
|
);
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
// ─── Step 7.5: orphan deferrals must be tracked ───────────────────────────
|
|
334
|
+
// Why: on 2026-05-20 PR #284 shipped four of five fixes for a version-skew
|
|
335
|
+
// failure class and explicitly deferred the fifth ("lifeline auto-restart on
|
|
336
|
+
// server upgrade — out of scope today"). Two days later that exact deferral
|
|
337
|
+
// produced the same outage. Per user feedback 2026-05-22: "WE NEED TO CHANGE
|
|
338
|
+
// THIS. Our development work should focus on COMPLETE features/fixes with NO
|
|
339
|
+
// deferrals." This check makes the rule structural: any spec that contains
|
|
340
|
+
// "deferred / out of scope today / follow-up / preemptive fix / NOT in this
|
|
341
|
+
// PR" language must explicitly track each instance (HTML comment marker
|
|
342
|
+
// `<!-- tracked: <id> -->` within 200 chars, or a frontmatter
|
|
343
|
+
// `deferrals-tracked` field). Override via INSTAR_DEV_ALLOW_ORPHAN_DEFERRALS=1
|
|
344
|
+
// (logged for visibility).
|
|
345
|
+
//
|
|
346
|
+
// Detector patterns intentionally conservative — false-positives are cheaper
|
|
347
|
+
// than false-negatives here. The author can either link a tracker or rephrase
|
|
348
|
+
// the sentence to not promise a deferral.
|
|
349
|
+
// Patterns: { regex, requireUnnegated } — when requireUnnegated is true,
|
|
350
|
+
// we skip the match if the immediately-preceding chars contain "no ", "non-",
|
|
351
|
+
// "non ", "non", or "un" (so "no deferrals" / "non-deferred" / "undeferred"
|
|
352
|
+
// don't false-alarm).
|
|
353
|
+
//
|
|
354
|
+
// Reviewer feedback 2026-05-22: the prior implementation honored a
|
|
355
|
+
// `deferrals-tracked:` frontmatter wave-through that short-circuited the
|
|
356
|
+
// entire body scan. That was a loophole — a future author could write
|
|
357
|
+
// `deferrals-tracked: see below` and ship orphan deferrals with no
|
|
358
|
+
// validation. Closed: every body hit must have its own inline tracker
|
|
359
|
+
// marker within 200 chars. The §"Deferrals tracked" section in the spec is
|
|
360
|
+
// still useful as a human-readable catalog, but no longer a bypass.
|
|
361
|
+
const DEFERRAL_PATTERNS = [
|
|
362
|
+
{ regex: /\bdeferred?\b/gi, requireUnnegated: true },
|
|
363
|
+
{ regex: /\bdeferrals?\b/gi, requireUnnegated: true },
|
|
364
|
+
{ regex: /\bout of scope today\b/gi, requireUnnegated: false },
|
|
365
|
+
{ regex: /\bout of scope for now\b/gi, requireUnnegated: false },
|
|
366
|
+
{ regex: /\bnot in this pr\b/gi, requireUnnegated: false },
|
|
367
|
+
{ regex: /\bpreemptive fix\b/gi, requireUnnegated: false },
|
|
368
|
+
// Match standalone "follow-up" / "follow-ups" / "followups" mentions.
|
|
369
|
+
// Reviewer broadened from the prior narrow "(?!\s+(?:are\s+)?tracked)"
|
|
370
|
+
// exclusion — that only handled "follow-ups tracked" / "follow-ups are
|
|
371
|
+
// tracked" and false-positived on natural variants. We now require the
|
|
372
|
+
// 200-char tracker-marker check to do the work uniformly.
|
|
373
|
+
{ regex: /\bfollow[- ]?ups?\b/gi, requireUnnegated: false },
|
|
374
|
+
];
|
|
375
|
+
const TRACKED_NEAR_HIT_CHARS = 200;
|
|
376
|
+
const TRACKED_MARKER = /<!--\s*tracked:\s*[A-Za-z0-9._/-]+\s*-->/;
|
|
377
|
+
const NEGATION_BEFORE = /(?:\b(?:no|non-?|un)[- ]?)$/i;
|
|
378
|
+
|
|
379
|
+
function findOrphanDeferrals(content) {
|
|
380
|
+
const orphans = [];
|
|
381
|
+
for (const { regex, requireUnnegated } of DEFERRAL_PATTERNS) {
|
|
382
|
+
regex.lastIndex = 0;
|
|
383
|
+
let m;
|
|
384
|
+
while ((m = regex.exec(content)) !== null) {
|
|
385
|
+
const start = m.index;
|
|
386
|
+
if (requireUnnegated) {
|
|
387
|
+
// Look at up to 8 chars immediately before the match. Treat
|
|
388
|
+
// matches preceded by "no ", "non-", "non ", "un" as legitimate
|
|
389
|
+
// negations (false-positive guard for "no deferrals", "non-
|
|
390
|
+
// deferred", "undeferred").
|
|
391
|
+
const before = content.slice(Math.max(0, start - 8), start);
|
|
392
|
+
if (NEGATION_BEFORE.test(before)) continue;
|
|
393
|
+
}
|
|
394
|
+
const end = Math.min(content.length, start + m[0].length + TRACKED_NEAR_HIT_CHARS);
|
|
395
|
+
const slice = content.slice(start, end);
|
|
396
|
+
if (TRACKED_MARKER.test(slice)) continue;
|
|
397
|
+
// Compute line number for the operator's diagnostic.
|
|
398
|
+
const beforeAll = content.slice(0, start);
|
|
399
|
+
const lineNo = (beforeAll.match(/\n/g) || []).length + 1;
|
|
400
|
+
orphans.push({ pattern: regex.source, match: m[0], lineNo });
|
|
401
|
+
if (orphans.length >= 16) return orphans; // cap noise (was 8; widened patterns may trip more)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return orphans;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const orphans = findOrphanDeferrals(specContent);
|
|
408
|
+
if (orphans.length > 0) {
|
|
409
|
+
const override = process.env.INSTAR_DEV_ALLOW_ORPHAN_DEFERRALS === '1';
|
|
410
|
+
if (override) {
|
|
411
|
+
// Log the override for visibility — every use is audited.
|
|
412
|
+
try {
|
|
413
|
+
const logPath = path.join(TRACES_DIR, 'orphan-deferral-overrides.jsonl');
|
|
414
|
+
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
415
|
+
fs.appendFileSync(
|
|
416
|
+
logPath,
|
|
417
|
+
JSON.stringify({
|
|
418
|
+
at: new Date().toISOString(),
|
|
419
|
+
spec,
|
|
420
|
+
orphans,
|
|
421
|
+
stagedFiles: inScopeFiles,
|
|
422
|
+
}) + '\n',
|
|
423
|
+
);
|
|
424
|
+
console.warn(
|
|
425
|
+
`[instar-dev-precommit] WARN: INSTAR_DEV_ALLOW_ORPHAN_DEFERRALS=1 — ` +
|
|
426
|
+
`${orphans.length} orphan deferral(s) in ${spec} bypassed and logged to ${path.relative(ROOT, logPath)}`,
|
|
427
|
+
);
|
|
428
|
+
} catch { /* logging is best-effort */ }
|
|
429
|
+
} else {
|
|
430
|
+
blockCommit(
|
|
431
|
+
inScopeFiles,
|
|
432
|
+
[
|
|
433
|
+
`Spec ${spec} contains ${orphans.length} orphan deferral mention(s) — each must be tracked.`,
|
|
434
|
+
'',
|
|
435
|
+
...orphans.map(o => ` • line ${o.lineNo}: "${o.match}"`),
|
|
436
|
+
'',
|
|
437
|
+
'Why this rule exists:',
|
|
438
|
+
' On 2026-05-20 a PR shipped 4 of 5 fixes for a failure class and',
|
|
439
|
+
' explicitly deferred the 5th. Two days later that exact deferral',
|
|
440
|
+
' produced the same outage. Deferrals are how regressions happen.',
|
|
441
|
+
'',
|
|
442
|
+
'How to resolve each one:',
|
|
443
|
+
' (a) Move the work into this PR (preferred — eliminates the deferral).',
|
|
444
|
+
' (b) Add a tracked marker within 200 chars of the mention:',
|
|
445
|
+
' `<!-- tracked: <id> -->` where <id> is an issue, topic, or',
|
|
446
|
+
' commitment-action ID that owns the follow-up.',
|
|
447
|
+
' (c) Rephrase the sentence so it no longer promises a deferral',
|
|
448
|
+
' (e.g. quote the historical phrase verbatim with surrounding',
|
|
449
|
+
' context that makes the non-prescriptive intent obvious).',
|
|
450
|
+
'',
|
|
451
|
+
'Emergency override (logged + audited):',
|
|
452
|
+
' INSTAR_DEV_ALLOW_ORPHAN_DEFERRALS=1 git commit ...',
|
|
453
|
+
' Use only when the deferral language is in a non-prescriptive context',
|
|
454
|
+
' (e.g. quoting an old spec). Every use lands in',
|
|
455
|
+
' .instar/instar-dev-traces/orphan-deferral-overrides.jsonl for review.',
|
|
456
|
+
].join('\n'),
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
333
461
|
// ─── Step 8: proposal-derived runbook gate (S-3) ─────────────────────────
|
|
334
462
|
// Per SELF-HEALING-REMEDIATOR-V2-SPEC §A11/§A22/§A32, runbook source files
|
|
335
463
|
// emitted by the SystemReviewer proposal pipeline must:
|