instar 1.3.1620 → 1.3.1621
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 +6 -0
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +56 -9
- package/dist/commands/server.js.map +1 -1
- package/dist/core/TopicProfileOrchestrator.d.ts +4 -0
- package/dist/core/TopicProfileOrchestrator.d.ts.map +1 -1
- package/dist/core/TopicProfileOrchestrator.js +14 -1
- package/dist/core/TopicProfileOrchestrator.js.map +1 -1
- package/dist/core/TopicSpawnBriefStore.d.ts +48 -0
- package/dist/core/TopicSpawnBriefStore.d.ts.map +1 -0
- package/dist/core/TopicSpawnBriefStore.js +107 -0
- package/dist/core/TopicSpawnBriefStore.js.map +1 -0
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/native/instar-desktop-host +0 -0
- package/dist/server/routes.d.ts +3 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +52 -10
- package/dist/server/routes.js.map +1 -1
- package/dist/server/sessionSpawnTopicBinding.d.ts +26 -0
- package/dist/server/sessionSpawnTopicBinding.d.ts.map +1 -1
- package/dist/server/sessionSpawnTopicBinding.js +50 -0
- package/dist/server/sessionSpawnTopicBinding.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +46 -46
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/upgrades/1.3.1621.md +27 -0
- package/upgrades/eli16/profile-restart-keeps-spawn-brief.md +24 -0
- package/upgrades/side-effects/profile-restart-keeps-spawn-brief.md +91 -0
|
@@ -33,6 +33,12 @@ spawnOpts?: {
|
|
|
33
33
|
* relay block) and no initial message, exactly what the raw
|
|
34
34
|
* spawnInteractiveSession(undefined, …) path injected before. */
|
|
35
35
|
silentStart?: boolean;
|
|
36
|
+
/** The prompt the replaced session was originally started with (direct
|
|
37
|
+
* spawn route). It is not in the thread history, so a CONTINUATION
|
|
38
|
+
* respawn (topic-profile re-apply) includes it — otherwise the new
|
|
39
|
+
* session sees nothing in flight and idles. Ignored when a user message
|
|
40
|
+
* drives the spawn. */
|
|
41
|
+
carriedBrief?: string;
|
|
36
42
|
}): Promise<string>;
|
|
37
43
|
/**
|
|
38
44
|
* Resolve the hub-intent classifier deps (Conversion #3,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/server.js
CHANGED
|
@@ -88,6 +88,7 @@ import { NewTopicDefaultStore, evaluateSessionPoolLocalClaim, createSpawnForTopi
|
|
|
88
88
|
import { parseDashboardCreatePayload, safeMachineLabel, createDashboardCreateStartRunner } from '../core/dashboardMachineChoice.js';
|
|
89
89
|
import { slugifyChannelName } from '../messaging/slack/sanitize.js';
|
|
90
90
|
import { TopicProfileOrchestrator, resolvedToApplied, } from '../core/TopicProfileOrchestrator.js';
|
|
91
|
+
import { TopicSpawnBriefStore, formatCarriedBriefBlock } from '../core/TopicSpawnBriefStore.js';
|
|
91
92
|
import { CodexResumeMap } from '../core/CodexResumeMap.js';
|
|
92
93
|
import { resolveStageBProductionActivation } from '../core/StageBActivationGate.js';
|
|
93
94
|
import { createInboundDeliveryTransferHandler, createInboundDeliveryTransferStep, writeStageCActivationLease } from '../core/CodexLifecycleProductionComposition.js';
|
|
@@ -880,6 +881,10 @@ let _topicProfileCarrier = null;
|
|
|
880
881
|
* respawn phase — the spawn chokepoint must not double-report the failure to
|
|
881
882
|
* the §10.4 breaker (the orchestrator records its own spawn outcome). */
|
|
882
883
|
const _orchestratorSpawnInFlight = new Set();
|
|
884
|
+
/** Direct-spawn brief store (set at server boot). spawnSessionForTopic clears
|
|
885
|
+
* a topic's brief on any spawn the orchestrator did not start, so an old
|
|
886
|
+
* task never reaches a later session that reuses the same tmux name. */
|
|
887
|
+
let _topicSpawnBriefsRef = null;
|
|
883
888
|
/** §5.3 "possibly stale" read disclosure — once per (topic, process). */
|
|
884
889
|
const _pendingPullStaleDisclosed = new Set();
|
|
885
890
|
/** Default framework for sessions when no per-topic override is set. */
|
|
@@ -1111,6 +1116,10 @@ accountSwap,
|
|
|
1111
1116
|
* worktree work resumes in ITS tree). Omitted = module project dir. */
|
|
1112
1117
|
spawnOpts) {
|
|
1113
1118
|
const silentStart = spawnOpts?.silentStart === true;
|
|
1119
|
+
const carriedBriefBlock = !silentStart && typeof spawnOpts?.carriedBrief === 'string' && spawnOpts.carriedBrief.length > 0
|
|
1120
|
+
&& !(typeof latestMessage === 'string' && latestMessage.length > 0)
|
|
1121
|
+
? formatCarriedBriefBlock(spawnOpts.carriedBrief)
|
|
1122
|
+
: null;
|
|
1114
1123
|
const hasLatestMessage = typeof latestMessage === 'string' && latestMessage.length > 0;
|
|
1115
1124
|
const msg = hasLatestMessage ? latestMessage : 'Session started — send a message to continue.';
|
|
1116
1125
|
// If memory is elevated/critical and we have the reaper, try to free memory
|
|
@@ -1279,6 +1288,9 @@ spawnOpts) {
|
|
|
1279
1288
|
else {
|
|
1280
1289
|
console.warn(`[telegram→session] Open commitments for topic ${topicId} unavailable for the handoff instruction (tracker not wired)`);
|
|
1281
1290
|
}
|
|
1291
|
+
if (carriedBriefBlock) {
|
|
1292
|
+
parts.push(carriedBriefBlock, ``);
|
|
1293
|
+
}
|
|
1282
1294
|
parts.push(buildHandoffContinuationInstruction(openCommitments));
|
|
1283
1295
|
}
|
|
1284
1296
|
bootstrapMessage = parts.join('\n');
|
|
@@ -1295,13 +1307,8 @@ spawnOpts) {
|
|
|
1295
1307
|
newSessionParts.push(userContextBlock);
|
|
1296
1308
|
newSessionParts.push(``);
|
|
1297
1309
|
}
|
|
1298
|
-
newSessionParts.push(`[telegram:${topicId}] ${msg}`);
|
|
1299
|
-
|
|
1300
|
-
bootstrapMessage = newSessionParts.join('\n');
|
|
1301
|
-
}
|
|
1302
|
-
else {
|
|
1303
|
-
bootstrapMessage = `[telegram:${topicId}] ${msg}`;
|
|
1304
|
-
}
|
|
1310
|
+
newSessionParts.push(carriedBriefBlock ? `[telegram:${topicId}]\n${carriedBriefBlock}` : `[telegram:${topicId}] ${msg}`);
|
|
1311
|
+
bootstrapMessage = newSessionParts.join('\n');
|
|
1305
1312
|
}
|
|
1306
1313
|
// Resolve the FULL topic profile EARLY (Topic Profile §5.2 — the single
|
|
1307
1314
|
// resolution point: framework + model + thinking mode, with the read-time
|
|
@@ -1432,6 +1439,18 @@ spawnOpts) {
|
|
|
1432
1439
|
if (resumeSessionId) {
|
|
1433
1440
|
_topicResumeMap?.remove(topicId);
|
|
1434
1441
|
}
|
|
1442
|
+
// A spawn the orchestrator did not start is a new session taking over the
|
|
1443
|
+
// topic (a natural or user-driven spawn): the previous session's direct-spawn
|
|
1444
|
+
// brief no longer applies. Clearing it here is what keeps a later profile
|
|
1445
|
+
// respawn of THIS session (same tmux name) from carrying a finished task.
|
|
1446
|
+
if (_topicSpawnBriefsRef && !_orchestratorSpawnInFlight.has(String(topicId))) {
|
|
1447
|
+
try {
|
|
1448
|
+
_topicSpawnBriefsRef.clear(topicId);
|
|
1449
|
+
}
|
|
1450
|
+
catch (err) {
|
|
1451
|
+
console.warn(`[spawnSessionForTopic] could not clear spawn brief for topic ${topicId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1435
1454
|
// TOPIC-PROFILE-SPEC §10.4 — record the successful spawn so the §10.4 breaker
|
|
1436
1455
|
// resets + the codex same-cwd fence window opens. SKIPPED when the orchestrator
|
|
1437
1456
|
// initiated THIS respawn: it records its own spawn outcome (the spawn port),
|
|
@@ -28549,6 +28568,11 @@ export async function startServer(options) {
|
|
|
28549
28568
|
// into AgentServer → routes, so the orchestrator + carrier (which late-bind
|
|
28550
28569
|
// off the just-constructed AgentServer's governors / the mesh block) are
|
|
28551
28570
|
// attached to THIS object after construction and reach the routes live.
|
|
28571
|
+
// Direct-spawn briefs (POST /sessions/spawn with a topic): carried into a
|
|
28572
|
+
// CONTINUATION profile respawn of the same session, since the brief is
|
|
28573
|
+
// not in the topic's chat history.
|
|
28574
|
+
const _topicSpawnBriefs = new TopicSpawnBriefStore(config.stateDir);
|
|
28575
|
+
_topicSpawnBriefsRef = _topicSpawnBriefs;
|
|
28552
28576
|
const _topicProfileCtx = (_topicProfileStore && _topicProfileResolver && _topicProfileWriteSurface && _topicProfileConfirmSlots)
|
|
28553
28577
|
? {
|
|
28554
28578
|
store: _topicProfileStore,
|
|
@@ -28559,6 +28583,7 @@ export async function startServer(options) {
|
|
|
28559
28583
|
carrier: _topicProfileCarrier,
|
|
28560
28584
|
// dashboard-door-model-controls (§3.2/§3.3) — the dashboard create path.
|
|
28561
28585
|
newTopicDefault: new NewTopicDefaultStore(config.stateDir),
|
|
28586
|
+
spawnBriefs: _topicSpawnBriefs,
|
|
28562
28587
|
audit: (event) => { appendTopicProfileAudit(config.stateDir, event); },
|
|
28563
28588
|
discloseCreationSeed: async (topicKey, text) => {
|
|
28564
28589
|
if (!telegram)
|
|
@@ -30254,7 +30279,7 @@ export async function startServer(options) {
|
|
|
30254
30279
|
// supposed to be a no-op.
|
|
30255
30280
|
return sessionManager.killSessionByTmuxName(sessionName);
|
|
30256
30281
|
},
|
|
30257
|
-
spawn: async (topicKey, _resolved,
|
|
30282
|
+
spawn: async (topicKey, _resolved, directive) => {
|
|
30258
30283
|
// The orchestrator already killed; respawn re-resolves the (now
|
|
30259
30284
|
// updated) pin via spawnSessionForTopic and picks up the resume id
|
|
30260
30285
|
// from the resume map. We mark the spawn in-flight so the spawn-path
|
|
@@ -30263,9 +30288,31 @@ export async function startServer(options) {
|
|
|
30263
30288
|
if (!Number.isFinite(n) || !telegram)
|
|
30264
30289
|
return { ok: false, failureClass: 'unknown' };
|
|
30265
30290
|
const topicName = telegram.getTopicName(n) || `topic-${n}`;
|
|
30291
|
+
// A CONTINUATION respawn rebuilds context from the thread history,
|
|
30292
|
+
// which does not hold a direct-spawn brief — carry the replaced
|
|
30293
|
+
// session's brief so the new session keeps its task. A resume
|
|
30294
|
+
// respawn keeps the whole conversation, so it needs no carry.
|
|
30295
|
+
let carriedBrief;
|
|
30296
|
+
try {
|
|
30297
|
+
carriedBrief = directive.method === 'continuation'
|
|
30298
|
+
? (_topicSpawnBriefs.getForSession(n, directive.replacedSessionName)?.prompt ?? undefined)
|
|
30299
|
+
: undefined;
|
|
30300
|
+
}
|
|
30301
|
+
catch { /* @silent-fallback-ok: an unreadable brief degrades to today's history-only continuation; the respawn itself must not fail on it */
|
|
30302
|
+
carriedBrief = undefined;
|
|
30303
|
+
}
|
|
30266
30304
|
_orchestratorSpawnInFlight.add(topicKey);
|
|
30267
30305
|
try {
|
|
30268
|
-
const spawnedName = await spawnSessionForTopic(sessionManager, telegram, topicName, n, undefined, topicMemory, undefined, undefined, undefined, { awaitInitialInjection: true });
|
|
30306
|
+
const spawnedName = await spawnSessionForTopic(sessionManager, telegram, topicName, n, undefined, topicMemory, undefined, undefined, undefined, { awaitInitialInjection: true, ...(carriedBrief ? { carriedBrief } : {}) });
|
|
30307
|
+
if (directive.replacedSessionName) {
|
|
30308
|
+
try {
|
|
30309
|
+
_topicSpawnBriefs.rebind(n, directive.replacedSessionName, spawnedName);
|
|
30310
|
+
}
|
|
30311
|
+
catch { /* @silent-fallback-ok: a failed re-key only means a LATER profile respawn of the new session will not carry the brief again */ }
|
|
30312
|
+
}
|
|
30313
|
+
if (carriedBrief) {
|
|
30314
|
+
appendTopicProfileAudit(config.stateDir, { type: 'respawn-brief-carried', topic: topicKey, chars: carriedBrief.length });
|
|
30315
|
+
}
|
|
30269
30316
|
const spawned = sessionManager.listRunningSessions()
|
|
30270
30317
|
.find((session) => session.tmuxSession === spawnedName);
|
|
30271
30318
|
return {
|