instar 1.3.962 → 1.3.963

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.
@@ -77,6 +77,7 @@ import { runDecisionGradingPass } from '../core/decisionGradingPass.js';
77
77
  import { annotateDecisionOutcome, decisionQualityRecordingLive, getDecisionAnnotationRejectionCounters } from '../core/DecisionQualityRecorderImpl.js';
78
78
  import { annotateCompletionRealcheck } from '../core/AutonomousRealCheckAnnotator.js';
79
79
  import { DP_COMPLETION_EVALUATE, DP_MESSAGING_TONE_GATE, PROVENANCE_COVERAGE, backlogTrackerExists, findWiredWithoutGraders } from '../data/provenanceCoverage.js';
80
+ import { CheckInReminderReconciler } from '../monitoring/CheckInReminderReconciler.js';
80
81
  import { RemoteCloseAudit } from '../core/RemoteCloseAudit.js';
81
82
  import { RemoteAckStore } from '../core/RemoteAckStore.js';
82
83
  import { FailureLedger } from '../monitoring/FailureLedger.js';
@@ -24319,6 +24320,111 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
24319
24320
  * counter is the rollout hard-stop signal. MUST be registered before
24320
24321
  * `/commitments/:id` or Express routes the literal here to the :id handler.
24321
24322
  */
24323
+ /**
24324
+ * POST /commitments/check-in-reminder/pass — run ONE check-in reminder pass
24325
+ * (ACT-724; docs/specs/dated-commitment-reminder.md).
24326
+ *
24327
+ * Driven by the `commitment-checkin-reminder` built-in job. Idempotent: the
24328
+ * `checkInReminderSentAt` stamp means a re-run sends nothing, so a retried or
24329
+ * duplicated trigger is safe.
24330
+ */
24331
+ router.post('/commitments/check-in-reminder/pass', async (_req, res) => {
24332
+ const cfg = ctx.config.commitments?.checkInReminder;
24333
+ const enabled = resolveDevAgentGate(cfg?.enabled, ctx.config);
24334
+ if (!enabled || !ctx.commitmentTracker) {
24335
+ res.status(503).json({ error: 'check-in-reminder-not-enabled' });
24336
+ return;
24337
+ }
24338
+ // Deterministic delivery — NOT the tone-gated path. A reminder must not be
24339
+ // holdable by a gate that fails closed; the text is a fixed template with
24340
+ // no agent prose, so there is nothing for a tone gate to judge.
24341
+ const telegram = ctx.telegram;
24342
+ const dryRun = cfg?.dryRun !== false;
24343
+ // A transport is required only to SEND. A dry run sends nothing, so demanding
24344
+ // one would make the soak — the whole point of the dark window — impossible
24345
+ // on an agent with no messaging configured, and would report the feature as
24346
+ // unavailable when it is merely quiet.
24347
+ if (!telegram && !dryRun) {
24348
+ res.status(503).json({ error: 'no-delivery-transport' });
24349
+ return;
24350
+ }
24351
+ try {
24352
+ const reconciler = new CheckInReminderReconciler({
24353
+ tracker: ctx.commitmentTracker,
24354
+ send: async (topicId, text) => {
24355
+ if (!telegram)
24356
+ throw new Error('no-delivery-transport');
24357
+ // Route the send through the SAME durable content dedup the
24358
+ // /telegram/reply route uses.
24359
+ //
24360
+ // This is load-bearing and was nearly a false claim: the reconciler
24361
+ // sends first and stamps after, so a crash in between re-sends on
24362
+ // the next pass. The spec justified that by saying "the relay
24363
+ // absorbs the duplicate" — but the dedup lives in the reply ROUTE,
24364
+ // and `sendToTopic` bypasses it entirely. Asserting the mitigation
24365
+ // without wiring it would have been a safety property that existed
24366
+ // only in the comment. (Caught in review round 2, 2026-07-25.)
24367
+ //
24368
+ // A duplicate is treated as SUCCESS-equivalent: the user already has
24369
+ // this exact reminder, so the send is complete and the caller may
24370
+ // stamp. Treating it as a failure would retry-loop until the window
24371
+ // expired and then genuinely double-send.
24372
+ if (outboundContentDedup.isDuplicate(topicId, text)) {
24373
+ return { ok: true, suppressedDuplicate: true };
24374
+ }
24375
+ if (!outboundContentDedup.tryReserve(topicId, text)) {
24376
+ return { ok: true, suppressedDuplicate: true };
24377
+ }
24378
+ try {
24379
+ const r = await telegram.sendToTopic(topicId, text);
24380
+ outboundContentDedup.record(topicId, text);
24381
+ return r;
24382
+ }
24383
+ catch (err) {
24384
+ // Release so a genuine transport failure is retried rather than
24385
+ // suppressed as a "duplicate" on the next pass.
24386
+ outboundContentDedup.releaseReservation(topicId, text);
24387
+ throw err;
24388
+ }
24389
+ },
24390
+ }, {
24391
+ enabled: true,
24392
+ // dryRun defaults TRUE: the graduated state is an explicit operator
24393
+ // decision, never something that arrives by omission.
24394
+ dryRun,
24395
+ ...(typeof cfg?.maxPerPass === 'number' ? { maxPerPass: cfg.maxPerPass } : {}),
24396
+ });
24397
+ const report = await reconciler.runPass();
24398
+ res.json(report);
24399
+ }
24400
+ catch (err) {
24401
+ res.status(500).json({ error: 'check-in-reminder-pass-failed', detail: String(err) });
24402
+ }
24403
+ });
24404
+ /** GET /commitments/check-in-reminder — read-only posture + the dated backlog. */
24405
+ router.get('/commitments/check-in-reminder', (_req, res) => {
24406
+ const cfg = ctx.config.commitments?.checkInReminder;
24407
+ const enabled = resolveDevAgentGate(cfg?.enabled, ctx.config);
24408
+ if (!enabled || !ctx.commitmentTracker) {
24409
+ res.status(503).json({ error: 'check-in-reminder-not-enabled' });
24410
+ return;
24411
+ }
24412
+ const all = ctx.commitmentTracker.getAll();
24413
+ const dated = all.filter((c) => !!c.checkInAt);
24414
+ res.json({
24415
+ enabled: true,
24416
+ dryRun: cfg?.dryRun !== false,
24417
+ datedCount: dated.length,
24418
+ // Surfaced deliberately: an exhausted reminder is a promise the user did
24419
+ // NOT receive, and it must be visible rather than buried in a stamp.
24420
+ undelivered: dated
24421
+ .filter((c) => !!c.checkInReminderFailedAt)
24422
+ .map((c) => ({ id: c.id, topicId: c.topicId, checkInAt: c.checkInAt, attempts: c.checkInReminderAttempts ?? 0 })),
24423
+ pending: dated
24424
+ .filter((c) => !c.checkInReminderSentAt && !c.checkInReminderFailedAt)
24425
+ .map((c) => ({ id: c.id, topicId: c.topicId, checkInAt: c.checkInAt })),
24426
+ });
24427
+ });
24322
24428
  router.get('/commitments/escalation-metrics', (_req, res) => {
24323
24429
  if (!ctx.commitmentTracker) {
24324
24430
  res.json({ enabled: false });