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.
@@ -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.931",
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-24T06:06:58.795Z",
5
- "instarVersion": "1.3.931",
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": "59e418f6d422344d2df994a788ac4949fe11c2cf20e811a76f8137d3aceab402",
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.