instar 1.3.604 → 1.3.606
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 +104 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +28 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/AutonomousSessions.d.ts +24 -0
- package/dist/core/AutonomousSessions.d.ts.map +1 -1
- package/dist/core/AutonomousSessions.js +22 -0
- package/dist/core/AutonomousSessions.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +13 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +101 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +49 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/feedback-factory/processing/FeedbackProcessingService.d.ts +70 -0
- package/dist/feedback-factory/processing/FeedbackProcessingService.d.ts.map +1 -0
- package/dist/feedback-factory/processing/FeedbackProcessingService.js +74 -0
- package/dist/feedback-factory/processing/FeedbackProcessingService.js.map +1 -0
- package/dist/feedback-factory/store/JsonlFeedbackStore.d.ts +34 -0
- package/dist/feedback-factory/store/JsonlFeedbackStore.d.ts.map +1 -1
- package/dist/feedback-factory/store/JsonlFeedbackStore.js +59 -0
- package/dist/feedback-factory/store/JsonlFeedbackStore.js.map +1 -1
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts +169 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts.map +1 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js +296 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js.map +1 -0
- package/dist/monitoring/ProxyCoordinator.d.ts +1 -1
- package/dist/monitoring/ProxyCoordinator.d.ts.map +1 -1
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts +44 -0
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts.map +1 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js +81 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js.map +1 -0
- package/dist/monitoring/sentinelWiring.d.ts +14 -0
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +19 -0
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +12 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +5 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +34 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +21 -0
- package/dist/server/CapabilityIndex.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 +45 -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/jobs/instar/feedback-factory-process.md +35 -0
- package/src/scaffold/templates.ts +12 -0
- package/upgrades/1.3.605.md +29 -0
- package/upgrades/1.3.606.md +28 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat-ratchet-fix.md +36 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat.md +40 -0
- package/upgrades/side-effects/feedback-processor-job.md +60 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeedbackProcessingService.ts — the production trigger that turns the already-
|
|
3
|
+
* parity'd `processUnprocessed` clustering pass into a real, triggerable
|
|
4
|
+
* capability (feedback-factory-migration spec §191: "the processor job is
|
|
5
|
+
* actually constructed and scheduled, not dead code").
|
|
6
|
+
*
|
|
7
|
+
* It owns a single `JsonlFeedbackStore` rooted at the CANONICAL store directory —
|
|
8
|
+
* the SAME directory the InboxDrainer fills (so the processor clusters the exact
|
|
9
|
+
* reports the receiving end ingested). Two surfaces ride this service:
|
|
10
|
+
*
|
|
11
|
+
* - `GET /feedback-factory/stats` → stats() (pure read; never mutates)
|
|
12
|
+
* - `POST /feedback-factory/process` → processNow() (one clustering pass)
|
|
13
|
+
*
|
|
14
|
+
* Both are dev-gated at the construction boundary (resolveDevAgentGate over
|
|
15
|
+
* feedbackFactory.processing.enabled): the service is constructed only when the
|
|
16
|
+
* gate is live; otherwise the route context holds null and both routes 503.
|
|
17
|
+
*
|
|
18
|
+
* Signal-vs-authority: processNow only appends local JSONL — it creates/merges
|
|
19
|
+
* dedup clusters and flips items unprocessed→processing. It takes NO external
|
|
20
|
+
* action (dispatch is not invoked here) and never force-closes a curated
|
|
21
|
+
* cluster (terminal transitions stay evidence-gated in the processor itself).
|
|
22
|
+
* Re-running is idempotent and forward-only: once an item is 'processing' it is
|
|
23
|
+
* no longer 'unprocessed', so a second pass is a no-op over it.
|
|
24
|
+
*/
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { JsonlFeedbackStore } from '../store/JsonlFeedbackStore.js';
|
|
27
|
+
import { processUnprocessed } from '../processor/process.js';
|
|
28
|
+
export class FeedbackProcessingService {
|
|
29
|
+
store;
|
|
30
|
+
constructor(opts) {
|
|
31
|
+
this.store = new JsonlFeedbackStore(opts.dataDir);
|
|
32
|
+
}
|
|
33
|
+
/** Pure read — the GET /feedback-factory/stats surface. */
|
|
34
|
+
stats() {
|
|
35
|
+
// Re-fold from disk first: the InboxDrainer is a SEPARATE PROCESS holding its
|
|
36
|
+
// OWN store instance and appends `unprocessed` rows to feedback.jsonl after
|
|
37
|
+
// this service was constructed at boot. Without the reload, stats() would
|
|
38
|
+
// report a snapshot frozen at construction time and mask post-boot ingest.
|
|
39
|
+
this.store.reload();
|
|
40
|
+
return this.store.stats();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run one clustering+apply pass over the canonical store and return the
|
|
44
|
+
* processor result plus the post-pass stats. `now` is injected for the reopen
|
|
45
|
+
* audit note (defaults to wall-clock ISO). Appends local JSONL only.
|
|
46
|
+
*/
|
|
47
|
+
processNow(now) {
|
|
48
|
+
// Re-fold from disk first so this pass clusters everything the (separate-
|
|
49
|
+
// process) InboxDrainer has ingested since boot. The service builds its store
|
|
50
|
+
// ONCE at boot and JsonlFeedbackStore loads ONLY in its constructor — without
|
|
51
|
+
// this reload, every pass after the initial backlog would be a permanent
|
|
52
|
+
// no-op over newly-ingested reports (the exact "ingested but never clustered"
|
|
53
|
+
// defect spec §191 closes).
|
|
54
|
+
this.store.reload();
|
|
55
|
+
const result = processUnprocessed(this.store, now ?? new Date().toISOString());
|
|
56
|
+
return { result, stats: this.store.stats() };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The canonical feedback-factory store directory. Mirrors the InboxDrainer
|
|
61
|
+
* resolution exactly: an explicit `processing.dataDir` wins, else the
|
|
62
|
+
* receiverPersistence `dataDir` (so the two ends share one store), else the
|
|
63
|
+
* shipped default `<stateDir>/state/feedback-factory/store`.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveCanonicalStoreDir(config) {
|
|
66
|
+
const ff = config.feedbackFactory;
|
|
67
|
+
const explicit = ff?.processing?.dataDir ?? ff?.receiverPersistence?.dataDir;
|
|
68
|
+
if (explicit)
|
|
69
|
+
return explicit;
|
|
70
|
+
if (!config.stateDir)
|
|
71
|
+
return null;
|
|
72
|
+
return join(config.stateDir, 'state', 'feedback-factory', 'store');
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=FeedbackProcessingService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeedbackProcessingService.js","sourceRoot":"","sources":["../../../src/feedback-factory/processing/FeedbackProcessingService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAiB7D,MAAM,OAAO,yBAAyB;IACnB,KAAK,CAAqB;IAE3C,YAAY,IAAsC;QAChD,IAAI,CAAC,KAAK,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,2DAA2D;IAC3D,KAAK;QACH,8EAA8E;QAC9E,4EAA4E;QAC5E,0EAA0E;QAC1E,2EAA2E;QAC3E,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,GAAY;QACrB,0EAA0E;QAC1E,8EAA8E;QAC9E,8EAA8E;QAC9E,yEAAyE;QACzE,8EAA8E;QAC9E,4BAA4B;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/E,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAC/C,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAMxC;IACC,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC;IAClC,MAAM,QAAQ,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,IAAI,EAAE,EAAE,mBAAmB,EAAE,OAAO,CAAC;IAC7E,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -36,6 +36,25 @@ export declare class JsonlFeedbackStore implements FeedbackStore {
|
|
|
36
36
|
private dispatches;
|
|
37
37
|
private counts;
|
|
38
38
|
constructor(dir: string);
|
|
39
|
+
/**
|
|
40
|
+
* Re-fold all three on-disk JSONL files into fresh in-memory state — the SAME
|
|
41
|
+
* load the constructor runs. Use this when another PROCESS may have appended to
|
|
42
|
+
* the shared store since this instance was built (e.g. the InboxDrainer, a
|
|
43
|
+
* separate launchd process, appends `unprocessed` rows to `feedback.jsonl`
|
|
44
|
+
* continuously; without a reload this in-memory Map is frozen at construction
|
|
45
|
+
* time and the processing pass becomes a permanent no-op over everything
|
|
46
|
+
* ingested after boot).
|
|
47
|
+
*
|
|
48
|
+
* Concurrency: this is a read-only re-fold and appends are atomic single-line
|
|
49
|
+
* writes (appendFileSync). A reload that races a mid-append at worst skips one
|
|
50
|
+
* torn trailing line (already handled by loadJsonl's torn-line skip); the next
|
|
51
|
+
* reload picks up the completed line — identical to the constructor's load path.
|
|
52
|
+
* The in-memory `counts` (FeedbackMetrics) are session-scoped tallies of THIS
|
|
53
|
+
* instance's own mutations, not durable rows, so they are intentionally NOT
|
|
54
|
+
* reset by a reload.
|
|
55
|
+
*/
|
|
56
|
+
reload(): void;
|
|
57
|
+
private loadAll;
|
|
39
58
|
private loadAndMaybeCompact;
|
|
40
59
|
private appendFeedback;
|
|
41
60
|
private appendCluster;
|
|
@@ -61,5 +80,20 @@ export declare class JsonlFeedbackStore implements FeedbackStore {
|
|
|
61
80
|
clusters: number;
|
|
62
81
|
dispatches: number;
|
|
63
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* Read-only aggregate snapshot for `GET /feedback-factory/stats`. Pure read —
|
|
85
|
+
* never mutates. `byStatus` buckets every feedback row by its `status`
|
|
86
|
+
* (defaulting an absent status to 'unprocessed', mirroring getUnprocessedFeedback).
|
|
87
|
+
* `lastWriteAt` is the latest content timestamp across all entities
|
|
88
|
+
* (feedback.receivedAt, cluster.updatedAt/createdAt, dispatch.createdAt) — a
|
|
89
|
+
* deterministic, content-derived high-water mark, null when the store is empty.
|
|
90
|
+
*/
|
|
91
|
+
stats(): {
|
|
92
|
+
total: number;
|
|
93
|
+
byStatus: Record<string, number>;
|
|
94
|
+
clusterCount: number;
|
|
95
|
+
dispatchCount: number;
|
|
96
|
+
lastWriteAt: string | null;
|
|
97
|
+
};
|
|
64
98
|
}
|
|
65
99
|
//# sourceMappingURL=JsonlFeedbackStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonlFeedbackStore.d.ts","sourceRoot":"","sources":["../../../src/feedback-factory/store/JsonlFeedbackStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAWzE,qBAAa,kBAAmB,YAAW,aAAa;IAU1C,OAAO,CAAC,QAAQ,CAAC,GAAG;IAThC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"JsonlFeedbackStore.d.ts","sourceRoot":"","sources":["../../../src/feedback-factory/store/JsonlFeedbackStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAWzE,qBAAa,kBAAmB,YAAW,aAAa;IAU1C,OAAO,CAAC,QAAQ,CAAC,GAAG;IAThC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,MAAM,CAAwE;gBAEzD,GAAG,EAAE,MAAM;IASxC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,IAAI,IAAI;IAId,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,aAAa;IAMrB,sBAAsB,IAAI,YAAY,EAAE;IAMxC,iBAAiB,IAAI,OAAO,EAAE;IAI9B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIlD,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI;IAmBlE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAS9D,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAY9D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAU1D,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIxC,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAMrC,cAAc,CAAC,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,EAAE;IAQ5E,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI9D,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAM5C,OAAO,IAAI,eAAe;IAI1B,sDAAsD;IACtD,KAAK,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAInE;;;;;;;OAOG;IACH,KAAK,IAAI;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B;CA4BF"}
|
|
@@ -42,6 +42,29 @@ export class JsonlFeedbackStore {
|
|
|
42
42
|
this.feedbackPath = join(dir, 'feedback.jsonl');
|
|
43
43
|
this.clustersPath = join(dir, 'clusters.jsonl');
|
|
44
44
|
this.dispatchesPath = join(dir, 'dispatches.jsonl');
|
|
45
|
+
this.loadAll();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Re-fold all three on-disk JSONL files into fresh in-memory state — the SAME
|
|
49
|
+
* load the constructor runs. Use this when another PROCESS may have appended to
|
|
50
|
+
* the shared store since this instance was built (e.g. the InboxDrainer, a
|
|
51
|
+
* separate launchd process, appends `unprocessed` rows to `feedback.jsonl`
|
|
52
|
+
* continuously; without a reload this in-memory Map is frozen at construction
|
|
53
|
+
* time and the processing pass becomes a permanent no-op over everything
|
|
54
|
+
* ingested after boot).
|
|
55
|
+
*
|
|
56
|
+
* Concurrency: this is a read-only re-fold and appends are atomic single-line
|
|
57
|
+
* writes (appendFileSync). A reload that races a mid-append at worst skips one
|
|
58
|
+
* torn trailing line (already handled by loadJsonl's torn-line skip); the next
|
|
59
|
+
* reload picks up the completed line — identical to the constructor's load path.
|
|
60
|
+
* The in-memory `counts` (FeedbackMetrics) are session-scoped tallies of THIS
|
|
61
|
+
* instance's own mutations, not durable rows, so they are intentionally NOT
|
|
62
|
+
* reset by a reload.
|
|
63
|
+
*/
|
|
64
|
+
reload() {
|
|
65
|
+
this.loadAll();
|
|
66
|
+
}
|
|
67
|
+
loadAll() {
|
|
45
68
|
this.feedback = this.loadAndMaybeCompact(this.feedbackPath, (r) => pickId(r, 'feedbackId', 'feedback_id', 'id'));
|
|
46
69
|
this.clusters = this.loadAndMaybeCompact(this.clustersPath, (r) => pickId(r, 'clusterId', 'cluster_id', 'id'));
|
|
47
70
|
this.dispatches = this.loadAndMaybeCompact(this.dispatchesPath, (r) => pickId(r, 'dispatchId', 'dispatch_id', 'id'));
|
|
@@ -154,6 +177,42 @@ export class JsonlFeedbackStore {
|
|
|
154
177
|
sizes() {
|
|
155
178
|
return { feedback: this.feedback.size, clusters: this.clusters.size, dispatches: this.dispatches.size };
|
|
156
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Read-only aggregate snapshot for `GET /feedback-factory/stats`. Pure read —
|
|
182
|
+
* never mutates. `byStatus` buckets every feedback row by its `status`
|
|
183
|
+
* (defaulting an absent status to 'unprocessed', mirroring getUnprocessedFeedback).
|
|
184
|
+
* `lastWriteAt` is the latest content timestamp across all entities
|
|
185
|
+
* (feedback.receivedAt, cluster.updatedAt/createdAt, dispatch.createdAt) — a
|
|
186
|
+
* deterministic, content-derived high-water mark, null when the store is empty.
|
|
187
|
+
*/
|
|
188
|
+
stats() {
|
|
189
|
+
const byStatus = {};
|
|
190
|
+
let lastWriteAt = null;
|
|
191
|
+
const consider = (ts) => {
|
|
192
|
+
if (typeof ts === 'string' && ts.length > 0 && (lastWriteAt === null || ts > lastWriteAt)) {
|
|
193
|
+
lastWriteAt = ts;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
for (const f of this.feedback.values()) {
|
|
197
|
+
const status = (f.status ?? 'unprocessed');
|
|
198
|
+
byStatus[status] = (byStatus[status] ?? 0) + 1;
|
|
199
|
+
consider(f.receivedAt);
|
|
200
|
+
}
|
|
201
|
+
for (const c of this.clusters.values()) {
|
|
202
|
+
consider(c.updatedAt);
|
|
203
|
+
consider(c.createdAt);
|
|
204
|
+
}
|
|
205
|
+
for (const d of this.dispatches.values()) {
|
|
206
|
+
consider(d.createdAt);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
total: this.feedback.size,
|
|
210
|
+
byStatus,
|
|
211
|
+
clusterCount: this.clusters.size,
|
|
212
|
+
dispatchCount: this.dispatches.size,
|
|
213
|
+
lastWriteAt,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
157
216
|
}
|
|
158
217
|
function loadJsonl(path, idOf) {
|
|
159
218
|
const rows = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonlFeedbackStore.js","sourceRoot":"","sources":["../../../src/feedback-factory/store/JsonlFeedbackStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,kGAAkG;AAClG,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAOrC,MAAM,OAAO,kBAAkB;IAUA;IATZ,YAAY,CAAS;IACrB,YAAY,CAAS;IACrB,cAAc,CAAS;IAEhC,QAAQ,
|
|
1
|
+
{"version":3,"file":"JsonlFeedbackStore.js","sourceRoot":"","sources":["../../../src/feedback-factory/store/JsonlFeedbackStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutonomousProgressHeartbeat — a hedged, change-gated, sparse liveness BACKSTOP
|
|
3
|
+
* for an autonomous run that has gone silent on the user for a long stretch
|
|
4
|
+
* while its terminal output is STILL changing.
|
|
5
|
+
*
|
|
6
|
+
* Spec: docs/specs/autonomous-progress-heartbeat.md (ELI16: .eli16.md).
|
|
7
|
+
*
|
|
8
|
+
* The incident this closes (2026-06-16, topic 12476): during a 24h autonomous
|
|
9
|
+
* run the agent finished a milestone, said "PR is armed", then went heads-down
|
|
10
|
+
* for ~an hour fixing CI — real work the whole time, but emitted ZERO
|
|
11
|
+
* user-facing message. An hour of silence is indistinguishable from a stall.
|
|
12
|
+
*
|
|
13
|
+
* This is NOT the suppressed PromiseBeacon §B1 "still on it, no new output"
|
|
14
|
+
* filler (HONEST-PROGRESS-MESSAGING removed that). It is a structurally higher
|
|
15
|
+
* bar: it fires ONLY on a LONG user-silence gate (≥25m) AND a corroborated
|
|
16
|
+
* recent output change (read from ActiveWorkSilenceSentinel's already-computed
|
|
17
|
+
* `lastOutputAt` snapshot — predicate #8 captures NOTHING of its own), with
|
|
18
|
+
* purely-observational wording, a per-topic cooldown, a widening per-run backoff
|
|
19
|
+
* + hard cap, and the shared one-voice ProxyCoordinator lease.
|
|
20
|
+
*
|
|
21
|
+
* Signal-only: it emits a liveness message and never gates, blocks, delays, or
|
|
22
|
+
* rewrites anything. Every predicate fails CLOSED (no emit) on any uncertainty.
|
|
23
|
+
*/
|
|
24
|
+
import { EventEmitter } from 'node:events';
|
|
25
|
+
import type { ProxyCoordinator } from './ProxyCoordinator.js';
|
|
26
|
+
export interface AutonomousHeartbeatConfig {
|
|
27
|
+
/** Master switch (resolved by the dev-gate at construction; absent → off). */
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
/** dryRun: log the intended heartbeat instead of sending. Default true. */
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
/** User-silence gate, in minutes. Default 25, floor-clamped to ~5. */
|
|
32
|
+
silenceThresholdMinutes?: number;
|
|
33
|
+
/** Tick cadence, ms. Default 60_000, floor-clamped to ~30_000. */
|
|
34
|
+
tickIntervalMs?: number;
|
|
35
|
+
/** Hard per-run heartbeat cap. Default 6. */
|
|
36
|
+
maxHeartbeatsPerRun?: number;
|
|
37
|
+
/** How recently the shared snapshot's lastOutputAt must have advanced. Default 5m. */
|
|
38
|
+
recentOutputChangeWindowMs?: number;
|
|
39
|
+
}
|
|
40
|
+
/** A topic with a live autonomous run, surfaced for the per-topic predicate. */
|
|
41
|
+
export interface ActiveAutonomousRun {
|
|
42
|
+
topicId: number;
|
|
43
|
+
/** The tmux session bound to the topic (for #4 alive + #8 snapshot lookup). */
|
|
44
|
+
sessionName: string | null;
|
|
45
|
+
/** Seconds remaining on the run window (from autonomousRunRemainingForTopic). */
|
|
46
|
+
remainingSeconds: number;
|
|
47
|
+
}
|
|
48
|
+
/** Run-state markers (predicate #2 mid-move + #3 warmup). */
|
|
49
|
+
export interface RunMarkers {
|
|
50
|
+
movedTo: string | null;
|
|
51
|
+
moveSuspended: boolean;
|
|
52
|
+
startedAtMs: number | null;
|
|
53
|
+
}
|
|
54
|
+
/** A single outbound-history entry (predicate #5 silence-clock). */
|
|
55
|
+
export interface OutboundHistoryEntry {
|
|
56
|
+
/** true = inbound user message; false = an outbound (agent/proxy/system) send. */
|
|
57
|
+
fromUser: boolean;
|
|
58
|
+
/** epoch ms of the entry. */
|
|
59
|
+
at: number;
|
|
60
|
+
}
|
|
61
|
+
export interface AutonomousHeartbeatDeps {
|
|
62
|
+
/** Cheap, in-memory: topics with a live autonomous run (predicate #1). */
|
|
63
|
+
listActiveAutonomousRuns: () => ActiveAutonomousRun[];
|
|
64
|
+
/** Read the run-state markers for #2 (mid-move) + #3 (warmup). Null fails closed. */
|
|
65
|
+
getRunMarkers: (topicId: number) => RunMarkers | null;
|
|
66
|
+
/** Predicate #4: is the bound session alive? */
|
|
67
|
+
isSessionAlive: (sessionName: string) => boolean;
|
|
68
|
+
/** Predicate #5: the topic's recent outbound history (most-recent first or any order). */
|
|
69
|
+
getTopicHistory: (topicId: number) => OutboundHistoryEntry[];
|
|
70
|
+
/**
|
|
71
|
+
* Predicate #8: ActiveWorkSilenceSentinel's ALREADY-COMPUTED lastOutputAt for
|
|
72
|
+
* a session (the shared OutputActivityTracker snapshot — NOT a capture). Return
|
|
73
|
+
* the lastOutputAt epoch ms, or null/undefined when the snapshot is unavailable
|
|
74
|
+
* or the session is absent (fails CLOSED — never an own capture).
|
|
75
|
+
*/
|
|
76
|
+
getSharedLastOutputAt: (sessionName: string) => number | null | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* The matching topic's one-line `focus` from ParallelActivityIndex.activities().
|
|
79
|
+
* Indexed by topic ONCE per tick by the caller. Null when unavailable.
|
|
80
|
+
*/
|
|
81
|
+
getFocusForTopic: (topicId: number) => string | null;
|
|
82
|
+
/** Predicate #9: the shared one-voice lease. */
|
|
83
|
+
proxyCoordinator: ProxyCoordinator;
|
|
84
|
+
/** The SAME canonical funnel PromiseBeacon uses (POST /telegram/reply/:topicId). */
|
|
85
|
+
sendMessage: (topicId: number, text: string, metadata: {
|
|
86
|
+
source: 'autonomous-heartbeat';
|
|
87
|
+
isProxy: true;
|
|
88
|
+
tier: number;
|
|
89
|
+
}) => Promise<void>;
|
|
90
|
+
/** Override Date.now for tests. */
|
|
91
|
+
now?: () => number;
|
|
92
|
+
/** Override timer setters for tests. */
|
|
93
|
+
setTimer?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
94
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
95
|
+
}
|
|
96
|
+
/** A ring-buffer record of an emit (or dry-run would-emit / suppression). */
|
|
97
|
+
export interface HeartbeatEmit {
|
|
98
|
+
topicId: number;
|
|
99
|
+
at: number;
|
|
100
|
+
minutesSilent: number;
|
|
101
|
+
/** The ALREADY-SCRUBBED focus (never raw attacker content), or null when generic. */
|
|
102
|
+
focus: string | null;
|
|
103
|
+
dryRun: boolean;
|
|
104
|
+
/** Set when this record is a SUPPRESSION (no emit) rather than an emit. */
|
|
105
|
+
suppressedReason?: string;
|
|
106
|
+
}
|
|
107
|
+
export declare class AutonomousProgressHeartbeat extends EventEmitter {
|
|
108
|
+
private readonly deps;
|
|
109
|
+
private readonly cfg;
|
|
110
|
+
private readonly runState;
|
|
111
|
+
private readonly lastEmits;
|
|
112
|
+
private static readonly LAST_EMITS_CAP;
|
|
113
|
+
private tickHandle;
|
|
114
|
+
private ticking;
|
|
115
|
+
private lastTickAt;
|
|
116
|
+
private topicsConsidered;
|
|
117
|
+
constructor(deps: AutonomousHeartbeatDeps, raw?: AutonomousHeartbeatConfig);
|
|
118
|
+
start(): void;
|
|
119
|
+
stop(): void;
|
|
120
|
+
/** Read-only status for GET /autonomous-heartbeat. */
|
|
121
|
+
status(): {
|
|
122
|
+
enabled: boolean;
|
|
123
|
+
dryRun: boolean;
|
|
124
|
+
silenceThresholdMinutes: number;
|
|
125
|
+
lastTickAt: number;
|
|
126
|
+
topicsConsidered: number;
|
|
127
|
+
lastEmits: HeartbeatEmit[];
|
|
128
|
+
};
|
|
129
|
+
/** Guard-posture surface (GET /guards). Cheap property read — no I/O. */
|
|
130
|
+
guardStatus(): {
|
|
131
|
+
enabled: boolean;
|
|
132
|
+
lastTickAt: number;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* One tick. Re-entrancy-guarded (the emit step is awaited and a send can
|
|
136
|
+
* block). Evaluates the per-topic predicate cheap-first; the ProxyCoordinator
|
|
137
|
+
* lease is acquired/released in a try/finally within THIS tick.
|
|
138
|
+
*
|
|
139
|
+
* Public for tests.
|
|
140
|
+
*/
|
|
141
|
+
tick(): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* The per-topic predicate, evaluated strictly cheapest-first, short-circuiting
|
|
144
|
+
* on the first failure. Predicate #1 (run active) is implied by `run` being in
|
|
145
|
+
* the active set. Every predicate is an in-memory read.
|
|
146
|
+
*/
|
|
147
|
+
private evaluateTopic;
|
|
148
|
+
/**
|
|
149
|
+
* The purely-observational, untrusted-framed line. NEVER an assertive "still
|
|
150
|
+
* working"/"still going" claim. `focus` is already scrubbed + HTML-escaped;
|
|
151
|
+
* null → the generic fallback.
|
|
152
|
+
*/
|
|
153
|
+
buildMessage(focus: string | null): string;
|
|
154
|
+
/** Most-recent outbound (fromUser===false) entry time, or null when none. */
|
|
155
|
+
private mostRecentOutboundAt;
|
|
156
|
+
private ensureRunState;
|
|
157
|
+
/**
|
|
158
|
+
* The cooldown (ms) that must elapse before the NEXT heartbeat, given how many
|
|
159
|
+
* have already fired on this run (`count`). The gap WIDENS with each heartbeat:
|
|
160
|
+
* the 1st→2nd gap is ladder[0] (25m), the 2nd→3rd gap is ladder[1] (40m), …
|
|
161
|
+
* (then holds at the last ladder value). So the index is `count-1` (the number
|
|
162
|
+
* of gaps already opened). Floored at silenceThresholdMinutes — the ladder
|
|
163
|
+
* never goes below the user-silence gate.
|
|
164
|
+
*/
|
|
165
|
+
private currentBackoffMs;
|
|
166
|
+
private recordEmit;
|
|
167
|
+
private recordSuppressed;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=AutonomousProgressHeartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutonomousProgressHeartbeat.d.ts","sourceRoot":"","sources":["../../src/monitoring/AutonomousProgressHeartbeat.ts"],"names":[],"mappings":"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"}
|