@adhdev/daemon-core 0.9.82-rc.470 → 0.9.82-rc.471
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/index.js +62 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -20
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +35 -0
- package/package.json +3 -3
- package/src/providers/cli-provider-instance.ts +68 -16
|
@@ -69,6 +69,17 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
69
69
|
* bound below still caps the episode, so a worker whose approval truly never
|
|
70
70
|
* returns is surfaced to the coordinator within AUTO_APPROVE_MASK_STALL_MS
|
|
71
71
|
* rather than held forever.
|
|
72
|
+
*
|
|
73
|
+
* INVARIANT (do not regress the ordering): this window must fully BRIDGE a
|
|
74
|
+
* single busy phase, and the mask-stall bound below must in turn exceed it —
|
|
75
|
+
* AUTO_APPROVE_MASK_STALL_MS > AUTO_APPROVE_FLAP_CONTINUITY_MS + max_busy_phase
|
|
76
|
+
* + AUTO_APPROVE_SETTLE_MS. Observed flap geometry (delegated-worker Bash
|
|
77
|
+
* approval): approval frames last ~1.5s, busy phases (modal=none) last
|
|
78
|
+
* ~4.3–4.5s. With the old 4000ms this window was SHORTER than a busy phase, so
|
|
79
|
+
* the settle clock was torn down every cycle and never accrued 600ms while the
|
|
80
|
+
* 4500ms mask-stall tripped INSIDE the first busy phase → a stalled-approval
|
|
81
|
+
* nudge leaked to the coordinator. 6000ms bridges the ~4.5s busy phase with
|
|
82
|
+
* margin so the returning approval frame survives to resume its settle clock.
|
|
72
83
|
*/
|
|
73
84
|
private static readonly AUTO_APPROVE_FLAP_CONTINUITY_MS;
|
|
74
85
|
/**
|
|
@@ -87,6 +98,15 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
87
98
|
* genuine never-resolving stall surfaces within this window. The settle gate keeps
|
|
88
99
|
* running underneath, so a prompt that finally stabilises still auto-approves, and
|
|
89
100
|
* mesh_approve (raw FSM, unmasked) works throughout.
|
|
101
|
+
*
|
|
102
|
+
* INVARIANT (do not regress): must be STRICTLY GREATER than
|
|
103
|
+
* AUTO_APPROVE_FLAP_CONTINUITY_MS + max_busy_phase + AUTO_APPROVE_SETTLE_MS so
|
|
104
|
+
* that during a flap the settle clock (which FLAP_CONTINUITY keeps alive across
|
|
105
|
+
* each ~4.3–4.5s busy phase) gets to accrue its 600ms on the RETURNING approval
|
|
106
|
+
* frame before this stall bound can trip. Observed geometry: approval ~1.5s,
|
|
107
|
+
* busy ~4.3–4.5s. 9000ms ≥ CONTINUITY(6000) + busy(~4.5s) + SETTLE(600) headroom;
|
|
108
|
+
* the old 4500ms tripped inside the very first busy phase (while modal=none, so
|
|
109
|
+
* the nudge was NOT deferred) and leaked to the coordinator.
|
|
90
110
|
*/
|
|
91
111
|
private static readonly AUTO_APPROVE_MASK_STALL_MS;
|
|
92
112
|
private adapter;
|
|
@@ -340,6 +360,21 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
340
360
|
private recordCompletionGateTrace;
|
|
341
361
|
private recordFsmTransitionTrace;
|
|
342
362
|
private flushCompletedDebounceIfFinalized;
|
|
363
|
+
/**
|
|
364
|
+
* A-3 (CLI 완료판정 통합): single authoritative emit for a CLI turn's
|
|
365
|
+
* `agent:generating_completed` event. The completion JUDGMENT — WHETHER and
|
|
366
|
+
* WHEN a turn is done (settle windows, continuity guards, the finalization
|
|
367
|
+
* gate, the short-gen / startup-grace / no-progress-monitor discriminators) —
|
|
368
|
+
* stays at each call site, where it is legitimately path-specific. What used
|
|
369
|
+
* to be duplicated across all five completion paths was the EVENT-SHAPE
|
|
370
|
+
* assembly: the `event` name, the conditional `taskId` spread, and the
|
|
371
|
+
* optional `finalSummary` / `evidenceLevel` / `completionDiagnostic` fields.
|
|
372
|
+
* Folding that assembly here removes the divergence (e.g. one site spreading
|
|
373
|
+
* taskId, others omitting it) without touching any judgment. Callers pass the
|
|
374
|
+
* values they have already computed; omitted optionals are simply absent from
|
|
375
|
+
* the emitted event, exactly as each inline builder produced before.
|
|
376
|
+
*/
|
|
377
|
+
private emitGeneratingCompleted;
|
|
343
378
|
private maybeAutoApproveStatus;
|
|
344
379
|
/**
|
|
345
380
|
* Re-drive the auto-approve check after the settle quiet window elapses.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.9.82-rc.
|
|
3
|
+
"version": "0.9.82-rc.471",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"author": "vilmire",
|
|
48
48
|
"license": "AGPL-3.0-or-later",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@adhdev/mesh-shared": "0.9.82-rc.
|
|
51
|
-
"@adhdev/session-host-core": "0.9.82-rc.
|
|
50
|
+
"@adhdev/mesh-shared": "0.9.82-rc.471",
|
|
51
|
+
"@adhdev/session-host-core": "0.9.82-rc.471",
|
|
52
52
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
53
53
|
"ajv": "^8.20.0",
|
|
54
54
|
"ajv-formats": "^3.0.1",
|
|
@@ -145,8 +145,19 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
145
145
|
* bound below still caps the episode, so a worker whose approval truly never
|
|
146
146
|
* returns is surfaced to the coordinator within AUTO_APPROVE_MASK_STALL_MS
|
|
147
147
|
* rather than held forever.
|
|
148
|
+
*
|
|
149
|
+
* INVARIANT (do not regress the ordering): this window must fully BRIDGE a
|
|
150
|
+
* single busy phase, and the mask-stall bound below must in turn exceed it —
|
|
151
|
+
* AUTO_APPROVE_MASK_STALL_MS > AUTO_APPROVE_FLAP_CONTINUITY_MS + max_busy_phase
|
|
152
|
+
* + AUTO_APPROVE_SETTLE_MS. Observed flap geometry (delegated-worker Bash
|
|
153
|
+
* approval): approval frames last ~1.5s, busy phases (modal=none) last
|
|
154
|
+
* ~4.3–4.5s. With the old 4000ms this window was SHORTER than a busy phase, so
|
|
155
|
+
* the settle clock was torn down every cycle and never accrued 600ms while the
|
|
156
|
+
* 4500ms mask-stall tripped INSIDE the first busy phase → a stalled-approval
|
|
157
|
+
* nudge leaked to the coordinator. 6000ms bridges the ~4.5s busy phase with
|
|
158
|
+
* margin so the returning approval frame survives to resume its settle clock.
|
|
148
159
|
*/
|
|
149
|
-
private static readonly AUTO_APPROVE_FLAP_CONTINUITY_MS =
|
|
160
|
+
private static readonly AUTO_APPROVE_FLAP_CONTINUITY_MS = 6000;
|
|
150
161
|
|
|
151
162
|
/**
|
|
152
163
|
* STATUS-MISMATCH: upper bound on how long the auto-approve→`generating` SURFACE
|
|
@@ -164,8 +175,17 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
164
175
|
* genuine never-resolving stall surfaces within this window. The settle gate keeps
|
|
165
176
|
* running underneath, so a prompt that finally stabilises still auto-approves, and
|
|
166
177
|
* mesh_approve (raw FSM, unmasked) works throughout.
|
|
178
|
+
*
|
|
179
|
+
* INVARIANT (do not regress): must be STRICTLY GREATER than
|
|
180
|
+
* AUTO_APPROVE_FLAP_CONTINUITY_MS + max_busy_phase + AUTO_APPROVE_SETTLE_MS so
|
|
181
|
+
* that during a flap the settle clock (which FLAP_CONTINUITY keeps alive across
|
|
182
|
+
* each ~4.3–4.5s busy phase) gets to accrue its 600ms on the RETURNING approval
|
|
183
|
+
* frame before this stall bound can trip. Observed geometry: approval ~1.5s,
|
|
184
|
+
* busy ~4.3–4.5s. 9000ms ≥ CONTINUITY(6000) + busy(~4.5s) + SETTLE(600) headroom;
|
|
185
|
+
* the old 4500ms tripped inside the very first busy phase (while modal=none, so
|
|
186
|
+
* the nudge was NOT deferred) and leaked to the coordinator.
|
|
167
187
|
*/
|
|
168
|
-
private static readonly AUTO_APPROVE_MASK_STALL_MS =
|
|
188
|
+
private static readonly AUTO_APPROVE_MASK_STALL_MS = 9000;
|
|
169
189
|
|
|
170
190
|
private adapter: ProviderCliAdapter;
|
|
171
191
|
private context: InstanceContext | null = null;
|
|
@@ -1836,13 +1856,11 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1836
1856
|
waitedMs,
|
|
1837
1857
|
busyEpoch: this.busyEpoch,
|
|
1838
1858
|
});
|
|
1839
|
-
this.
|
|
1840
|
-
event: 'agent:generating_completed',
|
|
1859
|
+
this.emitGeneratingCompleted({
|
|
1841
1860
|
chatTitle: pending.chatTitle,
|
|
1842
1861
|
duration: pending.duration,
|
|
1843
1862
|
timestamp: pending.timestamp,
|
|
1844
|
-
|
|
1845
|
-
...(pending.taskId ? { taskId: pending.taskId } : {}),
|
|
1863
|
+
taskId: pending.taskId,
|
|
1846
1864
|
// When finalization is forced past the timeout on a `parsed_status:` block
|
|
1847
1865
|
// (the parser never confirmed a final assistant turn) we previously rode an
|
|
1848
1866
|
// empty `finalSummary` unconditionally. That empty value propagates to the
|
|
@@ -1875,13 +1893,11 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1875
1893
|
duration: pending.duration,
|
|
1876
1894
|
busyEpoch: this.busyEpoch,
|
|
1877
1895
|
});
|
|
1878
|
-
this.
|
|
1879
|
-
event: 'agent:generating_completed',
|
|
1896
|
+
this.emitGeneratingCompleted({
|
|
1880
1897
|
chatTitle: pending.chatTitle,
|
|
1881
1898
|
duration: pending.duration,
|
|
1882
1899
|
timestamp: pending.timestamp,
|
|
1883
|
-
|
|
1884
|
-
...(pending.taskId ? { taskId: pending.taskId } : {}),
|
|
1900
|
+
taskId: pending.taskId,
|
|
1885
1901
|
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt),
|
|
1886
1902
|
});
|
|
1887
1903
|
this.completedDebouncePending = null;
|
|
@@ -1890,7 +1906,46 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1890
1906
|
this.lastApprovalEventFingerprint = '';
|
|
1891
1907
|
}
|
|
1892
1908
|
|
|
1909
|
+
/**
|
|
1910
|
+
* A-3 (CLI 완료판정 통합): single authoritative emit for a CLI turn's
|
|
1911
|
+
* `agent:generating_completed` event. The completion JUDGMENT — WHETHER and
|
|
1912
|
+
* WHEN a turn is done (settle windows, continuity guards, the finalization
|
|
1913
|
+
* gate, the short-gen / startup-grace / no-progress-monitor discriminators) —
|
|
1914
|
+
* stays at each call site, where it is legitimately path-specific. What used
|
|
1915
|
+
* to be duplicated across all five completion paths was the EVENT-SHAPE
|
|
1916
|
+
* assembly: the `event` name, the conditional `taskId` spread, and the
|
|
1917
|
+
* optional `finalSummary` / `evidenceLevel` / `completionDiagnostic` fields.
|
|
1918
|
+
* Folding that assembly here removes the divergence (e.g. one site spreading
|
|
1919
|
+
* taskId, others omitting it) without touching any judgment. Callers pass the
|
|
1920
|
+
* values they have already computed; omitted optionals are simply absent from
|
|
1921
|
+
* the emitted event, exactly as each inline builder produced before.
|
|
1922
|
+
*/
|
|
1923
|
+
private emitGeneratingCompleted(opts: {
|
|
1924
|
+
chatTitle: string;
|
|
1925
|
+
duration: number | undefined;
|
|
1926
|
+
timestamp: number;
|
|
1927
|
+
taskId?: string;
|
|
1928
|
+
finalSummary?: string;
|
|
1929
|
+
evidenceLevel?: string;
|
|
1930
|
+
completionDiagnostic?: Record<string, unknown>;
|
|
1931
|
+
}): void {
|
|
1932
|
+
this.pushEvent({
|
|
1933
|
+
event: 'agent:generating_completed',
|
|
1934
|
+
chatTitle: opts.chatTitle,
|
|
1935
|
+
duration: opts.duration,
|
|
1936
|
+
timestamp: opts.timestamp,
|
|
1937
|
+
// ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
|
|
1938
|
+
...(opts.taskId ? { taskId: opts.taskId } : {}),
|
|
1939
|
+
// finalSummary is always carried (value may be undefined) — every prior
|
|
1940
|
+
// inline builder included the key, so downstream consumers see the same shape.
|
|
1941
|
+
finalSummary: opts.finalSummary,
|
|
1942
|
+
...(opts.evidenceLevel !== undefined ? { evidenceLevel: opts.evidenceLevel } : {}),
|
|
1943
|
+
...(opts.completionDiagnostic !== undefined ? { completionDiagnostic: opts.completionDiagnostic } : {}),
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1893
1947
|
private maybeAutoApproveStatus(adapterStatus: any, now = Date.now()): boolean {
|
|
1948
|
+
// Manual-attendance suppression (provider-common): when a human is
|
|
1894
1949
|
// Manual-attendance suppression (provider-common): when a human is
|
|
1895
1950
|
// actively driving this session from the dashboard, hold auto-approve so
|
|
1896
1951
|
// the modal stays visible and they can pick a button / use the controlbar
|
|
@@ -2281,8 +2336,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2281
2336
|
missingEvidence,
|
|
2282
2337
|
evidenceLevel: 'weak',
|
|
2283
2338
|
});
|
|
2284
|
-
this.
|
|
2285
|
-
event: 'agent:generating_completed',
|
|
2339
|
+
this.emitGeneratingCompleted({
|
|
2286
2340
|
chatTitle,
|
|
2287
2341
|
duration: 0,
|
|
2288
2342
|
timestamp: now,
|
|
@@ -2618,8 +2672,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2618
2672
|
// surface its completion promptly without a 4s settle) still holds, and a
|
|
2619
2673
|
// non-mesh session has no coordinator to be falsely notified — the false-idle
|
|
2620
2674
|
// bug being fixed is specifically the mesh worker/coordinator misfire above.
|
|
2621
|
-
this.
|
|
2622
|
-
event: 'agent:generating_completed',
|
|
2675
|
+
this.emitGeneratingCompleted({
|
|
2623
2676
|
chatTitle,
|
|
2624
2677
|
duration: 0,
|
|
2625
2678
|
timestamp: now,
|
|
@@ -2857,8 +2910,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2857
2910
|
if (this.isMeshWorkerSession()) {
|
|
2858
2911
|
traceMeshEventStage('fired', this.meshTraceCtx(), 'no_progress_monitor_final_summary');
|
|
2859
2912
|
}
|
|
2860
|
-
this.
|
|
2861
|
-
event: 'agent:generating_completed',
|
|
2913
|
+
this.emitGeneratingCompleted({
|
|
2862
2914
|
chatTitle,
|
|
2863
2915
|
duration: this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1000) : undefined,
|
|
2864
2916
|
timestamp: me.timestamp,
|