instar 1.3.588 → 1.3.589
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +93 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/core/LiveTestArtifactStore.d.ts +129 -0
- package/dist/core/LiveTestArtifactStore.d.ts.map +1 -0
- package/dist/core/LiveTestArtifactStore.js +184 -0
- package/dist/core/LiveTestArtifactStore.js.map +1 -0
- package/dist/core/LiveTestGate.d.ts +54 -0
- package/dist/core/LiveTestGate.d.ts.map +1 -0
- package/dist/core/LiveTestGate.js +124 -0
- package/dist/core/LiveTestGate.js.map +1 -0
- package/dist/core/LiveTestHarness.d.ts +99 -0
- package/dist/core/LiveTestHarness.d.ts.map +1 -0
- package/dist/core/LiveTestHarness.js +102 -0
- package/dist/core/LiveTestHarness.js.map +1 -0
- package/dist/core/LocalSessionOwnershipStore.d.ts +56 -0
- package/dist/core/LocalSessionOwnershipStore.d.ts.map +1 -0
- package/dist/core/LocalSessionOwnershipStore.js +130 -0
- package/dist/core/LocalSessionOwnershipStore.js.map +1 -0
- package/dist/core/OwnershipApplier.d.ts +78 -0
- package/dist/core/OwnershipApplier.d.ts.map +1 -0
- package/dist/core/OwnershipApplier.js +101 -0
- package/dist/core/OwnershipApplier.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +9 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +12 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +3 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +4 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +58 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +2 -0
- package/upgrades/1.3.589.md +68 -0
- package/upgrades/side-effects/live-user-channel-proof-standard.md +54 -0
package/dist/server/routes.js
CHANGED
|
@@ -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,
|