selftune 0.2.25 → 0.2.27

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.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>selftune — Dashboard</title>
7
7
  <link rel="icon" type="image/png" href="/favicon.png" />
8
- <script type="module" crossorigin src="/assets/index-Dhgv5BQO.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-bvHYAGBm.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Dw2cE7zH.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-C5oyHiV1.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/vendor-ui-B3BPIYy7.js">
@@ -185,6 +185,50 @@ const MIME_TYPES: Record<string, string> = {
185
185
  ".ico": "image/x-icon",
186
186
  };
187
187
 
188
+ async function serveSpaShell(spaDir: string | null): Promise<Response> {
189
+ if (!spaDir) {
190
+ return new Response("Dashboard build not found. Run `bun run build:dashboard` first.", {
191
+ status: 503,
192
+ headers: { "Content-Type": "text/plain; charset=utf-8", ...corsHeaders() },
193
+ });
194
+ }
195
+
196
+ const indexPath = join(spaDir, "index.html");
197
+ const indexFile = Bun.file(indexPath);
198
+ if (!(await indexFile.exists())) {
199
+ return new Response(
200
+ "Dashboard assets are updating. Retry in a moment or run `selftune dashboard --restart`.",
201
+ {
202
+ status: 503,
203
+ headers: {
204
+ "Content-Type": "text/plain; charset=utf-8",
205
+ "Retry-After": "1",
206
+ ...corsHeaders(),
207
+ },
208
+ },
209
+ );
210
+ }
211
+
212
+ try {
213
+ const html = await indexFile.text();
214
+ return new Response(html, {
215
+ headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
216
+ });
217
+ } catch {
218
+ return new Response(
219
+ "Dashboard assets are updating. Retry in a moment or run `selftune dashboard --restart`.",
220
+ {
221
+ status: 503,
222
+ headers: {
223
+ "Content-Type": "text/plain; charset=utf-8",
224
+ "Retry-After": "1",
225
+ ...corsHeaders(),
226
+ },
227
+ },
228
+ );
229
+ }
230
+ }
231
+
188
232
  async function computeStatusFromDb(): Promise<StatusResult> {
189
233
  const db = getDb();
190
234
  const telemetry = querySessionTelemetry(db);
@@ -519,16 +563,7 @@ export async function startDashboardServer(
519
563
 
520
564
  // ---- GET / ---- Serve SPA shell
521
565
  if (url.pathname === "/" && req.method === "GET") {
522
- if (spaDir) {
523
- const html = await Bun.file(join(spaDir, "index.html")).text();
524
- return new Response(html, {
525
- headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
526
- });
527
- }
528
- return new Response("Dashboard build not found. Run `bun run build:dashboard` first.", {
529
- status: 503,
530
- headers: { "Content-Type": "text/plain; charset=utf-8", ...corsHeaders() },
531
- });
566
+ return serveSpaShell(spaDir);
532
567
  }
533
568
 
534
569
  // ---- POST /api/actions/{watch,evolve,rollback,watchlist} ----
@@ -672,10 +707,7 @@ export async function startDashboardServer(
672
707
 
673
708
  // ---- SPA fallback ----
674
709
  if (spaDir && req.method === "GET" && !url.pathname.startsWith("/api/")) {
675
- const html = await Bun.file(join(spaDir, "index.html")).text();
676
- return new Response(html, {
677
- headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
678
- });
710
+ return serveSpaShell(spaDir);
679
711
  }
680
712
 
681
713
  return new Response("Not Found", { status: 404, headers: corsHeaders() });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selftune",
3
- "version": "0.2.25",
3
+ "version": "0.2.27",
4
4
  "description": "Skill-level observability and self-improvement for AI agents — monitors skill routing, detects missed triggers, and evolves descriptions automatically",
5
5
  "keywords": [
6
6
  "agent",
@@ -86,6 +86,7 @@ describe("OverviewCompositionSurface", () => {
86
86
  expect(html).toContain("After Feed");
87
87
  expect(html.indexOf("Comparison 1")).toBeLessThan(html.indexOf("Before Feed"));
88
88
  expect(html.indexOf("Run Summary 4")).toBeLessThan(html.indexOf("After Feed"));
89
+ expect(html).toContain('<div class="col-span-12"><div>Before Feed</div></div>');
89
90
  });
90
91
 
91
92
  it("omits the comparison block when there are no rows", () => {
@@ -48,7 +48,7 @@ export function OverviewCompositionSurface({
48
48
  <OverviewComparisonSurface {...comparison} renderSkillLink={renderSkillLink} />
49
49
  </div>
50
50
  ) : null}
51
- {sectionsBeforeFeed}
51
+ {sectionsBeforeFeed ? <div className="col-span-12">{sectionsBeforeFeed}</div> : null}
52
52
  </>
53
53
  ) : null;
54
54
 
@@ -28,6 +28,7 @@ export interface SkillReportScaffoldProps {
28
28
  summary?: ReactNode;
29
29
  showOnboardingBanner?: boolean;
30
30
  guideButtonLabel?: string;
31
+ prioritizeChildren?: boolean;
31
32
  nextAction: SkillReportNextAction;
32
33
  trustState: TrustState;
33
34
  coverage?: TrustFields["coverage"];
@@ -52,6 +53,7 @@ export function SkillReportScaffold({
52
53
  summary,
53
54
  showOnboardingBanner = false,
54
55
  guideButtonLabel = "How to read this page",
56
+ prioritizeChildren = false,
55
57
  nextAction,
56
58
  trustState,
57
59
  coverage,
@@ -115,6 +117,8 @@ export function SkillReportScaffold({
115
117
  }
116
118
  />
117
119
 
120
+ {prioritizeChildren && children ? <div className="space-y-4">{children}</div> : null}
121
+
118
122
  <SkillTrustNarrativePanel
119
123
  trustState={trustState}
120
124
  coverage={coverage}
@@ -141,7 +145,7 @@ export function SkillReportScaffold({
141
145
  />
142
146
  </div>
143
147
 
144
- {children ? (
148
+ {children && !prioritizeChildren ? (
145
149
  <div className="space-y-4 border-t border-border/10 pt-4">{children}</div>
146
150
  ) : null}
147
151
  </div>
package/skill/SKILL.md CHANGED
@@ -13,7 +13,7 @@ description: >
13
13
  even if they don't say "selftune" explicitly.
14
14
  metadata:
15
15
  author: selftune-dev
16
- version: 0.2.25
16
+ version: 0.2.27
17
17
  category: developer-tools
18
18
  ---
19
19