wicked-crew 0.7.38 → 0.7.40
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/api/chat-scope.d.ts +37 -1
- package/dist/api/chat-scope.d.ts.map +1 -1
- package/dist/api/chat-scope.js +133 -9
- package/dist/api/chat-scope.js.map +1 -1
- package/dist/api/chat-transcripts.d.ts +45 -2
- package/dist/api/chat-transcripts.d.ts.map +1 -1
- package/dist/api/chat-transcripts.js +89 -5
- package/dist/api/chat-transcripts.js.map +1 -1
- package/dist/api/routes.d.ts +70 -10
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +206 -20
- package/dist/api/routes.js.map +1 -1
- package/dist/api/run-timing-index.d.ts +22 -0
- package/dist/api/run-timing-index.d.ts.map +1 -1
- package/dist/api/run-timing-index.js +63 -0
- package/dist/api/run-timing-index.js.map +1 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +120 -17
- package/dist/api/server.js.map +1 -1
- package/dist/api/testing.d.ts +26 -0
- package/dist/api/testing.d.ts.map +1 -1
- package/dist/api/testing.js +48 -2
- package/dist/api/testing.js.map +1 -1
- package/dist/api/worktree-sweep.d.ts +12 -0
- package/dist/api/worktree-sweep.d.ts.map +1 -0
- package/dist/api/worktree-sweep.js +41 -0
- package/dist/api/worktree-sweep.js.map +1 -0
- package/dist/cli/bearer.d.ts +8 -0
- package/dist/cli/bearer.d.ts.map +1 -0
- package/dist/cli/bearer.js +16 -0
- package/dist/cli/bearer.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +21 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapter.d.ts +11 -2
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +23 -4
- package/dist/core/adapter.js.map +1 -1
- package/dist/interactive/demo-events.d.ts +3 -0
- package/dist/interactive/demo-events.d.ts.map +1 -1
- package/dist/interactive/demo-events.js +14 -1
- package/dist/interactive/demo-events.js.map +1 -1
- package/dist/interactive/doc-grounding.d.ts +6 -0
- package/dist/interactive/doc-grounding.d.ts.map +1 -1
- package/dist/interactive/doc-grounding.js +4 -0
- package/dist/interactive/doc-grounding.js.map +1 -1
- package/dist/interactive/draft-events.d.ts +4 -0
- package/dist/interactive/draft-events.d.ts.map +1 -1
- package/dist/interactive/draft-events.js +12 -2
- package/dist/interactive/draft-events.js.map +1 -1
- package/dist/interactive/proxy-routes.d.ts +14 -0
- package/dist/interactive/proxy-routes.d.ts.map +1 -1
- package/dist/interactive/proxy-routes.js +98 -3
- package/dist/interactive/proxy-routes.js.map +1 -1
- package/dist/interactive/repo-snapshot.d.ts.map +1 -1
- package/dist/interactive/repo-snapshot.js +3 -2
- package/dist/interactive/repo-snapshot.js.map +1 -1
- package/dist/projects/graph.d.ts +11 -0
- package/dist/projects/graph.d.ts.map +1 -1
- package/dist/projects/graph.js +12 -0
- package/dist/projects/graph.js.map +1 -1
- package/dist/qe/author-workflow.d.ts +2 -0
- package/dist/qe/author-workflow.d.ts.map +1 -1
- package/dist/qe/author-workflow.js +55 -12
- package/dist/qe/author-workflow.js.map +1 -1
- package/dist/skills/phase-skill-gaps.d.ts +108 -0
- package/dist/skills/phase-skill-gaps.d.ts.map +1 -0
- package/dist/skills/phase-skill-gaps.js +199 -0
- package/dist/skills/phase-skill-gaps.js.map +1 -0
- package/dist/skills/runtime.d.ts +1 -1
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +2 -1
- package/dist/skills/runtime.js.map +1 -1
- package/dist/studio/assets/index-Bg7Z3BR-.css +32 -0
- package/dist/studio/assets/index-BvOFMjf9.js +554 -0
- package/dist/studio/index.html +2 -2
- package/dist/studio/testid-inventory.json +100 -10
- package/endpoint-manifest.json +1 -1
- package/package.json +3 -3
- package/dist/studio/assets/index-C12tVMLX.css +0 -32
- package/dist/studio/assets/index-DFkL6Rzf.js +0 -546
|
@@ -20,6 +20,14 @@ export declare class RunTimingIndex {
|
|
|
20
20
|
private readonly runToCreatedAt;
|
|
21
21
|
/** runId → terminal instant, unix SECONDS (`AgentSession.ended_at`; api-types 0.38.0, crew#496). */
|
|
22
22
|
private readonly runToEndedAt;
|
|
23
|
+
/** runId → launch channel (`AgentSession.channel`; crew#632). */
|
|
24
|
+
private readonly runToChannel;
|
|
25
|
+
/** runId → launch actor string (`AgentSession.launch_actor`; crew#632). */
|
|
26
|
+
private readonly runToLaunchActor;
|
|
27
|
+
/** runId → warm seat count at chat-promotion time (`AgentSession.chat_seat_count`; crew#641/#642). */
|
|
28
|
+
private readonly runToChatSeatCount;
|
|
29
|
+
/** runId → whether the promoted chat was graph-grounded (`AgentSession.chat_grounded`; crew#641/#642). */
|
|
30
|
+
private readonly runToChatGrounded;
|
|
23
31
|
/**
|
|
24
32
|
* Consume pre-read `run.launched` entries — the seam that lets `createServer` feed this index
|
|
25
33
|
* from the ONE `readAll({ action: 'run.launched' })` it already runs for `RetryIndex` +
|
|
@@ -42,6 +50,20 @@ export declare class RunTimingIndex {
|
|
|
42
50
|
set(runId: string, launchedAtMillis: number): void;
|
|
43
51
|
/** The run's launch time in unix SECONDS, or `undefined` (the DTO spells that as an ABSENT field). */
|
|
44
52
|
createdAtFor(runId: string): number | undefined;
|
|
53
|
+
/** Record the launch channel for a run (crew#632). */
|
|
54
|
+
setChannel(runId: string, channel: 'studio' | 'cli' | 'api'): void;
|
|
55
|
+
/** The launch channel, or `undefined` (ABSENT when the launch did not name one). */
|
|
56
|
+
channelFor(runId: string): 'studio' | 'cli' | 'api' | undefined;
|
|
57
|
+
/** Record the launch actor string for a run (crew#632). */
|
|
58
|
+
setLaunchActor(runId: string, actor: string): void;
|
|
59
|
+
/** The launch actor string, or `undefined` (ABSENT when the launch did not name one). */
|
|
60
|
+
launchActorFor(runId: string): string | undefined;
|
|
61
|
+
/** Record the warm seat count and grounding state at chat-promotion time (crew#641/#642). */
|
|
62
|
+
setChatPromotion(runId: string, seatCount: number, grounded: boolean): void;
|
|
63
|
+
/** The warm seat count at chat-promotion, or `undefined` (ABSENT when not a chat-promoted run). */
|
|
64
|
+
chatSeatCountFor(runId: string): number | undefined;
|
|
65
|
+
/** Whether the chat was graph-grounded at launch, or `undefined` (ABSENT when not chat-promoted). */
|
|
66
|
+
chatGroundedFor(runId: string): boolean | undefined;
|
|
45
67
|
/**
|
|
46
68
|
* Consume pre-read `run.ended` entries (crew#496 / studio#230) — the daemon records one when it
|
|
47
69
|
* sees a run's terminal frame (`sessionCompleted` | `sessionFailed` | `runCancelled`). The run's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-timing-index.d.ts","sourceRoot":"","sources":["../../src/api/run-timing-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW1D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;
|
|
1
|
+
{"version":3,"file":"run-timing-index.d.ts","sourceRoot":"","sources":["../../src/api/run-timing-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW1D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+C;IAC5E,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAChE,0GAA0G;IAC1G,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA8B;IAEhE;;;;OAIG;IACH,wBAAwB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI;IAoBrD;;;;;;OAMG;IACG,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1E;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI;IAIlD,sGAAsG;IACtG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C,sDAAsD;IACtD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;IAIlE,oFAAoF;IACpF,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS;IAI/D,2DAA2D;IAC3D,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIlD,yFAAyF;IACzF,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD,6FAA6F;IAC7F,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAK3E,mGAAmG;IACnG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAInD,qGAAqG;IACrG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAInD;;;;;;;;OAQG;IACH,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI;IAOpD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAKpD;;iCAE6B;IAC7B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAG9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,EACf,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAaR"}
|
|
@@ -26,6 +26,14 @@ export class RunTimingIndex {
|
|
|
26
26
|
runToCreatedAt = new Map();
|
|
27
27
|
/** runId → terminal instant, unix SECONDS (`AgentSession.ended_at`; api-types 0.38.0, crew#496). */
|
|
28
28
|
runToEndedAt = new Map();
|
|
29
|
+
/** runId → launch channel (`AgentSession.channel`; crew#632). */
|
|
30
|
+
runToChannel = new Map();
|
|
31
|
+
/** runId → launch actor string (`AgentSession.launch_actor`; crew#632). */
|
|
32
|
+
runToLaunchActor = new Map();
|
|
33
|
+
/** runId → warm seat count at chat-promotion time (`AgentSession.chat_seat_count`; crew#641/#642). */
|
|
34
|
+
runToChatSeatCount = new Map();
|
|
35
|
+
/** runId → whether the promoted chat was graph-grounded (`AgentSession.chat_grounded`; crew#641/#642). */
|
|
36
|
+
runToChatGrounded = new Map();
|
|
29
37
|
/**
|
|
30
38
|
* Consume pre-read `run.launched` entries — the seam that lets `createServer` feed this index
|
|
31
39
|
* from the ONE `readAll({ action: 'run.launched' })` it already runs for `RetryIndex` +
|
|
@@ -36,6 +44,23 @@ export class RunTimingIndex {
|
|
|
36
44
|
if (typeof entry.runId === 'string' && typeof entry.ts === 'number' && entry.ts > 0) {
|
|
37
45
|
this.runToCreatedAt.set(entry.runId, toSeconds(entry.ts));
|
|
38
46
|
}
|
|
47
|
+
const runId = entry.runId;
|
|
48
|
+
if (typeof runId !== 'string')
|
|
49
|
+
continue;
|
|
50
|
+
const detail = entry.detail;
|
|
51
|
+
const ch = detail?.['channel'];
|
|
52
|
+
if (ch === 'studio' || ch === 'cli' || ch === 'api')
|
|
53
|
+
this.runToChannel.set(runId, ch);
|
|
54
|
+
const la = detail?.['actor'];
|
|
55
|
+
if (typeof la === 'string' && la.length > 0)
|
|
56
|
+
this.runToLaunchActor.set(runId, la);
|
|
57
|
+
// crew#641/#642 (item 5): chat promotion provenance.
|
|
58
|
+
const sc = detail?.['chatSeatCount'];
|
|
59
|
+
if (typeof sc === 'number')
|
|
60
|
+
this.runToChatSeatCount.set(runId, sc);
|
|
61
|
+
const cg = detail?.['chatGrounded'];
|
|
62
|
+
if (typeof cg === 'boolean')
|
|
63
|
+
this.runToChatGrounded.set(runId, cg);
|
|
39
64
|
}
|
|
40
65
|
}
|
|
41
66
|
/**
|
|
@@ -65,6 +90,35 @@ export class RunTimingIndex {
|
|
|
65
90
|
createdAtFor(runId) {
|
|
66
91
|
return this.runToCreatedAt.get(runId);
|
|
67
92
|
}
|
|
93
|
+
/** Record the launch channel for a run (crew#632). */
|
|
94
|
+
setChannel(runId, channel) {
|
|
95
|
+
this.runToChannel.set(runId, channel);
|
|
96
|
+
}
|
|
97
|
+
/** The launch channel, or `undefined` (ABSENT when the launch did not name one). */
|
|
98
|
+
channelFor(runId) {
|
|
99
|
+
return this.runToChannel.get(runId);
|
|
100
|
+
}
|
|
101
|
+
/** Record the launch actor string for a run (crew#632). */
|
|
102
|
+
setLaunchActor(runId, actor) {
|
|
103
|
+
this.runToLaunchActor.set(runId, actor);
|
|
104
|
+
}
|
|
105
|
+
/** The launch actor string, or `undefined` (ABSENT when the launch did not name one). */
|
|
106
|
+
launchActorFor(runId) {
|
|
107
|
+
return this.runToLaunchActor.get(runId);
|
|
108
|
+
}
|
|
109
|
+
/** Record the warm seat count and grounding state at chat-promotion time (crew#641/#642). */
|
|
110
|
+
setChatPromotion(runId, seatCount, grounded) {
|
|
111
|
+
this.runToChatSeatCount.set(runId, seatCount);
|
|
112
|
+
this.runToChatGrounded.set(runId, grounded);
|
|
113
|
+
}
|
|
114
|
+
/** The warm seat count at chat-promotion, or `undefined` (ABSENT when not a chat-promoted run). */
|
|
115
|
+
chatSeatCountFor(runId) {
|
|
116
|
+
return this.runToChatSeatCount.get(runId);
|
|
117
|
+
}
|
|
118
|
+
/** Whether the chat was graph-grounded at launch, or `undefined` (ABSENT when not chat-promoted). */
|
|
119
|
+
chatGroundedFor(runId) {
|
|
120
|
+
return this.runToChatGrounded.get(runId);
|
|
121
|
+
}
|
|
68
122
|
/**
|
|
69
123
|
* Consume pre-read `run.ended` entries (crew#496 / studio#230) — the daemon records one when it
|
|
70
124
|
* sees a run's terminal frame (`sessionCompleted` | `sessionFailed` | `runCancelled`). The run's
|
|
@@ -111,6 +165,15 @@ export function recordRunLaunched(audit, runTimingIndex, actor, runId, detail) {
|
|
|
111
165
|
const ts = audit.record('run.launched', actor, { runId, detail });
|
|
112
166
|
if (ts > 0)
|
|
113
167
|
runTimingIndex?.set(runId, ts);
|
|
168
|
+
// crew#632: also stamp channel/actor into the index for live serving (same posture as created_at).
|
|
169
|
+
const ch = detail['channel'];
|
|
170
|
+
if ((ch === 'studio' || ch === 'cli' || ch === 'api') && runTimingIndex !== undefined) {
|
|
171
|
+
runTimingIndex.setChannel(runId, ch);
|
|
172
|
+
}
|
|
173
|
+
const la = detail['actor'];
|
|
174
|
+
if (typeof la === 'string' && la.length > 0 && runTimingIndex !== undefined) {
|
|
175
|
+
runTimingIndex.setLaunchActor(runId, la);
|
|
176
|
+
}
|
|
114
177
|
return ts;
|
|
115
178
|
}
|
|
116
179
|
//# sourceMappingURL=run-timing-index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-timing-index.js","sourceRoot":"","sources":["../../src/api/run-timing-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH;;;;GAIG;AACH,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,OAAO,cAAc;IACR,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5D,oGAAoG;IACnF,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-timing-index.js","sourceRoot":"","sources":["../../src/api/run-timing-index.ts"],"names":[],"mappings":"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"}
|
package/dist/api/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAW9B,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"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"}
|
package/dist/api/server.js
CHANGED
|
@@ -22,9 +22,10 @@ import { coreUnitId } from './evidence.js';
|
|
|
22
22
|
import { registerClient, broadcast } from '../events/bus.js';
|
|
23
23
|
import { TerminalHub, registerTerminalWs } from '../events/terminals.js';
|
|
24
24
|
import { QeGateCache, startQeGateSubscriber } from '../qe/gate-events.js';
|
|
25
|
-
import { startInteractiveDraftSubscriber } from '../interactive/draft-events.js';
|
|
26
|
-
import { startInteractiveEditSubscriber } from '../interactive/edit-events.js';
|
|
27
|
-
import { startInteractiveChatSubscriber } from '../interactive/chat-events.js';
|
|
25
|
+
import { INTERACTIVE_DRAFT_WORKFLOW_DEF, startInteractiveDraftSubscriber } from '../interactive/draft-events.js';
|
|
26
|
+
import { INTERACTIVE_EDIT_WORKFLOW_DEF, startInteractiveEditSubscriber } from '../interactive/edit-events.js';
|
|
27
|
+
import { INTERACTIVE_CHAT_WORKFLOW_DEF, startInteractiveChatSubscriber } from '../interactive/chat-events.js';
|
|
28
|
+
import { PhaseSkillArming, RunSkillGapIndex } from '../skills/phase-skill-gaps.js';
|
|
28
29
|
import { startInteractiveDemoSubscriber } from '../interactive/demo-events.js';
|
|
29
30
|
import { resolveProjectInteractiveRoot } from '../interactive/bridge-root.js';
|
|
30
31
|
import { sweepDocLedgers } from '../interactive/doc-ledger-sweep.js';
|
|
@@ -44,6 +45,7 @@ import { SeatHealthTracker } from './seat-health.js';
|
|
|
44
45
|
import { rosterWithStandingFactory } from './roster-standing.js';
|
|
45
46
|
import { ChatTurnIndex } from './chat-turns.js';
|
|
46
47
|
import { ChatTranscriptStore } from './chat-transcripts.js';
|
|
48
|
+
import { sweepDeliveredWorktree } from './worktree-sweep.js';
|
|
47
49
|
import { installEndpointManifestHook } from './endpoint-manifest.js';
|
|
48
50
|
import { WorkerStallWatchdog } from './stall-watchdog.js';
|
|
49
51
|
import { applyWorkerConfigRoot } from './seat-signin.js';
|
|
@@ -224,6 +226,11 @@ export async function createServer(adapter, options) {
|
|
|
224
226
|
// bootstrap-configured state home (crew#353); the warn hook is the loud half of the migration
|
|
225
227
|
// posture — an override root shadowing a default-root file must be SAID at boot, never silent.
|
|
226
228
|
const projectSettings = new ProjectSettingsStore(undefined, (m) => app.log.warn(m));
|
|
229
|
+
// crew#619: chats promoted to runs retain their transcripts until the run is terminal, even
|
|
230
|
+
// across daemon restarts. The maps are populated from the audit trail below (non-terminal
|
|
231
|
+
// `run.launched` entries that carry a `chatId`) and kept in sync by the event loop.
|
|
232
|
+
const chatRetained = new Map();
|
|
233
|
+
const runToChat = new Map();
|
|
227
234
|
// Retry lineage (CREW-UX-3) + ad-hoc group attach (wicked-studio#27): both durable records
|
|
228
235
|
// live in the trail's `run.launched` entries, so ONE exhaustive scan feeds both indexes —
|
|
229
236
|
// boot stays at three full-file trail scans, not four (the crew#321 consolidation note).
|
|
@@ -241,7 +248,18 @@ export async function createServer(adapter, options) {
|
|
|
241
248
|
// frames — one more filtered scan, same try, same best-effort. Nothing is re-emitted at boot: a
|
|
242
249
|
// run that terminalled with no entry (pre-field, or the crash window between the engine's
|
|
243
250
|
// status write and the synchronous record below) stays undated.
|
|
244
|
-
|
|
251
|
+
const endedEntries = await audit.readAll({ action: 'run.ended' });
|
|
252
|
+
runTimingIndex.hydrateFromEndedEntries(endedEntries);
|
|
253
|
+
// crew#619: rebuild the chat↔run retention maps for runs that were still live when the
|
|
254
|
+
// daemon was last stopped. The `run.launched` entries that carry `chatId` and are NOT in
|
|
255
|
+
// `run.ended` represent runs whose transcripts must still be on disk.
|
|
256
|
+
const endedRunIds = new Set(endedEntries.filter((e) => typeof e.runId === 'string').map((e) => e.runId));
|
|
257
|
+
for (const entry of launchEntries) {
|
|
258
|
+
const chatId = entry.detail?.['chatId'];
|
|
259
|
+
if (typeof entry.runId === 'string' && typeof chatId === 'string' && !endedRunIds.has(entry.runId)) {
|
|
260
|
+
linkChatRun(chatId, entry.runId);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
245
263
|
}
|
|
246
264
|
catch (err) {
|
|
247
265
|
app.log.warn(`[runs] launch-index hydrate failed (prior runs read as not-a-retry / ungrouped / undated until restart): ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -283,6 +301,12 @@ export async function createServer(adapter, options) {
|
|
|
283
301
|
// trail's `guidance.set` entries so notes survive a daemon restart.
|
|
284
302
|
const guidanceIndex = new GuidanceIndex();
|
|
285
303
|
await guidanceIndex.hydrate(audit, (m) => app.log.warn(m));
|
|
304
|
+
// crew#661: each drafting seam's ARM-TIME skill outcome (diagnostics / health), and the runs
|
|
305
|
+
// launched while a seam was unarmed (`session.skill_gaps`) — same durable trail pattern.
|
|
306
|
+
const phaseSkills = new PhaseSkillArming(() => skillsRuntime?.health().current?.gen ?? null);
|
|
307
|
+
const runSkillGaps = new RunSkillGapIndex();
|
|
308
|
+
await runSkillGaps.hydrate(audit, (m) => app.log.warn(m));
|
|
309
|
+
const skillHeld = (name) => skillsRuntime?.holdsSkill(name) ?? false;
|
|
286
310
|
// Delivered-PR record (CREW-UX-8, crew#321): same durable pattern — hydrated from the
|
|
287
311
|
// trail's `run.delivered` entries so `session.delivery` survives a daemon restart.
|
|
288
312
|
const deliveryIndex = new DeliveryIndex();
|
|
@@ -577,9 +601,11 @@ export async function createServer(adapter, options) {
|
|
|
577
601
|
...(o.clisJson !== undefined ? { clisJson: o.clisJson } : {}),
|
|
578
602
|
// The roster WITH standing when no override is set (F-RECON-002/003).
|
|
579
603
|
roster: rosterWithStanding,
|
|
580
|
-
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it
|
|
581
|
-
|
|
604
|
+
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it;
|
|
605
|
+
// the arm-time answer is recorded for /diagnostics (crew#661).
|
|
606
|
+
skillHeld: phaseSkills.probe('interactive-draft', INTERACTIVE_DRAFT_WORKFLOW_DEF, skillHeld),
|
|
582
607
|
onRunFiled: fileRun,
|
|
608
|
+
onRunLaunched: (runId, detail) => { recordRunLaunched(audit, runTimingIndex, DAEMON_ACTOR, runId, detail); },
|
|
583
609
|
// F-046: the create-time grounding sidecar is read under the SAME per-project docs root the
|
|
584
610
|
// proxy recorded it in.
|
|
585
611
|
groundingStore: docGrounding,
|
|
@@ -587,6 +613,9 @@ export async function createServer(adapter, options) {
|
|
|
587
613
|
log: (m) => app.log.warn(m),
|
|
588
614
|
logError: (m) => app.log.error(m),
|
|
589
615
|
});
|
|
616
|
+
// crew#661: a seam that failed to arm runs nothing — its arm-time skill answer is not a gap.
|
|
617
|
+
if (draftSub === null)
|
|
618
|
+
phaseSkills.forget('interactive-draft');
|
|
590
619
|
if (draftSub !== null) {
|
|
591
620
|
const sub = draftSub;
|
|
592
621
|
app.log.info('interactive-draft subscription armed (filter wicked.interactive.doc.created)');
|
|
@@ -613,8 +642,9 @@ export async function createServer(adapter, options) {
|
|
|
613
642
|
...(o.clisJson !== undefined ? { clisJson: o.clisJson } : {}),
|
|
614
643
|
// The roster WITH standing when no override is set (F-RECON-002/003).
|
|
615
644
|
roster: rosterWithStanding,
|
|
616
|
-
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it
|
|
617
|
-
|
|
645
|
+
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it;
|
|
646
|
+
// the arm-time answer is recorded for /diagnostics (crew#661).
|
|
647
|
+
skillHeld: phaseSkills.probe('interactive-edit', INTERACTIVE_EDIT_WORKFLOW_DEF, skillHeld),
|
|
618
648
|
// The demo-kind gate (CREW-UX-9): a demo doc's step feedback is the demo seam's — but
|
|
619
649
|
// only when that seam is actually up. Probed per event (the demo seam arms below), so an
|
|
620
650
|
// un-armed demo seam gets an honest error status instead of a silent, unanswerable drop.
|
|
@@ -624,6 +654,9 @@ export async function createServer(adapter, options) {
|
|
|
624
654
|
log: (m) => app.log.warn(m),
|
|
625
655
|
logError: (m) => app.log.error(m),
|
|
626
656
|
});
|
|
657
|
+
// crew#661: a seam that failed to arm runs nothing — its arm-time skill answer is not a gap.
|
|
658
|
+
if (editSub === null)
|
|
659
|
+
phaseSkills.forget('interactive-edit');
|
|
627
660
|
if (editSub !== null) {
|
|
628
661
|
const sub = editSub;
|
|
629
662
|
app.log.info('interactive-edit subscription armed (filter wicked.interactive.feedback.processed)');
|
|
@@ -650,6 +683,7 @@ export async function createServer(adapter, options) {
|
|
|
650
683
|
roster: rosterWithStanding,
|
|
651
684
|
resolveDocsRoot: o.resolveDocsRoot ?? interactiveDocsRoot,
|
|
652
685
|
onRunFiled: fileRun,
|
|
686
|
+
onRunLaunched: (runId, detail) => { recordRunLaunched(audit, runTimingIndex, DAEMON_ACTOR, runId, detail); },
|
|
653
687
|
groundingStore: docGrounding,
|
|
654
688
|
log: (m) => app.log.warn(m),
|
|
655
689
|
logError: (m) => app.log.error(m),
|
|
@@ -678,8 +712,9 @@ export async function createServer(adapter, options) {
|
|
|
678
712
|
...(o.clisJson !== undefined ? { clisJson: o.clisJson } : {}),
|
|
679
713
|
// The roster WITH standing when no override is set (F-RECON-002/003).
|
|
680
714
|
roster: rosterWithStanding,
|
|
681
|
-
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it
|
|
682
|
-
|
|
715
|
+
// The quality-floor skill gate (draft-skill.ts): stamped only when the published snapshot holds it;
|
|
716
|
+
// the arm-time answer is recorded for /diagnostics (crew#661).
|
|
717
|
+
skillHeld: phaseSkills.probe('interactive-chat', INTERACTIVE_CHAT_WORKFLOW_DEF, skillHeld),
|
|
683
718
|
...(o.queueSweepMs !== undefined ? { queueSweepMs: o.queueSweepMs } : {}),
|
|
684
719
|
...(o.landingGateMs !== undefined ? { landingGateMs: o.landingGateMs } : {}),
|
|
685
720
|
resolveDocsRoot: o.resolveDocsRoot ?? interactiveDocsRoot,
|
|
@@ -689,6 +724,9 @@ export async function createServer(adapter, options) {
|
|
|
689
724
|
log: (m) => app.log.warn(m),
|
|
690
725
|
logError: (m) => app.log.error(m),
|
|
691
726
|
});
|
|
727
|
+
// crew#661: a seam that failed to arm runs nothing — its arm-time skill answer is not a gap.
|
|
728
|
+
if (chatSub === null)
|
|
729
|
+
phaseSkills.forget('interactive-chat');
|
|
692
730
|
if (chatSub !== null) {
|
|
693
731
|
const sub = chatSub;
|
|
694
732
|
app.log.info('interactive-chat subscription armed (filter wicked.interactive.chat.posted)');
|
|
@@ -808,6 +846,19 @@ export async function createServer(adapter, options) {
|
|
|
808
846
|
// written from the stamped frames below, dropped with the chat on `chatClosed`, served on
|
|
809
847
|
// `GET /chats/:id.messages`.
|
|
810
848
|
const chatTranscripts = new ChatTranscriptStore();
|
|
849
|
+
// crew#619: see declaration of chatRetained/runToChat above (before the hydration block).
|
|
850
|
+
// linkChatRun populates both maps and is called from the hydration block (function-hoisted)
|
|
851
|
+
// and from the launch route (via RoutesRuntime.linkChatRun).
|
|
852
|
+
function linkChatRun(chatId, runId) {
|
|
853
|
+
runToChat.set(runId, chatId);
|
|
854
|
+
const existing = chatRetained.get(chatId);
|
|
855
|
+
if (existing !== undefined) {
|
|
856
|
+
existing.add(runId);
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
chatRetained.set(chatId, new Set([runId]));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
811
862
|
// Boot reaper (crew#502 hardening, W6): the scratch namespaces of daemons that died without
|
|
812
863
|
// closing their chats (`<tmp>/wicked-crew-chats/<pid>-*` with a dead pid) are removed once, here,
|
|
813
864
|
// under the same real-directory/ownership checks a live close applies. Not under vitest: the
|
|
@@ -817,9 +868,10 @@ export async function createServer(adapter, options) {
|
|
|
817
868
|
if (reaped.length > 0) {
|
|
818
869
|
app.log.info(`chat scratch: reaped ${reaped.length} namespace(s) of dead daemons: ${reaped.join(', ')}`);
|
|
819
870
|
}
|
|
820
|
-
//
|
|
821
|
-
//
|
|
822
|
-
|
|
871
|
+
// Clear orphaned transcripts at boot. Transcripts for promoted runs that are still
|
|
872
|
+
// non-terminal (rehydrated above into chatRetained) are PRESERVED so Continue-in-Build
|
|
873
|
+
// prefill remains reproducible across a daemon restart (crew#619).
|
|
874
|
+
chatTranscripts.clearOrphaned(new Set(chatRetained.keys()));
|
|
823
875
|
}
|
|
824
876
|
const offEvent = adapter.onEvent((event) => {
|
|
825
877
|
gateCache.ingest(event);
|
|
@@ -827,14 +879,22 @@ export async function createServer(adapter, options) {
|
|
|
827
879
|
seatHealth.ingest(event);
|
|
828
880
|
if (event.type === 'chatClosed' && typeof event.chat === 'string') {
|
|
829
881
|
chatScopes.closed(event.chat);
|
|
830
|
-
//
|
|
831
|
-
|
|
882
|
+
// crew#619: retain the transcript when a promoted run is still live — the chat may be
|
|
883
|
+
// idle-TTL'd before the run finishes, and Continue-in-Build needs the transcript.
|
|
884
|
+
const retaining = chatRetained.get(event.chat);
|
|
885
|
+
if (retaining === undefined || retaining.size === 0) {
|
|
886
|
+
// ONE mechanism for DELETE / idle / pool_cap alike: the transcript goes with the chat.
|
|
887
|
+
chatTranscripts.drop(event.chat);
|
|
888
|
+
}
|
|
832
889
|
}
|
|
833
890
|
// Stamp BEFORE folding: the closing `chatReply` is the frame most worth correlating — and the
|
|
834
891
|
// one the transcript records (only a stamped reply is persisted; a straggler after the close
|
|
835
892
|
// carries no `turn_id` and cannot recreate the file).
|
|
836
893
|
const stamped = chatTurns.decorate(event);
|
|
837
|
-
|
|
894
|
+
// crew#618 Acceptance 1: rewrite the chatReply frame ONCE — before both observe (persist) and
|
|
895
|
+
// broadcast (/ws → studio render/promote). `observe`'s own rewrite pass is then a no-op.
|
|
896
|
+
const rewritten = chatTranscripts.rewriteEvent(stamped);
|
|
897
|
+
chatTranscripts.observe(rewritten);
|
|
838
898
|
chatTurns.observe(event);
|
|
839
899
|
// Only feed the watchdog when its sweep is (or will be) armed: sweeping is what
|
|
840
900
|
// prunes its per-run maps, so ingesting while disabled grows without bound
|
|
@@ -847,7 +907,7 @@ export async function createServer(adapter, options) {
|
|
|
847
907
|
skillsRuntime?.observe(event);
|
|
848
908
|
const session = typeof event.session === 'string' ? event.session : undefined;
|
|
849
909
|
const projectId = session !== undefined ? membershipIndex.projectOf(session) : undefined;
|
|
850
|
-
broadcast(projectId !== undefined ? { ...
|
|
910
|
+
broadcast(projectId !== undefined ? { ...rewritten, project_id: projectId } : rewritten);
|
|
851
911
|
// The delivered-PR record (CREW-UX-8, crew#321): resolved once per run at its terminal
|
|
852
912
|
// frame, best-effort, off the hot path — see `resolveRunDelivery` above for why BOTH
|
|
853
913
|
// terminal frames trigger it and why a failed deliver is a no-op. THEN the delivery-
|
|
@@ -855,6 +915,22 @@ export async function createServer(adapter, options) {
|
|
|
855
915
|
// healing the DTO's stranded/vacuous/none label in seconds instead of at the next sweep.
|
|
856
916
|
if ((event.type === 'sessionCompleted' || event.type === 'sessionFailed' || event.type === 'runCancelled') &&
|
|
857
917
|
session !== undefined) {
|
|
918
|
+
// crew#619: when a run that was linked to a chat terminates, release the retention hold and
|
|
919
|
+
// drop the transcript if the chat was already reclaimed (not in chatScopes).
|
|
920
|
+
const linkedChat = runToChat.get(session);
|
|
921
|
+
if (linkedChat !== undefined) {
|
|
922
|
+
runToChat.delete(session);
|
|
923
|
+
const retaining = chatRetained.get(linkedChat);
|
|
924
|
+
if (retaining !== undefined) {
|
|
925
|
+
retaining.delete(session);
|
|
926
|
+
if (retaining.size === 0) {
|
|
927
|
+
chatRetained.delete(linkedChat);
|
|
928
|
+
if (!chatScopes.has(linkedChat)) {
|
|
929
|
+
chatTranscripts.drop(linkedChat);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
858
934
|
// `ended_at` (crew#496 / studio#230; api-types 0.38.0): the durable record first (`run.ended`),
|
|
859
935
|
// then the index — the `run.delivered` write order. Synchronous, on the frame, so the DTO dates
|
|
860
936
|
// the run the instant it terminals. IDEMPOTENT per run: a resume/retry re-terminal (or any
|
|
@@ -870,6 +946,26 @@ export async function createServer(adapter, options) {
|
|
|
870
946
|
runTimingIndex.setEnded(session, endedTs);
|
|
871
947
|
}
|
|
872
948
|
void resolveRunDelivery(session)
|
|
949
|
+
// crew#620 Acceptance 3: sweep the delivered run's worktree once the PR is open.
|
|
950
|
+
// Best-effort — a sweep error must never fail the terminal frame.
|
|
951
|
+
.then(async () => {
|
|
952
|
+
if (deliveryIndex.urlFor(session) !== undefined) {
|
|
953
|
+
try {
|
|
954
|
+
const views = await adapter.sessionsDetail();
|
|
955
|
+
const repoRef = views.find((v) => v.session.id === session)?.session.repo_ref;
|
|
956
|
+
if (repoRef !== null && repoRef !== undefined) {
|
|
957
|
+
const repos = await adapter.listRepos();
|
|
958
|
+
const repoRoot = repos.find((r) => r.id === repoRef)?.root_path;
|
|
959
|
+
if (repoRoot !== undefined) {
|
|
960
|
+
await sweepDeliveredWorktree(session, repoRoot, (m) => app.log.info(m));
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
catch (err) {
|
|
965
|
+
app.log.warn(`[runs] worktree sweep failed for ${session}: ${err instanceof Error ? err.message : String(err)}`);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
})
|
|
873
969
|
.then(() => deliveryCache.warm(session))
|
|
874
970
|
// Wave 6 (F-7R2-014): a terminal `qe-author-tests` run registers its TEST SET — the
|
|
875
971
|
// produced tests as the verify phase judged them — AFTER the delivery record resolved, so
|
|
@@ -934,6 +1030,9 @@ export async function createServer(adapter, options) {
|
|
|
934
1030
|
// close like the event listener.
|
|
935
1031
|
const offLaunch = adapter.onLaunch((notice) => {
|
|
936
1032
|
skillsRuntime?.launched(notice);
|
|
1033
|
+
// crew#661: a run the engine ACCEPTED on a workflow that armed WITHOUT its declared skill proceeds
|
|
1034
|
+
// degraded and says so on the run (`session.skill_gaps`, a `run.skill.unarmed` trail entry). Never throws.
|
|
1035
|
+
runSkillGaps.onLaunch(notice, phaseSkills, audit, DAEMON_ACTOR, (m) => app.log.warn(m));
|
|
937
1036
|
});
|
|
938
1037
|
app.addHook('onClose', async () => {
|
|
939
1038
|
offEvent();
|
|
@@ -1025,6 +1124,8 @@ export async function createServer(adapter, options) {
|
|
|
1025
1124
|
groupIndex,
|
|
1026
1125
|
runTimingIndex,
|
|
1027
1126
|
guidanceIndex,
|
|
1127
|
+
phaseSkills,
|
|
1128
|
+
runSkillGaps,
|
|
1028
1129
|
chatScopes,
|
|
1029
1130
|
chatTurns,
|
|
1030
1131
|
chatTranscripts,
|
|
@@ -1053,6 +1154,8 @@ export async function createServer(adapter, options) {
|
|
|
1053
1154
|
// Routes that say something to the thread (a refused chat seat, F-2R2-007) emit through the
|
|
1054
1155
|
// SAME /ws fan-out the engine's frames take.
|
|
1055
1156
|
broadcast: (frame) => broadcast(frame),
|
|
1157
|
+
// crew#619: retain a chat's transcript for the lifetime of its promoted run.
|
|
1158
|
+
linkChatRun,
|
|
1056
1159
|
});
|
|
1057
1160
|
// The UI-emittable direction of the interactive seam. Registered unconditionally (a null relay
|
|
1058
1161
|
// answers 503, not 404) and BEFORE the static/SPA fallback below, like every other API route.
|