create-pmos 0.177.0 → 0.179.0

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.
@@ -108,8 +108,9 @@ function header() {
108
108
  S.ttl = el('h1', { 'data-c3pg': 'title' });
109
109
  S.sub = el('div', { class: 'sub', 'data-c3pg': 'date' }, dateLine());
110
110
  S.termBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'term-count' }, '0');
111
- /* the AGENT button (the bolt glyph, as the mockup's Sessions pill): the Terminal page, the full agent surfaces, with the needs-you badge. It is an icon only (PM, 2026-10-12: no "Sessions" label); its tooltip and aria-label name it. Ctrl J and the More menu fold and open the dock. */
112
- S.termBtn = button({ variant: 'ghost', label: [ic('bolt', 'sm'), S.termBdg], onClick: () => { import('./c3-terminal.js').then((m) => m.openTerminalPage()); },
111
+ /* the AGENT button (the bolt glyph, as the mockup's Sessions pill), with the needs-you badge: the terminal of the session opened last while it runs
112
+ * (PM, 2026-10-13), else the Terminal page, the full agent surfaces; the terminal sheet's "All sessions" opens that page. It is an icon only (PM, 2026-10-12: no "Sessions" label); its tooltip and aria-label name it. Ctrl J and the More menu fold and open the dock. */
113
+ S.termBtn = button({ variant: 'ghost', label: [ic('bolt', 'sm'), S.termBdg], onClick: () => { import('./c3-session-term.js').then((m) => m.openLastSession()); },
113
114
  attrs: { class: 'psess', title: 'Agent surfaces: sessions, results to accept, questions for you', 'aria-label': 'Agent surfaces: sessions, results to accept, questions for you', 'aria-haspopup': 'dialog', 'data-c3pg': 'agent-button' } }); // the mockup's header button (agent-surfaces.html #act)
114
115
  S.tools = el('div', { class: 'tools', 'data-c3pg': 'tools' });
115
116
  if (S.demoMod) S.tools.append(S.demoMod.demoPill());
@@ -521,6 +521,19 @@
521
521
  .c3 .cal3-xs{font-size:var(--fs-1)}
522
522
  .c3 .cal3-prep{align-items:flex-start;padding:6px 0;border-bottom:1px solid var(--border)}
523
523
  .c3 .cal3-prep .ki{flex:none}
524
+ /* Calendar › Notes meeting series (c3-notes-series): a series' recent meetings indented under it, the quiet "more" lines,
525
+ the head's series line, the topic dots (last 10 meetings) and two cards side by side when there is room */
526
+ .c3 .cal3-nrow.cal3-nsub{padding-left:var(--sp-5)}
527
+ .c3 .cal3-nrow.cal3-nsub .tt{font-weight:400;font-size:var(--fs-2)}
528
+ .c3 .nrow.cal3-nmore{display:flex;padding-top:2px;padding-bottom:2px}
529
+ .c3 .cal3-nserl{gap:4px;flex-wrap:wrap}
530
+ .c3 .cal3-nadd{padding-top:var(--sp-2);flex-wrap:wrap}
531
+ .c3 .cal3-nadd .cal3-nsearch{flex:1 1 220px;width:auto}
532
+ .c3 .cal3-dots{display:inline-flex;gap:3px;align-items:center}
533
+ .c3 .cal3-dots .cal3-dot{width:7px;height:7px;border-radius:50%;background:var(--border)}
534
+ .c3 .cal3-dots .cal3-dot.on{background:var(--acc)}
535
+ .c3 .cal3-two{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:var(--sp-3);align-items:start}
536
+ .c3 .cal3-two:empty{display:none}
524
537
  .c3 .cal3-prepb{flex:1;min-width:0;font-size:var(--fs-3)}
525
538
  .c3 .cal3-agi{display:inline-flex;align-items:center;gap:2px}
526
539
  .c3 .cal3-agi[data-cal3-heard="true"] svg{color:var(--acc)}
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
  /* run-tests.js — run the workspace suites side by side.
4
4
  *
5
- * node run-tests.js <group> [--jobs=N] [--shard=I/N] [--changed[=REF]] [--timings-out=FILE] [--list] [--verbose]
5
+ * node run-tests.js <group> [--jobs=N] [--shard=I/N] [--changed[=REF]] [--retry-browser] [--timings-out=FILE] [--list] [--verbose]
6
6
  * node run-tests.js --check
7
7
  * node run-tests.js --merge-timings=DIR
8
8
  *
@@ -28,6 +28,13 @@
28
28
  * the suites that failed and the suites its new commits reach, not the whole group again. A suite it skips is written
29
29
  * to --passed-out too, so a pass carries forward to the run after. An empty or unknown SHA skips nothing.
30
30
  *
31
+ * --retry-browser runs a failed browser suite once more, alone, after the others finish (ci-flaky-retry, PM
32
+ * 2026-10-13). On 2026-10-12 most red Workspace CI runs went green on "Re-run failed jobs" with no change: 27 of 38
33
+ * re-runs. A suite that passes on the retry counts as passed and is printed as FLAKY, with a ::warning:: on CI and a
34
+ * line in the job summary, so the flaky suites stay visible and get fixed. A suite that fails twice fails the run. A
35
+ * suite that timed out is not retried: a second 10-minute wait costs more than the re-run it saves. Unit and module
36
+ * suites are never retried. Workspace CI passes it; a local run does not.
37
+ *
31
38
  * Output: a suite's own output is buffered and printed whole when it finishes, so lines from two
32
39
  * suites never interleave. A passing suite prints its last lines; --verbose prints all of it.
33
40
  *
@@ -307,12 +314,29 @@ async function main() {
307
314
  await Promise.all(Array.from({ length: Math.min(jobs, shared.length) }, worker));
308
315
  for (const f of list.filter((x) => exclusive.has(x))) results.push(await runOne(f, verbose));
309
316
 
317
+ // --retry-browser: one more run of each failed browser suite, alone, so the load of the first pass is gone (see the header)
318
+ const flaky = [];
319
+ if (flag('retry-browser')) {
320
+ const isBrowser = (f) => FILES.panels.includes(f) || FILES.ui.includes(f);
321
+ for (const r of results.filter((x) => !x.ok && isBrowser(x.file) && !/timed out/.test(x.why))) {
322
+ console.log(`\nrun-tests: ${r.file} failed (${r.why}). Running it once more, alone.`);
323
+ const again = await runOne(r.file, verbose);
324
+ if (again.ok) { flaky.push(r); r.ok = true; r.flaky = true; }
325
+ }
326
+ }
310
327
  const failed = results.filter((r) => !r.ok);
311
328
  const slowest = [...results].sort((a, b) => b.secs - a.secs).slice(0, 5).map((r) => `${r.file} ${r.secs}s`).join(', ');
312
329
  const timingsOut = flag('timings-out');
313
330
  writePassed(results);
314
331
  if (timingsOut && timingsOut !== true) fs.writeFileSync(timingsOut, JSON.stringify(Object.fromEntries(results.map((r) => [r.file, r.secs])), null, 2));
315
332
  console.log(`\nrun-tests: ${results.length - failed.length}/${results.length} suites passed in ${((Date.now() - t0) / 1000).toFixed(1)}s wall. Slowest: ${slowest}.`);
333
+ if (flaky.length) {
334
+ console.log(`FLAKY: ${flaky.map((r) => `${r.file} (first run: ${r.why})`).join(', ')}. Each passed when run again alone.`);
335
+ if (process.env.GITHUB_ACTIONS) for (const r of flaky) console.log(`::warning title=Flaky suite::${r.file} failed (${r.why}) and passed when run again alone. Fix it: it cost this run a retry.`);
336
+ if (process.env.GITHUB_STEP_SUMMARY) {
337
+ try { fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, `### Flaky suites (passed on the retry)\n\n${flaky.map((r) => `- \`${r.file}\` (first run: ${r.why})`).join('\n')}\n`); } catch { /* the summary is a convenience */ }
338
+ }
339
+ }
316
340
  // exitCode, never process.exit(): stdout to a pipe is asynchronous, and exiting here cut the CI log
317
341
  // off mid-suite, before the summary that names what failed.
318
342
  if (failed.length) { console.log(`FAILED: ${failed.map((r) => `${r.file} (${r.why})`).join(', ')}`); process.exitCode = 1; }
@@ -61,6 +61,7 @@
61
61
  "notes-highlight.test.js",
62
62
  "notes-page.test.js",
63
63
  "notes-conflicts.test.js",
64
+ "notes-series.test.js",
64
65
  "notes-resume.test.js",
65
66
  "proactive-prepare.test.js",
66
67
  "learn.test.js",
@@ -208,6 +209,7 @@
208
209
  "notes-highlight.test.js": 1,
209
210
  "notes-page.test.js": 1,
210
211
  "notes-conflicts.test.js": 1,
212
+ "notes-series.test.js": 1,
211
213
  "notes-resume.test.js": 8,
212
214
  "proactive-prepare.test.js": 9,
213
215
  "learn.test.js": 3,
@@ -0,0 +1,5 @@
1
+ {
2
+ "_comment": "Initiative c3-notes-series: meeting series in Calendar › Notes (one row per series, the series page, a note's place in its series, older notes folded, search in the transcript).",
3
+ "panels": ["pm-c3-notes-series-test.js"],
4
+ "seconds": { "pm-c3-notes-series-test.js": 40 }
5
+ }