instar 1.3.931 → 1.3.933
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/dashboard/glance.js +1 -0
- package/dashboard/index.html +18 -0
- package/dist/messaging/slack/SlackApiClient.d.ts +8 -0
- package/dist/messaging/slack/SlackApiClient.d.ts.map +1 -1
- package/dist/messaging/slack/SlackApiClient.js +44 -2
- package/dist/messaging/slack/SlackApiClient.js.map +1 -1
- 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/throughputRoutes.d.ts +53 -0
- package/dist/server/throughputRoutes.d.ts.map +1 -0
- package/dist/server/throughputRoutes.js +98 -0
- package/dist/server/throughputRoutes.js.map +1 -0
- package/package.json +2 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.932.md +29 -0
- package/upgrades/1.3.933.md +22 -0
- package/upgrades/side-effects/dashboard-throughput.md +77 -0
- package/upgrades/side-effects/slack-outbound-transport-recovery.md +14 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
type Author = 'codey' | 'echo' | 'other';
|
|
3
|
+
type Weights = {
|
|
4
|
+
velocity: number;
|
|
5
|
+
speed: number;
|
|
6
|
+
quality: number;
|
|
7
|
+
output: number;
|
|
8
|
+
};
|
|
9
|
+
type GhExec = (args: string[]) => Promise<{
|
|
10
|
+
code: number;
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
}>;
|
|
14
|
+
export declare const DEFAULT_THROUGHPUT_WEIGHTS: Weights;
|
|
15
|
+
/** Canonical server-owned implementation of Echo's throughput-metrics.mjs contract. */
|
|
16
|
+
export declare function buildThroughputSeries(opts: {
|
|
17
|
+
days: 7 | 14 | 30;
|
|
18
|
+
now?: Date;
|
|
19
|
+
run?: GhExec;
|
|
20
|
+
weights?: Weights;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
repo: string;
|
|
23
|
+
windowDays: 7 | 30 | 14;
|
|
24
|
+
generatedAt: string;
|
|
25
|
+
weights: Weights;
|
|
26
|
+
rows: {
|
|
27
|
+
day: string;
|
|
28
|
+
authors: Partial<Record<Author, {
|
|
29
|
+
merges: number;
|
|
30
|
+
medianLatencyH: number;
|
|
31
|
+
reworkLoops: number;
|
|
32
|
+
reverts: number;
|
|
33
|
+
medianPushIters: number;
|
|
34
|
+
medianLoc: number;
|
|
35
|
+
}>>;
|
|
36
|
+
team: {
|
|
37
|
+
dayLoc: number;
|
|
38
|
+
index: number;
|
|
39
|
+
merges: number;
|
|
40
|
+
medianLatencyH: number;
|
|
41
|
+
reworkLoops: number;
|
|
42
|
+
reverts: number;
|
|
43
|
+
medianPushIters: number;
|
|
44
|
+
medianLoc: number;
|
|
45
|
+
};
|
|
46
|
+
}[];
|
|
47
|
+
}>;
|
|
48
|
+
export declare function createThroughputRoutes(options?: {
|
|
49
|
+
run?: GhExec;
|
|
50
|
+
weights?: Weights;
|
|
51
|
+
}): Router;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=throughputRoutes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throughputRoutes.d.ts","sourceRoot":"","sources":["../../src/server/throughputRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAU9D,KAAK,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AACzC,KAAK,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACpF,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAI5F,eAAO,MAAM,0BAA0B,EAAE,OAAkE,CAAC;AAyC5G,uFAAuF;AACvF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;GAwBnH;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAYhG"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { Router } from 'express';
|
|
3
|
+
export const DEFAULT_THROUGHPUT_WEIGHTS = { velocity: .40, speed: .20, quality: .25, output: .15 };
|
|
4
|
+
const WINDOWS = [7, 14, 30];
|
|
5
|
+
const ZERO = () => ({ merges: 0, medianLatencyH: 0, reworkLoops: 0, reverts: 0, medianPushIters: 0, medianLoc: 0 });
|
|
6
|
+
function gh(args) {
|
|
7
|
+
return new Promise(resolve => execFile('gh', args, { timeout: 30_000, maxBuffer: 32 * 1024 * 1024 }, (err, stdout, stderr) => resolve({ code: err ? 1 : 0, stdout: stdout ?? '', stderr: stderr ?? '' })));
|
|
8
|
+
}
|
|
9
|
+
function median(values) {
|
|
10
|
+
if (!values.length)
|
|
11
|
+
return 0;
|
|
12
|
+
const a = [...values].sort((x, y) => x - y);
|
|
13
|
+
const m = Math.floor(a.length / 2);
|
|
14
|
+
return Math.round((a.length % 2 ? a[m] : (a[m - 1] + a[m]) / 2) * 10) / 10;
|
|
15
|
+
}
|
|
16
|
+
function authorOf(login) { return login === 'JKHeadley' ? 'codey' : login === 'EchoOfDawn' ? 'echo' : 'other'; }
|
|
17
|
+
function pdtDay(iso) { return new Date(Date.parse(iso) - 7 * 3_600_000).toISOString().slice(0, 10); }
|
|
18
|
+
function metrics(prs, details) {
|
|
19
|
+
return {
|
|
20
|
+
merges: prs.length,
|
|
21
|
+
medianLatencyH: median(prs.map(p => (Date.parse(p.mergedAt) - Date.parse(p.createdAt)) / 3_600_000)),
|
|
22
|
+
reworkLoops: prs.reduce((n, p) => n + (details.get(p.number)?.reworkLoops ?? 0), 0),
|
|
23
|
+
reverts: prs.filter(p => /^revert/i.test(p.title)).length,
|
|
24
|
+
medianPushIters: median(prs.map(p => details.get(p.number)?.commits ?? 0)),
|
|
25
|
+
medianLoc: median(prs.map(p => p.additions + p.deletions)),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function detailMap(numbers, run) {
|
|
29
|
+
const out = new Map();
|
|
30
|
+
for (let offset = 0; offset < numbers.length; offset += 50) {
|
|
31
|
+
const batch = numbers.slice(offset, offset + 50);
|
|
32
|
+
const fields = batch.map(n => `p${n}:pullRequest(number:${n}){number reviews(first:30){nodes{state}} commits{totalCount}}`).join(' ');
|
|
33
|
+
const r = await run(['api', 'graphql', '-f', `query=query{repository(owner:"JKHeadley",name:"instar"){${fields}}}`]);
|
|
34
|
+
if (r.code)
|
|
35
|
+
throw new Error(`github-details-unavailable: ${r.stderr.slice(0, 120)}`);
|
|
36
|
+
const repo = JSON.parse(r.stdout)?.data?.repository ?? {};
|
|
37
|
+
for (const n of batch) {
|
|
38
|
+
const p = repo[`p${n}`];
|
|
39
|
+
if (!p)
|
|
40
|
+
continue;
|
|
41
|
+
out.set(n, { reworkLoops: (p.reviews?.nodes ?? []).filter((x) => x.state === 'CHANGES_REQUESTED').length, commits: Number(p.commits?.totalCount ?? 0) });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/** Canonical server-owned implementation of Echo's throughput-metrics.mjs contract. */
|
|
47
|
+
export async function buildThroughputSeries(opts) {
|
|
48
|
+
const now = opts.now ?? new Date();
|
|
49
|
+
const run = opts.run ?? gh;
|
|
50
|
+
const weights = opts.weights ?? DEFAULT_THROUGHPUT_WEIGHTS;
|
|
51
|
+
const cutoff = now.getTime() - opts.days * 86_400_000;
|
|
52
|
+
const listed = await run(['pr', 'list', '--repo', 'JKHeadley/instar', '--state', 'merged', '--limit', '400', '--json', 'number,title,author,mergedAt,createdAt,additions,deletions']);
|
|
53
|
+
if (listed.code)
|
|
54
|
+
throw new Error(`github-list-unavailable: ${listed.stderr.slice(0, 120)}`);
|
|
55
|
+
const prs = JSON.parse(listed.stdout).filter(p => Date.parse(p.mergedAt) >= cutoff && Date.parse(p.mergedAt) <= now.getTime());
|
|
56
|
+
const details = await detailMap(prs.map(p => p.number), run);
|
|
57
|
+
const days = new Map();
|
|
58
|
+
for (const p of prs)
|
|
59
|
+
days.set(pdtDay(p.mergedAt), [...(days.get(pdtDay(p.mergedAt)) ?? []), p]);
|
|
60
|
+
const rows = [...days].sort(([a], [b]) => a.localeCompare(b)).map(([day, all]) => {
|
|
61
|
+
const authors = {};
|
|
62
|
+
for (const a of ['codey', 'echo', 'other']) {
|
|
63
|
+
const own = all.filter(p => authorOf(p.author?.login) === a);
|
|
64
|
+
if (own.length)
|
|
65
|
+
authors[a] = metrics(own, details);
|
|
66
|
+
}
|
|
67
|
+
return { day, authors, team: { ...metrics(all, details), dayLoc: all.reduce((n, p) => n + p.additions + p.deletions, 0), index: 0 } };
|
|
68
|
+
});
|
|
69
|
+
const maxM = Math.max(1, ...rows.map(r => r.team.merges));
|
|
70
|
+
const maxL = Math.max(1, ...rows.map(r => r.team.medianLatencyH));
|
|
71
|
+
const maxLoc = Math.max(1, ...rows.map(r => r.team.dayLoc));
|
|
72
|
+
for (const r of rows) {
|
|
73
|
+
const v = r.team.merges / maxM;
|
|
74
|
+
const s = 1 - r.team.medianLatencyH / maxL;
|
|
75
|
+
const q = 1 - Math.min(1, (r.team.reworkLoops + 2 * r.team.reverts) / r.team.merges);
|
|
76
|
+
const o = Math.log1p(r.team.dayLoc) / Math.log1p(maxLoc);
|
|
77
|
+
r.team.index = Math.round(1000 * (weights.velocity * v + weights.speed * s + weights.quality * q + weights.output * o)) / 10;
|
|
78
|
+
}
|
|
79
|
+
return { repo: 'JKHeadley/instar', windowDays: opts.days, generatedAt: now.toISOString(), weights, rows };
|
|
80
|
+
}
|
|
81
|
+
export function createThroughputRoutes(options = {}) {
|
|
82
|
+
const router = Router();
|
|
83
|
+
router.get('/throughput/series', async (req, res) => {
|
|
84
|
+
const days = Number(req.query.days ?? 14);
|
|
85
|
+
if (!WINDOWS.includes(days)) {
|
|
86
|
+
res.status(400).json({ error: 'invalid-throughput-window', allowed: WINDOWS });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
res.set('Cache-Control', 'private, max-age=60').json(await buildThroughputSeries({ days: days, ...options }));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
res.status(503).json({ error: 'throughput-series-unavailable' });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return router;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=throughputRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throughputRoutes.js","sourceRoot":"","sources":["../../src/server/throughputRoutes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instar",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.933",
|
|
4
4
|
"description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"proper-lockfile": "^4.1.2",
|
|
130
130
|
"ssh2": "1.17.0",
|
|
131
131
|
"telegram": "^2.26.22",
|
|
132
|
+
"undici": "^6.27.0",
|
|
132
133
|
"ws": "^8.19.0",
|
|
133
134
|
"zod": "^4.3.6"
|
|
134
135
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-24T13:04:17.807Z",
|
|
5
|
+
"instarVersion": "1.3.933",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -1530,7 +1530,7 @@
|
|
|
1530
1530
|
"type": "subsystem",
|
|
1531
1531
|
"domain": "server",
|
|
1532
1532
|
"sourcePath": "src/server/AgentServer.ts",
|
|
1533
|
-
"contentHash": "
|
|
1533
|
+
"contentHash": "ea6bc1c5440b492c3127aba0367ee4e2248c29aedf59126f484d14402c78d90b",
|
|
1534
1534
|
"since": "2025-01-01"
|
|
1535
1535
|
},
|
|
1536
1536
|
"subsystem:session-manager": {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
After three consecutive network-level `fetch failed` errors, the Slack API
|
|
9
|
+
client replaces its own undici dispatcher and retries through a fresh
|
|
10
|
+
connection pool. Successful calls reset the failure streak. The recovery pool
|
|
11
|
+
is scoped to Slack requests only — unrelated HTTP clients are not affected.
|
|
12
|
+
`undici` is now a declared dependency (it was previously imported as a
|
|
13
|
+
transitive package).
|
|
14
|
+
|
|
15
|
+
## What to Tell Your User
|
|
16
|
+
|
|
17
|
+
After a laptop network change (new Wi-Fi, hotspot, VPN flip), outbound Slack
|
|
18
|
+
delivery now recovers on its own within a few failed attempts instead of
|
|
19
|
+
staying dead until a server restart. Nothing to configure.
|
|
20
|
+
|
|
21
|
+
## Summary of New Capabilities
|
|
22
|
+
|
|
23
|
+
- Slack outbound transport self-heals after network interface changes.
|
|
24
|
+
- Recovery is scoped to the Slack client's own connection pool.
|
|
25
|
+
|
|
26
|
+
## Verification
|
|
27
|
+
|
|
28
|
+
Tier 1 focused evidence: `tests/unit/slack-socket-reconnect.test.ts` — 17/17
|
|
29
|
+
passing. Slack API response and retry semantics are unchanged.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The dashboard now has a read-only Throughput tab backed by a canonical `/throughput/series` route.
|
|
9
|
+
|
|
10
|
+
## What to Tell Your User
|
|
11
|
+
|
|
12
|
+
Use Throughput to compare Codey, Echo, or team delivery across 7, 14, or 30 days, including a single composite index.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
- Charts merges, merge latency, rework, reverts, commit iterations, changed lines, and the composite index.
|
|
17
|
+
- Uses the documented V40/S20/Q25/O15 weights and returns those weights in the API contract.
|
|
18
|
+
- Reads GitHub pull-request data without mutating repository or runtime state.
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
The metric contract, dashboard registry, panel placement, URL state, navigation, and viewport floors pass locally. TypeScript and repository invariants pass, with browser verification at 2560px and 390px.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Side-Effects Review — Dashboard Throughput
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `dashboard-throughput`
|
|
4
|
+
**Date:** 2026-07-24
|
|
5
|
+
**Author:** Instar-codey
|
|
6
|
+
**Second-pass reviewer:** not required
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Adds a read-only dashboard tab and server route that derive daily pull-request delivery metrics from bounded, structured GitHub CLI responses. The browser renders the server-owned contract and never writes GitHub or Instar state.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
No behavioral decision point. The only rejection is structural API validation limiting windows to 7, 14, or 30 days.
|
|
15
|
+
|
|
16
|
+
## 1. Over-block
|
|
17
|
+
|
|
18
|
+
Malformed or unsupported window values receive 400. Valid documented windows are all accepted; there is no message or action block surface.
|
|
19
|
+
|
|
20
|
+
## 2. Under-block
|
|
21
|
+
|
|
22
|
+
GitHub outages and malformed responses return 503 rather than plausible zero data. The metric remains limited by GitHub's bounded review list (30 reviews per PR) and 400 merged PR list.
|
|
23
|
+
|
|
24
|
+
## 3. Level-of-abstraction fit
|
|
25
|
+
|
|
26
|
+
Aggregation belongs on the server because it is the canonical contract and can safely execute structured `gh` calls. The browser only selects and plots.
|
|
27
|
+
|
|
28
|
+
## 4. Signal vs authority compliance
|
|
29
|
+
|
|
30
|
+
Required reference: [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
31
|
+
|
|
32
|
+
- [x] No — this change has no block/allow surface.
|
|
33
|
+
|
|
34
|
+
These are observational signals only and authorize no action.
|
|
35
|
+
|
|
36
|
+
## 4b. Judgment-point check
|
|
37
|
+
|
|
38
|
+
No static heuristic is added at a competing-signals decision point. The published composite is descriptive arithmetic with returned weights, not an authority.
|
|
39
|
+
|
|
40
|
+
## 5. Interactions
|
|
41
|
+
|
|
42
|
+
The route uses authenticated dashboard middleware already owned by AgentServer. A one-minute private cache header reduces repeated reads. It shares no mutable state, so there is no double-fire, race, or feedback loop.
|
|
43
|
+
|
|
44
|
+
## 6. External surfaces
|
|
45
|
+
|
|
46
|
+
The external read surface is GitHub pull-request metadata. The user-visible dashboard adds no operator action and no persistent state.
|
|
47
|
+
|
|
48
|
+
## 6b. Operator-surface quality
|
|
49
|
+
|
|
50
|
+
1. The primary content—the index and charts—is visible immediately.
|
|
51
|
+
2. Labels are plain language; no hashes, JSON, or internal identifiers are primary content.
|
|
52
|
+
3. There are no destructive actions.
|
|
53
|
+
4. Selectors and all seven charts were browser-verified at 2560px and 390px; phone layout is one column with no horizontal overflow.
|
|
54
|
+
|
|
55
|
+
## 7. Multi-machine posture
|
|
56
|
+
|
|
57
|
+
**Proxied-on-read:** each machine computes the same repository-global GitHub view on request. There is no durable state to replicate, no notice requiring one-voice gating, and no generated URL.
|
|
58
|
+
|
|
59
|
+
## 8. Rollback cost
|
|
60
|
+
|
|
61
|
+
Pure code rollback: revert the route registration and tab, then ship a patch. No data migration or agent-state repair is required.
|
|
62
|
+
|
|
63
|
+
## Conclusion
|
|
64
|
+
|
|
65
|
+
The review moved all metric and index ownership server-side, made GitHub failure explicit, and kept the dashboard fluid and read-only. Clear to ship.
|
|
66
|
+
|
|
67
|
+
## Second-pass review
|
|
68
|
+
|
|
69
|
+
Not required: no messaging, lifecycle, dispatch, context-recovery, coherence, trust, sentinel, guard, gate, or watchdog authority changes.
|
|
70
|
+
|
|
71
|
+
## Evidence pointers
|
|
72
|
+
|
|
73
|
+
Focused suite: 127 passed, one pre-existing conditional skip. TypeScript and repository invariants pass. Browser captures: `throughput-2560.png` and `throughput-390.png`.
|
|
74
|
+
|
|
75
|
+
## Class-Closure Declaration
|
|
76
|
+
|
|
77
|
+
No agent-authored-artifact defect — not applicable.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Side-effects Review — Slack outbound transport recovery
|
|
2
|
+
|
|
3
|
+
## Class review
|
|
4
|
+
|
|
5
|
+
The missing standard was transport recovery after interface changes: retrying the same undici pool was not evidence of a fresh network path. The process gap was no focused fault-injection check for repeated `fetch failed` across a Wi-Fi transition.
|
|
6
|
+
|
|
7
|
+
## Decision
|
|
8
|
+
|
|
9
|
+
The client keeps normal API retry behavior. On three consecutive network fetch failures it destroys and replaces a Slack-client-owned undici dispatcher supplied per request; unrelated HTTP clients are not affected. Successful calls clear the streak.
|
|
10
|
+
|
|
11
|
+
## Evidence
|
|
12
|
+
|
|
13
|
+
- Tier 1 focused Socket Mode reconnect suite: 17/17 passing.
|
|
14
|
+
- ELI16: stale sockets are thrown away after three failed tries; the next try gets a fresh network path.
|