instar 1.3.588 → 1.3.590

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 (51) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +105 -2
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/LiveTestArtifactStore.d.ts +129 -0
  5. package/dist/core/LiveTestArtifactStore.d.ts.map +1 -0
  6. package/dist/core/LiveTestArtifactStore.js +184 -0
  7. package/dist/core/LiveTestArtifactStore.js.map +1 -0
  8. package/dist/core/LiveTestGate.d.ts +54 -0
  9. package/dist/core/LiveTestGate.d.ts.map +1 -0
  10. package/dist/core/LiveTestGate.js +124 -0
  11. package/dist/core/LiveTestGate.js.map +1 -0
  12. package/dist/core/LiveTestHarness.d.ts +99 -0
  13. package/dist/core/LiveTestHarness.d.ts.map +1 -0
  14. package/dist/core/LiveTestHarness.js +102 -0
  15. package/dist/core/LiveTestHarness.js.map +1 -0
  16. package/dist/core/LocalSessionOwnershipStore.d.ts +56 -0
  17. package/dist/core/LocalSessionOwnershipStore.d.ts.map +1 -0
  18. package/dist/core/LocalSessionOwnershipStore.js +130 -0
  19. package/dist/core/LocalSessionOwnershipStore.js.map +1 -0
  20. package/dist/core/OwnershipApplier.d.ts +78 -0
  21. package/dist/core/OwnershipApplier.d.ts.map +1 -0
  22. package/dist/core/OwnershipApplier.js +101 -0
  23. package/dist/core/OwnershipApplier.js.map +1 -0
  24. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  25. package/dist/core/PostUpdateMigrator.js +9 -0
  26. package/dist/core/PostUpdateMigrator.js.map +1 -1
  27. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  28. package/dist/core/devGatedFeatures.js +12 -0
  29. package/dist/core/devGatedFeatures.js.map +1 -1
  30. package/dist/core/durableOwnershipActivation.d.ts +29 -0
  31. package/dist/core/durableOwnershipActivation.d.ts.map +1 -0
  32. package/dist/core/durableOwnershipActivation.js +41 -0
  33. package/dist/core/durableOwnershipActivation.js.map +1 -0
  34. package/dist/scaffold/templates.d.ts.map +1 -1
  35. package/dist/scaffold/templates.js +2 -0
  36. package/dist/scaffold/templates.js.map +1 -1
  37. package/dist/server/AgentServer.d.ts +3 -0
  38. package/dist/server/AgentServer.d.ts.map +1 -1
  39. package/dist/server/AgentServer.js +2 -0
  40. package/dist/server/AgentServer.js.map +1 -1
  41. package/dist/server/routes.d.ts +4 -0
  42. package/dist/server/routes.d.ts.map +1 -1
  43. package/dist/server/routes.js +58 -0
  44. package/dist/server/routes.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/data/builtin-manifest.json +64 -64
  47. package/src/scaffold/templates.ts +2 -0
  48. package/upgrades/1.3.589.md +68 -0
  49. package/upgrades/1.3.590.md +21 -0
  50. package/upgrades/side-effects/live-user-channel-proof-standard.md +54 -0
  51. package/upgrades/side-effects/pool-consistent-multimachine-activation.md +39 -0
@@ -3262,6 +3262,35 @@ export function createRoutes(ctx) {
3262
3262
  }
3263
3263
  try {
3264
3264
  const verdict = await ctx.completionEvaluator.evaluate(condition, typeof transcriptTail === 'string' ? transcriptTail : '', parseStopSignals(req.body));
3265
+ // ── Live-user-channel-proof veto (spec §4) ──────────────────────────────
3266
+ // A deterministic post-check on a met:true verdict: a USER-FACING feature
3267
+ // cannot resolve "done" without a verified live-test artifact. Same shape as
3268
+ // the anti-laundering veto — filing/claiming "done" never buys the exit.
3269
+ // dry-run/warn COMPUTE the veto (telemetry) but never override; only veto-mode
3270
+ // overrides met:true → met:false (the safe direction — keep working).
3271
+ if (verdict.met && ctx.liveTestGate) {
3272
+ try {
3273
+ const body = (req.body ?? {});
3274
+ const featureId = typeof body.featureId === 'string' && body.featureId
3275
+ ? body.featureId
3276
+ : condition.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'autonomous-goal';
3277
+ const userFacing = typeof body.userFacing === 'boolean' ? body.userFacing : undefined;
3278
+ const gate = ctx.liveTestGate.evaluate({ featureId, userFacing, goalText: condition, mode: ctx.liveTestGateMode });
3279
+ if (gate.outcome !== 'allow') {
3280
+ if (gate.blocks) {
3281
+ res.json({ met: false, reason: `live-test gate: ${gate.reason}`, liveTestGate: { outcome: gate.outcome, mode: gate.mode, overrode: true } });
3282
+ return;
3283
+ }
3284
+ // dry-run / warn: surface the would-block but honor the original verdict.
3285
+ res.json({ ...verdict, liveTestGate: { outcome: gate.outcome, mode: gate.mode, wouldBlock: gate.wouldBlock, reason: gate.reason, overrode: false } });
3286
+ return;
3287
+ }
3288
+ }
3289
+ catch {
3290
+ // @silent-fallback-ok — a gate error must never trap a genuine completion
3291
+ // (the completion judge is the primary authority); fall through to the verdict.
3292
+ }
3293
+ }
3265
3294
  res.json(verdict);
3266
3295
  }
3267
3296
  catch (err) {
@@ -11053,8 +11082,37 @@ export function createRoutes(ctx) {
11053
11082
  // next real message, so a CAS failure must never fail the transfer itself.
11054
11083
  // `placedOwnership:false` is reported to the caller.
11055
11084
  }
11085
+ // §7.4 (live-user-channel-proof spec): surface whether the seat ACTUALLY moved,
11086
+ // not just ok:true. The 2026-06-15 bug was `ok:true` with the topic never moving —
11087
+ // a lie-by-omission. The honest signal is the post-transfer owner: did the target
11088
+ // end up the active owner? A real transfer that did NOT land that is reported
11089
+ // `seatMoved:false` + a reason, so a caller (or the live-test harness) can never
11090
+ // read `ok` as `moved`.
11091
+ let seatMoved;
11092
+ let seatMoveReason;
11093
+ {
11094
+ const ownerNow = ctx.sessionOwnershipRegistry.ownerOf(topicId);
11095
+ const post = ctx.sessionOwnershipRegistry.read(topicId);
11096
+ if (plan.action === 'noop') {
11097
+ seatMoved = true; // already-there / no move required — the seat is at the target
11098
+ }
11099
+ else if (post?.status === 'active' && ownerNow === target) {
11100
+ seatMoved = true; // the target is the confirmed active owner — a real move
11101
+ }
11102
+ else {
11103
+ seatMoved = false;
11104
+ seatMoveReason =
11105
+ drainLeg.attempted && drainLeg.ok === false
11106
+ ? 'drain failed — the seat did not move (topic stays whole on its current machine)'
11107
+ : 'ownership did not transfer to the target (the pin is set, but the target is not the active owner)';
11108
+ }
11109
+ }
11056
11110
  res.json({
11057
11111
  ok: true,
11112
+ // seatMoved is the load-bearing honesty field — ok:true means "request processed",
11113
+ // seatMoved means "the conversation actually runs on the target now".
11114
+ seatMoved,
11115
+ ...(seatMoveReason ? { seatMoveReason } : {}),
11058
11116
  topicId,
11059
11117
  targetMachine: target,
11060
11118
  targetNickname: ctx.machinePoolRegistry?.getCapacity(target)?.nickname ?? null,