@notis_ai/cli 0.2.0-beta.179.1 → 0.2.0-beta.181.1

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.
@@ -11820,7 +11820,7 @@ var SAFE_VIEWPORT_HEIGHT_SCRIPT = `(() => {
11820
11820
  })()`;
11821
11821
 
11822
11822
  // src/runtime/agent-browser.js
11823
- var PREPARE_CAPTURE_SCRIPT = "(() => { const s = document.getElementById('harness-status'); if (s) s.style.display = 'none'; const r = document.getElementById('root'); if (r) { r.style.paddingTop = '0'; r.style.minHeight = '0'; } document.body.style.minHeight = '0'; document.documentElement.style.minHeight = '0'; return true; })()";
11823
+ var PREPARE_CAPTURE_SCRIPT = "(() => { const r = document.getElementById('root'); if (r) r.style.minHeight = '0'; document.body.style.minHeight = '0'; document.documentElement.style.minHeight = '0'; return true; })()";
11824
11824
  var FONTS_STATUS_SCRIPT = "(() => (document.fonts ? document.fonts.status : 'loaded'))()";
11825
11825
  var CONTENT_HEIGHT_SCRIPT = "(() => { const r = document.getElementById('root'); if (!r) return Math.ceil(document.documentElement.scrollHeight); return Math.ceil(Math.max(r.scrollHeight, r.getBoundingClientRect().height)); })()";
11826
11826
  var MIN_CSS_VIEWPORT_HEIGHT = 720;
@@ -12300,7 +12300,7 @@ var DESIGN_ASSERTIONS_SCRIPT = `(() => {
12300
12300
  };
12301
12301
  const all = Array.from(root.querySelectorAll('*'));
12302
12302
  for (const el of all) {
12303
- if (el.id === 'harness-status' || !visible(el) || isControl(el)) continue;
12303
+ if (!visible(el) || isControl(el)) continue;
12304
12304
  if (isBox(el)) {
12305
12305
  let p = el.parentElement; let depth = 0;
12306
12306
  while (p && p !== root && depth < 6) { if (!isControl(p) && isBox(p)) { push('nested_border_box', el); break; } p = p.parentElement; depth += 1; }
@@ -12317,7 +12317,7 @@ var DESIGN_ASSERTIONS_SCRIPT = `(() => {
12317
12317
  const text = (node.textContent || '').trim();
12318
12318
  if (!text) continue;
12319
12319
  const el = node.parentElement;
12320
- if (!el || el.closest('#harness-status') || !visible(el)) continue;
12320
+ if (!el || !visible(el)) continue;
12321
12321
  const size = parseFloat(getComputedStyle(el).fontSize);
12322
12322
  if (size > 0 && size < 12) push('text_below_12px', el, { font_size: size });
12323
12323
  if (/^Loading(\\.{3}|\\u2026)?(\\s|$)/.test(text)) push('loading_placeholder_after_mount', el);
@@ -14201,15 +14201,20 @@ async function appsDeployHandler(ctx) {
14201
14201
  } catch {
14202
14202
  warnings.push("The app was updated, but the temporary release directory needs local cleanup.");
14203
14203
  }
14204
+ const skillReviews = (Array.isArray(result.payload.skill_reviews) ? result.payload.skill_reviews : []).filter((review) => review && typeof review.review_url === "string");
14204
14205
  return ctx.output.emitSuccess({
14205
14206
  command: ctx.spec.command_path.join(" "),
14206
14207
  data: {
14207
14208
  app_id: appId,
14208
14209
  version: deployedVersion,
14209
- idempotency_key: idempotencyKey
14210
+ idempotency_key: idempotencyKey,
14211
+ ...skillReviews.length ? { skill_reviews: skillReviews } : {}
14210
14212
  },
14211
14213
  warnings,
14212
- humanSummary: `Deployed to app ${appId} (version ${deployedVersion})`,
14214
+ humanSummary: [
14215
+ `Deployed to app ${appId} (version ${deployedVersion})`,
14216
+ ...skillReviews.map((review) => `Review ${review.skill} changes: ${review.review_url}`)
14217
+ ].join("\n"),
14213
14218
  meta: { mutating: true, idempotency_key: idempotencyKey }
14214
14219
  });
14215
14220
  } finally {
@@ -368,6 +368,8 @@ export interface RuntimeResource {
368
368
  kind: 'app' | 'report';
369
369
  /** Host-provided adoption eligibility, never report-authored authority. */
370
370
  analytics_eligible?: boolean;
371
+ /** Host-derived report family for adoption analytics, e.g. skill review reports. */
372
+ report_kind?: 'skill_review' | 'custom';
371
373
  id: string;
372
374
  revision: number;
373
375
  name?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notis_ai/cli",
3
- "version": "0.2.0-beta.179.1",
3
+ "version": "0.2.0-beta.181.1",
4
4
  "description": "Agent-first Notis CLI for apps and generic tool execution",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1257,15 +1257,22 @@ async function appsDeployHandler(ctx) {
1257
1257
  try { release.close(); }
1258
1258
  catch { warnings.push('The app was updated, but the temporary release directory needs local cleanup.'); }
1259
1259
 
1260
+ // One review report per skill this release changed; share the link when the user should review it.
1261
+ const skillReviews = (Array.isArray(result.payload.skill_reviews) ? result.payload.skill_reviews : [])
1262
+ .filter((review) => review && typeof review.review_url === 'string');
1260
1263
  return ctx.output.emitSuccess({
1261
1264
  command: ctx.spec.command_path.join(' '),
1262
1265
  data: {
1263
1266
  app_id: appId,
1264
1267
  version: deployedVersion,
1265
1268
  idempotency_key: idempotencyKey,
1269
+ ...(skillReviews.length ? { skill_reviews: skillReviews } : {}),
1266
1270
  },
1267
1271
  warnings,
1268
- humanSummary: `Deployed to app ${appId} (version ${deployedVersion})`,
1272
+ humanSummary: [
1273
+ `Deployed to app ${appId} (version ${deployedVersion})`,
1274
+ ...skillReviews.map((review) => `Review ${review.skill} changes: ${review.review_url}`),
1275
+ ].join('\n'),
1269
1276
  meta: { mutating: true, idempotency_key: idempotencyKey },
1270
1277
  });
1271
1278
  } finally {
@@ -3,18 +3,13 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { dirname } from 'node:path';
4
4
  import { contentCapturePlan, MEASURE_SCREENSHOT_CONTENT_SCRIPT, SAFE_VIEWPORT_HEIGHT_SCRIPT } from './screenshot-framing.js';
5
5
 
6
- export const HIDE_HARNESS_STATUS_SCRIPT =
7
- "(() => { const el = document.getElementById('harness-status'); if (el) el.style.opacity = '0'; return true; })()";
8
-
9
6
  /**
10
- * Prepare the mounted harness page for a listing capture: remove the debug
11
- * banner and the layout the harness adds around the app (top padding for the
12
- * banner, 100vh min-height) so content height can be measured and framed
13
- * without artificial whitespace.
7
+ * Prepare the mounted harness page for a listing capture: remove the 100vh
8
+ * min-height the harness adds around the app so content height can be
9
+ * measured and framed without artificial whitespace.
14
10
  */
15
11
  const PREPARE_CAPTURE_SCRIPT =
16
- "(() => { const s = document.getElementById('harness-status'); if (s) s.style.display = 'none';" +
17
- " const r = document.getElementById('root'); if (r) { r.style.paddingTop = '0'; r.style.minHeight = '0'; }" +
12
+ "(() => { const r = document.getElementById('root'); if (r) r.style.minHeight = '0';" +
18
13
  " document.body.style.minHeight = '0'; document.documentElement.style.minHeight = '0'; return true; })()";
19
14
 
20
15
  const FONTS_STATUS_SCRIPT =
@@ -583,7 +578,7 @@ export const DESIGN_ASSERTIONS_SCRIPT = `(() => {
583
578
  };
584
579
  const all = Array.from(root.querySelectorAll('*'));
585
580
  for (const el of all) {
586
- if (el.id === 'harness-status' || !visible(el) || isControl(el)) continue;
581
+ if (!visible(el) || isControl(el)) continue;
587
582
  if (isBox(el)) {
588
583
  let p = el.parentElement; let depth = 0;
589
584
  while (p && p !== root && depth < 6) { if (!isControl(p) && isBox(p)) { push('nested_border_box', el); break; } p = p.parentElement; depth += 1; }
@@ -600,7 +595,7 @@ export const DESIGN_ASSERTIONS_SCRIPT = `(() => {
600
595
  const text = (node.textContent || '').trim();
601
596
  if (!text) continue;
602
597
  const el = node.parentElement;
603
- if (!el || el.closest('#harness-status') || !visible(el)) continue;
598
+ if (!el || !visible(el)) continue;
604
599
  const size = parseFloat(getComputedStyle(el).fontSize);
605
600
  if (size > 0 && size < 12) push('text_below_12px', el, { font_size: size });
606
601
  if (/^Loading(\\.{3}|\\u2026)?(\\s|$)/.test(text)) push('loading_placeholder_after_mount', el);
@@ -93,12 +93,10 @@
93
93
  color: hsl(var(--foreground));
94
94
  -webkit-font-smoothing: antialiased;
95
95
  }
96
- #harness-status { position: fixed; top: 0; left: 0; right: 0; padding: 4px 8px; font-size: 11px; background: #111; color: #0f0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; z-index: 9999; }
97
- #root { padding-top: 24px; min-height: 100vh; }
96
+ #root { min-height: 100vh; }
98
97
  </style>
99
98
  </head>
100
99
  <body>
101
- <div id="harness-status">harness: booting</div>
102
100
  <div id="root" data-notis-app-root></div>
103
101
  <script type="module">
104
102
  const routeExport = {{ROUTE_EXPORT}};
@@ -134,10 +132,9 @@
134
132
  return Object.prototype.hasOwnProperty.call(tools, name) ? tools[name] : undefined;
135
133
  }
136
134
 
137
- const status = document.getElementById('harness-status');
138
- const setStatus = (msg, color = '#0f0') => {
139
- status.textContent = `harness: ${msg}`;
140
- status.style.color = color;
135
+ // Boot progress goes to the console so the rendered page stays identical to the app.
136
+ const setStatus = (msg, failed = false) => {
137
+ (failed ? console.error : console.info)(`[notis harness] ${msg}`);
141
138
  };
142
139
 
143
140
  window.__harness = {
@@ -416,13 +413,13 @@
416
413
  window.__harness.mounted = true;
417
414
  const errors = window.__harness.errors.length;
418
415
  const calls = window.__harness.runtimeCalls.length;
419
- setStatus(`mounted (errors=${errors}, runtimeCalls=${calls})`, errors ? '#f55' : '#0f0');
416
+ setStatus(`mounted (errors=${errors}, runtimeCalls=${calls})`, errors > 0);
420
417
  } catch (error) {
421
418
  window.__harness.errors.push({
422
419
  type: 'scenario',
423
420
  message: error && error.message ? error.message : String(error),
424
421
  });
425
- setStatus(`scenario failed: ${error && error.message ? error.message : String(error)}`, '#f55');
422
+ setStatus(`scenario failed: ${error && error.message ? error.message : String(error)}`, true);
426
423
  }
427
424
  }));
428
425
  } catch (error) {
@@ -431,7 +428,7 @@
431
428
  message: error && error.message ? error.message : String(error),
432
429
  stack: error && error.stack,
433
430
  });
434
- setStatus(`boot failed: ${error && error.message ? error.message : String(error)}`, '#f55');
431
+ setStatus(`boot failed: ${error && error.message ? error.message : String(error)}`, true);
435
432
  }
436
433
  </script>
437
434
  </body>