create-pmos 0.511.0 → 0.513.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.
- package/package.json +27 -31
- package/payload/KIT-VERSION +1 -1
- package/payload/planning/evals/eval-calibration.md +1 -1
- package/payload/planning/okrs/health-budgets.md +1 -1
- package/payload/state/discoveries.md +1 -1
- package/workspace/briefing-premium-adddoc-test.js +3 -3
- package/workspace/briefing-premium-board-test.js +2 -2
- package/workspace/briefing-premium-initiative-test.js +3 -3
- package/workspace/briefing-premium-insights-test.js +2 -2
- package/workspace/briefing-premium-sources-test.js +4 -5
- package/workspace/briefing-premium-test.js +2 -2
- package/workspace/changelog.json +26 -0
- package/workspace/fixtures/next-prompt-replay.json +40 -0
- package/workspace/guide/home.md +1 -1
- package/workspace/guide/index.md +1 -0
- package/workspace/guide/next-prompt.md +62 -0
- package/workspace/guide/settings.md +3 -1
- package/workspace/intel-report-ui-test.js +1 -1
- package/workspace/intelligence-gaps-ui-test.js +1 -1
- package/workspace/lib/next-prompt.js +199 -0
- package/workspace/lib/premium-console-type.js +15 -12
- package/workspace/lib/route-modules.js +1 -0
- package/workspace/lib/routes-next-prompt.js +248 -0
- package/workspace/metric-drafts-ui-test.js +2 -2
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/premium-menu-rows-test.js +1 -1
- package/workspace/premium-vw-doc-test.js +1 -1
- package/workspace/public/pm/bd-pin-card.css +4 -4
- package/workspace/public/pm/bd-publish.css +11 -11
- package/workspace/public/pm/bd-shared.css +17 -17
- package/workspace/public/pm/c3-capture.css +9 -9
- package/workspace/public/pm/c3-initiatives.css +23 -23
- package/workspace/public/pm/c3-listen.css +1 -1
- package/workspace/public/pm/components.css +572 -572
- package/workspace/public/pm/console3.css +374 -373
- package/workspace/public/pm/cozy-adler.css +4 -4
- package/workspace/public/pm/cozy-aud.css +1 -1
- package/workspace/public/pm/cozy-board.css +328 -328
- package/workspace/public/pm/cozy-ev.css +80 -78
- package/workspace/public/pm/cozy-home-rows.css +32 -32
- package/workspace/public/pm/cozy-home.css +285 -241
- package/workspace/public/pm/cozy-insights.css +200 -200
- package/workspace/public/pm/cozy-live-pill.css +5 -5
- package/workspace/public/pm/cozy-mtg-present.css +28 -28
- package/workspace/public/pm/cozy-onboard.css +15 -15
- package/workspace/public/pm/cozy-panel.css +39 -39
- package/workspace/public/pm/cozy-pick.css +5 -5
- package/workspace/public/pm/cozy-rec-now.css +23 -23
- package/workspace/public/pm/cozy-rec-present.css +11 -11
- package/workspace/public/pm/cozy-rec-tab.css +13 -13
- package/workspace/public/pm/cozy-settings.js +37 -2
- package/workspace/public/pm/cozy-steps.css +14 -14
- package/workspace/public/pm/cozy-today.css +95 -95
- package/workspace/public/pm/cozy-viewer.css +27 -27
- package/workspace/public/pm/cozy-vw-mtg.css +113 -113
- package/workspace/public/pm/cozy-vw-rp.css +79 -79
- package/workspace/public/pm/cozy-vw-shell.css +43 -43
- package/workspace/public/pm/cozy-vw.css +129 -129
- package/workspace/public/pm/cozy-xv.css +15 -15
- package/workspace/public/pm/cozy.css +53 -21
- package/workspace/public/pm/dash-view.css +27 -27
- package/workspace/public/pm/hi-pop.css +26 -26
- package/workspace/public/pm/home-chat.js +21 -4
- package/workspace/public/pm/home-impact.css +8 -8
- package/workspace/public/pm/home-ini.css +36 -36
- package/workspace/public/pm/home-line.css +7 -7
- package/workspace/public/pm/impact.css +9 -9
- package/workspace/public/pm/ini-view.css +243 -243
- package/workspace/public/pm/load-shapes.css +1 -1
- package/workspace/public/pm/loose-props.css +14 -14
- package/workspace/public/pm/metric-drafts.css +20 -20
- package/workspace/public/pm/ms-suggest.css +9 -9
- package/workspace/public/pm/next-prompt-ui.js +117 -0
- package/workspace/public/pm/ov-view.css +14 -14
- package/workspace/public/pm/premium-insights.js +3 -3
- package/workspace/public/pm/premium-report-frame.css +1 -1
- package/workspace/public/pm/premium-report-intel.css +17 -17
- package/workspace/public/pm/premium-report-print.css +1 -1
- package/workspace/public/pm/premium-vw-backlog.css +13 -13
- package/workspace/public/pm/premium-vw-cal.css +32 -32
- package/workspace/public/pm/premium-vw-copy.css +7 -7
- package/workspace/public/pm/premium-vw-doc.css +69 -69
- package/workspace/public/pm/premium-vw-item.css +12 -12
- package/workspace/public/pm/premium-vw-jira.css +39 -39
- package/workspace/public/pm/premium-vw-meet.css +28 -28
- package/workspace/public/pm/premium-vw-notepad.css +13 -13
- package/workspace/public/pm/premium-vw-notes.css +11 -11
- package/workspace/public/pm/premium-vw-rec.css +27 -27
- package/workspace/public/pm/premium-vw-report.css +21 -21
- package/workspace/public/pm/premium-vw-slides.css +28 -28
- package/workspace/public/pm/premium.css +618 -618
- package/workspace/public/pm/prog-order.css +6 -6
- package/workspace/public/pm/prog-page.css +17 -17
- package/workspace/public/pm/program-charter.css +33 -33
- package/workspace/public/pm/ready-lib.css +6 -6
- package/workspace/public/pm/sort-order.css +1 -1
- package/workspace/public/pm/split-merge.css +18 -18
- package/workspace/public/pm/task-card.css +24 -24
- package/workspace/public/pm/tk-tasks.css +42 -42
- package/workspace/public/pm/tk-view.css +6 -6
- package/workspace/public/pm/wf-page.css +31 -31
- package/workspace/public/premium-aud.html +1 -1
- package/workspace/public/premium-board.html +1 -1
- package/workspace/public/premium-intelligence.html +1 -1
- package/workspace/public/premium-rec.html +1 -1
- package/workspace/public/premium-viewer.html +1 -1
- package/workspace/public/premium-workflows.html +1 -1
- package/workspace/public/premium.html +1 -1
- package/workspace/public/vendor/plus-jakarta-sans-var.woff2 +0 -0
- package/workspace/server.js +1 -0
- package/workspace/test-lists/next-prompt.json +5 -0
- package/workspace/third-party/README.md +2 -1
- package/workspace/third-party/plus-jakarta-sans-OFL.LICENSE +93 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.513.0",
|
|
4
4
|
"description": "Scaffold the PMOS portable kit — run the PMOS product-management workflow (initiative → lane-fit spec → contract → build → three gates, with work-type lanes for features, research, maintenance, incidents, and content) entirely inside your own repo, with all state as git-versioned files. Includes `workflow-sweep`, which audits the state every board derives from and separates real defects from work you simply have not done. `create-pmos workspace` also installs + launches the local Terminal Workspace GUI. No database, no network, no telemetry.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -32,6 +32,32 @@
|
|
|
32
32
|
"audit"
|
|
33
33
|
],
|
|
34
34
|
"pmosChanges": [
|
|
35
|
+
{
|
|
36
|
+
"v": "0.513.0",
|
|
37
|
+
"at": "2026-11-03T15:46:14.696Z",
|
|
38
|
+
"f": 4,
|
|
39
|
+
"prs": [
|
|
40
|
+
{
|
|
41
|
+
"n": 1203,
|
|
42
|
+
"t": "Typography roles with Plus Jakarta Sans, two weights, four sizes",
|
|
43
|
+
"s": "Typography roles with Plus Jakarta Sans, two weights, four sizes",
|
|
44
|
+
"k": "new"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"v": "0.512.0",
|
|
50
|
+
"at": "2026-11-03T15:33:10.629Z",
|
|
51
|
+
"f": 4,
|
|
52
|
+
"prs": [
|
|
53
|
+
{
|
|
54
|
+
"n": 1204,
|
|
55
|
+
"t": "Suggest the next prompt and sharpen a rough one in the chat",
|
|
56
|
+
"s": "Suggest the next prompt and sharpen a rough one in the chat",
|
|
57
|
+
"k": "new"
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
35
61
|
{
|
|
36
62
|
"v": "0.511.0",
|
|
37
63
|
"at": "2026-11-03T15:10:29.930Z",
|
|
@@ -536,36 +562,6 @@
|
|
|
536
562
|
"d": "On a phone the initiative page had uneven edges. Now everything lines up on one even margin."
|
|
537
563
|
}
|
|
538
564
|
]
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
"v": "0.493.0",
|
|
542
|
-
"at": "2026-11-02T14:41:05.438Z",
|
|
543
|
-
"f": 4,
|
|
544
|
-
"prs": [
|
|
545
|
-
{
|
|
546
|
-
"n": 1152,
|
|
547
|
-
"t": "Retire Now / Next / Later; the Roadmap is one ranked list",
|
|
548
|
-
"s": "Retire Now / Next / Later; the Roadmap is one ranked list",
|
|
549
|
-
"k": "new",
|
|
550
|
-
"h": "One ranked roadmap",
|
|
551
|
-
"d": "The roadmap split work into Now, Next and Later. Now it is one ranked list, and each initiative's stage says where it is."
|
|
552
|
-
}
|
|
553
|
-
]
|
|
554
|
-
},
|
|
555
|
-
{
|
|
556
|
-
"v": "0.492.0",
|
|
557
|
-
"at": "2026-11-02T10:50:33.055Z",
|
|
558
|
-
"f": 4,
|
|
559
|
-
"prs": [
|
|
560
|
-
{
|
|
561
|
-
"n": 1155,
|
|
562
|
-
"t": "A new user's empty PMOS folder no longer skips the setup conversation",
|
|
563
|
-
"s": "A new user's empty PMOS folder no longer skips the setup conversation",
|
|
564
|
-
"k": "fix",
|
|
565
|
-
"h": "New users get the setup conversation",
|
|
566
|
-
"d": "A new user with an empty PMOS folder landed on a bare Home. Now the setup conversation starts as it should."
|
|
567
|
-
}
|
|
568
|
-
]
|
|
569
565
|
}
|
|
570
566
|
]
|
|
571
567
|
}
|
package/payload/KIT-VERSION
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Eval calibration log"
|
|
4
4
|
description: "Append-only record of every PM override of an evaluator verdict."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-11-03T15:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T15:46:12Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Health budgets"
|
|
4
4
|
description: "Closed registry of health-budget anchors (D59), edited only by the PM."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-11-03T15:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T15:46:12Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Discoveries and friction log"
|
|
4
4
|
description: "Append-only record of what runs discovered and where the process rubbed."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-11-03T15:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T15:46:12Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -145,7 +145,7 @@ const PAGES = {
|
|
|
145
145
|
ok('A3 the add route takes POST only', wrong === 405);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
/* A8 fidelity: the form follows the Agreed design (premium-agreed-design): the Viewer is one cozy card in
|
|
148
|
+
/* A8 fidelity: the form follows the Agreed design (premium-agreed-design): the Viewer is one cozy card in Plus Jakarta Sans, its presses pills, the main one
|
|
149
149
|
* the solid colour. The colours are read from the page's own tokens, so a theme is checked against itself. */
|
|
150
150
|
for (const [w, h] of [[1280, 900], [390, 844]]) for (const th of ['light', 'dark']) {
|
|
151
151
|
const R = await open('initiative', { w, h, theme: th });
|
|
@@ -159,8 +159,8 @@ const PAGES = {
|
|
|
159
159
|
return { vw: cs('#czViewer').backgroundColor, card: tok('--cz-card', 'background-color'), vwR: cs('#czViewer').borderTopLeftRadius, ff: cs('#czViewer').fontFamily, go: [cs(go).backgroundColor, '700', cs(go).borderTopLeftRadius], solid: tok('--cz-solid', 'background-color'), no: bk ? getComputedStyle(bk).backgroundColor : 'rgba(0, 0, 0, 0)', dlg: !!(document.querySelector('#dlg') && !!document.querySelector('#dlg.on')) };
|
|
160
160
|
});
|
|
161
161
|
const d = [];
|
|
162
|
-
if (!/^
|
|
163
|
-
if (g.vw !== g.card || !/^
|
|
162
|
+
if (!/^"?Plus Jakarta Sans/.test(btn.ff) || btn.br !== '999px') d.push('button ' + JSON.stringify(btn));
|
|
163
|
+
if (g.vw !== g.card || !/^"?Plus Jakarta Sans/.test(g.ff) || (w > 760 && parseFloat(g.vwR) < 20)) d.push('viewer ' + [g.vw, g.card, g.vwR, g.ff].join(' '));
|
|
164
164
|
if (g.go[0] !== g.solid || +g.go[1] < 700 || g.go[2] !== '999px') d.push('Add document ' + g.go.join(' ') + ' want ' + g.solid);
|
|
165
165
|
if (g.no !== g.card && g.no !== 'rgba(0, 0, 0, 0)') d.push('Back ' + g.no); // ← cancels (batch 18 item 2-C): the header's quiet round press
|
|
166
166
|
if (g.dlg) d.push('the old dialog opened');
|
|
@@ -645,11 +645,11 @@ const IVREAD = () => {
|
|
|
645
645
|
await R.ctx.close();
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
-
/* B13 the Agreed design's look:
|
|
648
|
+
/* B13 the Agreed design's look: Plus Jakarta Sans, the soft panel, the chips and the track's rows */
|
|
649
649
|
for (const th of ['light', 'dark']) {
|
|
650
650
|
const R = await open({ w: 1440, h: 900, theme: th }), q = R.page;
|
|
651
651
|
const s = await q.evaluate(() => { const cs = (sel) => getComputedStyle(document.querySelector(sel)); const main = cs('main.bd-main'), row = document.querySelector('.bt-l').getBoundingClientRect(); return { font: cs('body').fontFamily, rad: main.borderTopLeftRadius, bg: main.backgroundColor, chip: Math.round(document.querySelector('#chJira').getBoundingClientRect().height), row: Math.round(row.height), tab: cs('#tabIni').fontWeight, fab: cs('#czFab').borderTopLeftRadius }; });
|
|
652
|
-
ok(`B13 the look of the Agreed design at 1440 px, ${th}:
|
|
652
|
+
ok(`B13 the look of the Agreed design at 1440 px, ${th}: Plus Jakarta Sans, a 28 px panel, 30 px chips, 54 px rows`, /^"?Plus Jakarta Sans/.test(s.font) && s.rad === '28px' && s.chip === 30 && s.row >= 54 && s.row <= 62 && s.tab === '600' && (th === 'light' ? s.bg === 'rgb(255, 255, 255)' : s.bg !== 'rgb(255, 255, 255)'), JSON.stringify(s));
|
|
653
653
|
await R.ctx.close();
|
|
654
654
|
}
|
|
655
655
|
return finish();
|
|
@@ -252,7 +252,7 @@ const WRITES = /^\/api\/(?:boards\/(?:move|tasks\/(?:add|state))|lifecycle|core-
|
|
|
252
252
|
const post = await fetch(BASE + '/api/initiative-premium?id=x', { method: 'POST' }); ok('I10 the route answers GET only', post.status === 405);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
/* I12 fidelity: the Agreed design (premium-agreed-design, Inside one initiative):
|
|
255
|
+
/* I12 fidelity: the Agreed design (premium-agreed-design, Inside one initiative): Plus Jakarta Sans, the cozy card, the CTA in the solid colour, the floating
|
|
256
256
|
* menu. The colours are read from the page's own tokens, so each theme is checked against itself. */
|
|
257
257
|
for (const [w, h] of [[1440, 900], [390, 844]]) for (const th of ['light', 'dark']) {
|
|
258
258
|
const R = await open({ w, h, theme: th });
|
|
@@ -264,7 +264,7 @@ const WRITES = /^\/api\/(?:boards\/(?:move|tasks\/(?:add|state))|lifecycle|core-
|
|
|
264
264
|
return { font: cs('body').fontFamily, cta: (cs('#czViewer .iv-go') || {}).backgroundColor, ctaAlt: !document.querySelector('#czViewer .iv-go'), solid: tok('--cz-solid'), blue: tok('--cz-blue'), well: tok('--cz-well'), card: tok('--cz-card'), box: cs('#czViewer .iv-mc').backgroundColor, rad: parseFloat(cs(innerWidth <= 760 ? '#czViewer .iv-tel' : '#czViewer .iv-mc').borderTopLeftRadius), fab: fr ? [Math.round(fr.width), Math.round(fr.height)] : null, over: document.documentElement.scrollWidth - innerWidth, cardW: Math.round(c.width) };
|
|
265
265
|
});
|
|
266
266
|
const d = [];
|
|
267
|
-
if (!/^
|
|
267
|
+
if (!/^"?Plus Jakarta Sans/.test(g.font)) d.push('font ' + g.font);
|
|
268
268
|
if (!g.ctaAlt && ![g.solid, g.blue].includes(g.cta)) d.push('cta ' + g.cta + ' want ' + g.solid + ' or ' + g.blue);
|
|
269
269
|
if (![g.well, g.card].includes(g.box) && !/rgba/.test(g.box)) d.push('card box ' + g.box);
|
|
270
270
|
// a phone has no wrapper card (batch 23 item 5, canvas PmA): the mission is the first card there
|
|
@@ -272,7 +272,7 @@ const WRITES = /^\/api\/(?:boards\/(?:move|tasks\/(?:add|state))|lifecycle|core-
|
|
|
272
272
|
// on a phone the initiative's page is the Viewer, full screen over the list: the floating menu waits under it (HbCPhone)
|
|
273
273
|
if (w > 760 && (!g.fab || g.fab[0] !== 56 || g.fab[1] !== 56)) d.push('fab ' + JSON.stringify(g.fab));
|
|
274
274
|
if (g.over > 0) d.push('sideways scroll ' + g.over);
|
|
275
|
-
ok(`I12 the initiative follows the Agreed design at ${w} px, ${th}:
|
|
275
|
+
ok(`I12 the initiative follows the Agreed design at ${w} px, ${th}: Plus Jakarta Sans, the cozy card, the CTA, the floating menu`, d.length === 0, d.join(' ; '));
|
|
276
276
|
ok(`I12 no page error at ${w} px, ${th}`, R.errors.length === 0, R.errors.join(' | '));
|
|
277
277
|
await R.ctx.close();
|
|
278
278
|
}
|
|
@@ -603,13 +603,13 @@ const BMR = { ok: true, state: 'ready', model: { tiles: [
|
|
|
603
603
|
await R.ctx.close();
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
/* I11 fidelity to the Agreed design (AgInsGoals, AgInsPhone):
|
|
606
|
+
/* I11 fidelity to the Agreed design (AgInsGoals, AgInsPhone): Plus Jakarta Sans, the cozy panel, the pill tabs, the table, the strip and the six tiles */
|
|
607
607
|
for (const [w, h] of [[1440, 900], [390, 844]]) {
|
|
608
608
|
const R = await open({ w, h }); await sleep(300);
|
|
609
609
|
const f = await R.page.evaluate(() => { const cs = (s) => getComputedStyle(document.querySelector(s)); const main = cs('main.ins'), tab = cs('#viewChip'), strip = cs('#insHero'), row = document.querySelector('#goalTbl .ins-row').getBoundingClientRect();
|
|
610
610
|
return { font: cs('body').fontFamily, radius: main.borderTopLeftRadius, bg: main.backgroundColor, tabBg: tab.backgroundColor, tabR: tab.borderTopLeftRadius, tabW: tab.fontWeight, stripR: strip.borderTopLeftRadius, stripBg: strip.backgroundColor, rowH: Math.round(row.height), over: document.documentElement.scrollWidth > innerWidth, fab: document.querySelector('#czFab').getBoundingClientRect().width, fabX: Math.round(document.querySelector('#czFab').getBoundingClientRect().left) }; });
|
|
611
611
|
const phone = w < 720;
|
|
612
|
-
ok(`I11 the page wears the Agreed design at ${w} px:
|
|
612
|
+
ok(`I11 the page wears the Agreed design at ${w} px: Plus Jakarta Sans, the white panel, the pill View chip, the well strip, 56 px floating button`, /^"?Plus Jakarta Sans/.test(f.font) && f.radius === (phone ? '0px' : '28px') && (phone || f.bg === 'rgb(255, 255, 255)') && f.tabBg === 'rgb(244, 243, 240)' && f.tabR === '999px' && +f.tabW >= 600 && (phone || (f.stripR === '16px' && f.stripBg === 'rgb(244, 243, 240)' && f.rowH >= 60)) && !f.over && f.fab === 56 && (phone ? f.fabX > 300 : f.fabX === 36), JSON.stringify(f));
|
|
613
613
|
if (!phone) {
|
|
614
614
|
await toTrends(R.page);
|
|
615
615
|
const t = await R.page.evaluate(() => { const tiles = [...document.querySelectorAll('#bmBody [data-tile]')].map((x) => x.getBoundingClientRect()); return { n: tiles.length, tileH: tiles.length ? Math.round(tiles[0].height) : 0, over: document.documentElement.scrollWidth > innerWidth }; });
|
|
@@ -193,7 +193,7 @@ const sh = (cwd, args) => spawnSync('git', args, { cwd, encoding: 'utf8' });
|
|
|
193
193
|
{
|
|
194
194
|
// re-pointed again for the Agreed design's Home: the source row is a Needs-you row of Home's list, and the digest is a row of New for you.
|
|
195
195
|
// Re-pointed for Home A + C (HvAC, HvACDesk): a row is one line, its mark and its title; the subject moved to the row's tooltip and
|
|
196
|
-
// accessible name, and the title is
|
|
196
|
+
// accessible name, and the title is the row title role, 15 px at 600 (feedback batch 26 item 6)
|
|
197
197
|
const ROWS = [['row', '.hm-rm'], ['number', '.hv-d'], ['title', '.hm-rt b']];
|
|
198
198
|
const DIGS = [['event', ''], ['eventTime', '.ev-tx .ev-mut'], ['eventTitle', '.ev-tx b']];
|
|
199
199
|
const SANS = 'var(--cz-sans)';
|
|
@@ -201,10 +201,10 @@ const sh = (cwd, args) => spawnSync('git', args, { cwd, encoding: 'utf8' });
|
|
|
201
201
|
const WANT = {
|
|
202
202
|
row: { fontFamily: SANS, color: 'var(--cz-ink)', backgroundColor: 'transparent' },
|
|
203
203
|
number: { backgroundColor: 'var(--cz-blue)', borderRadius: '50%', width: '8px', height: '8px' }, // the row's dot is blue: it waits on you (HvAC .d)
|
|
204
|
-
title: { fontFamily: SANS, fontSize: '
|
|
204
|
+
title: { fontFamily: SANS, fontSize: 'var(--fs-row)', fontWeight: 'var(--fw-strong)', color: 'var(--cz-ink)' }, // the row title role (batch 26 item 6), desktop and phone
|
|
205
205
|
event: { fontFamily: SANS, color: 'var(--cz-ink)', backgroundColor: 'transparent' }, // a row of New for you's table (cozy-ev.css)
|
|
206
|
-
eventTime: { fontSize: '
|
|
207
|
-
eventTitle: { fontFamily: SANS, fontSize: '
|
|
206
|
+
eventTime: { fontSize: 'var(--fs-meta)', color: 'var(--cz-ink3)' },
|
|
207
|
+
eventTitle: { fontFamily: SANS, fontSize: 'var(--fs-row)', fontWeight: 'var(--fw-strong)', color: 'var(--cz-ink)' },
|
|
208
208
|
};
|
|
209
209
|
const grab = (pg, pairs, base, col) => pg.evaluate(([pairs, want, base, col]) => {
|
|
210
210
|
const o = {};
|
|
@@ -235,7 +235,6 @@ const sh = (cwd, args) => spawnSync('git', args, { cwd, encoding: 'utf8' });
|
|
|
235
235
|
await allNeeds(R.page);
|
|
236
236
|
// on a phone "Not in an initiative" starts folded (HvAC): open it to reach the source row
|
|
237
237
|
if (w === 390) { const lh = await R.page.$('#hmList .hv-lh[aria-expanded="false"]'); if (lh) await lh.click(); }
|
|
238
|
-
WANT.title.fontSize = w === 390 ? '16px' : '14px';
|
|
239
238
|
await sleep(500);
|
|
240
239
|
const rowSel = '#hmList .hm-r[data-id^="n:src:"]';
|
|
241
240
|
const diffs = diff(await grab(R.page, ROWS, rowSel, '.hm-pg'), ROWS, 4); // the row fills its group (the group's own inset aside)
|
|
@@ -127,7 +127,7 @@ const vw = () => { const v = document.querySelector('#czViewer:not([hidden])');
|
|
|
127
127
|
const selBg = await p.evaluate(() => getComputedStyle(document.querySelector('.hm-r.sel')).backgroundColor);
|
|
128
128
|
ok('R12 the selected row is tinted (HvACDesk .sel)', selBg && !/rgba\(0, 0, 0, 0\)|transparent/.test(selBg), selBg);
|
|
129
129
|
const hd = await p.evaluate(() => { const h = document.querySelector('#hmCh'); return h && !h.hidden ? { t: (h.querySelector('.hm-chb') || {}).textContent || '', mark: !!h.querySelector('.hv-mk .hv-d, .hv-mk .hv-ck'), y: Math.round(h.getBoundingClientRect().top), size: getComputedStyle(h.querySelector('.hm-chb')).fontSize } : null; });
|
|
130
|
-
ok('R12 the chat\'s header line names the open row: its mark and its title,
|
|
130
|
+
ok('R12 the chat\'s header line names the open row: its mark and its title, 15 px (the row title role, batch 26 item 6), at the top of the chat card (HvACDesk .ch)', !!hd && hd.t === r0.t && hd.mark && hd.y === 32 && hd.size === '15px', JSON.stringify(hd)); }
|
|
131
131
|
|
|
132
132
|
/* R10 */
|
|
133
133
|
ok('R10 a page where nothing was pressed to record sends no POST', A.posts.filter((x) => /briefing-premium\/(decide|put-off|return|start)/.test(x.path)).length === 0, JSON.stringify(A.posts.map((x) => x.path)));
|
|
@@ -273,7 +273,7 @@ const vw = () => { const v = document.querySelector('#czViewer:not([hidden])');
|
|
|
273
273
|
const desk = document.querySelector('#hmDesk'), list = document.querySelector('#hmList'), cs = getComputedStyle(document.querySelector('#hmChat')), r = list.getBoundingClientRect();
|
|
274
274
|
return { inset: Math.round(r.left), radius: cs.borderTopLeftRadius, list: Math.round(list.getBoundingClientRect().width), font: getComputedStyle(document.body).fontFamily, theme: document.documentElement.dataset.theme || '', bg: getComputedStyle(document.body).backgroundColor, rail: !!document.querySelector('nav.rail'), menu: !!document.querySelector('#czMenu, .cz-nav') };
|
|
275
275
|
});
|
|
276
|
-
ok(`R12 Home follows the Home A + C design at 1440 px (HvACDesk), ${theme}: the list at 16 px and 360 px wide, the chat a card with a 24 px radius,
|
|
276
|
+
ok(`R12 Home follows the Home A + C design at 1440 px (HvACDesk), ${theme}: the list at 16 px and 360 px wide, the chat a card with a 24 px radius, Plus Jakarta Sans, the floating place menu, no rail`, f.inset === 16 && f.radius === '24px' && f.list === 360 && /Plus Jakarta Sans/.test(f.font) && f.menu && !f.rail, JSON.stringify(f));
|
|
277
277
|
await D.ctx.close();
|
|
278
278
|
}
|
|
279
279
|
return finish();
|
package/workspace/changelog.json
CHANGED
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "0.513.0",
|
|
4
|
+
"at": "2026-11-03T15:46:14.696Z",
|
|
5
|
+
"f": 4,
|
|
6
|
+
"prs": [
|
|
7
|
+
{
|
|
8
|
+
"n": 1203,
|
|
9
|
+
"t": "Typography roles with Plus Jakarta Sans, two weights, four sizes",
|
|
10
|
+
"s": "Typography roles with Plus Jakarta Sans, two weights, four sizes",
|
|
11
|
+
"k": "new"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"v": "0.512.0",
|
|
17
|
+
"at": "2026-11-03T15:33:10.629Z",
|
|
18
|
+
"f": 4,
|
|
19
|
+
"prs": [
|
|
20
|
+
{
|
|
21
|
+
"n": 1204,
|
|
22
|
+
"t": "Suggest the next prompt and sharpen a rough one in the chat",
|
|
23
|
+
"s": "Suggest the next prompt and sharpen a rough one in the chat",
|
|
24
|
+
"k": "new"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
2
28
|
{
|
|
3
29
|
"v": "0.511.0",
|
|
4
30
|
"at": "2026-11-03T15:10:29.930Z",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"about": "Recorded answers for the next-prompt and sharpen-prompt replay gates (lib/routes-next-prompt.js). Each answer was given by claude-sonnet-5-5 on a real reply from the PMOS project threads on 2026-11-03, except the cases named as made up, which test a drop. The replay never calls a model.",
|
|
3
|
+
"next": [
|
|
4
|
+
{ "name": "a reply that asks a question gets the answer as a follow card, citing the line it answers",
|
|
5
|
+
"reply": "#1198 (no initiative without an expected outcome) is merged, and kit-publish is publishing it.\nAll five approved features are now merged except the hindsight engine, which stays unbuilt because there are only 1 of the 10 needed prediction-and-outcome pairs. Do you want to swap it for another idea, such as a period-end KR debrief, or stay at four?",
|
|
6
|
+
"answer": { "cards": [{ "move": "follow", "text": "Yes, swap the hindsight engine for the period-end KR debrief.", "from": "Do you want to swap it for another idea, such as a period-end KR debrief, or stay at four?" }] },
|
|
7
|
+
"expect": { "filed": 1 } },
|
|
8
|
+
{ "name": "a retired thing in an initiative chat gets an ask-the-past card, citing the verb that answers it",
|
|
9
|
+
"place": { "initiative": "Fix OOH Digital missing from Board" },
|
|
10
|
+
"reply": "Found the cause: the Board hid initiatives on the Later horizon. Retiring Now/Next/Later everywhere is a bigger change, so I asked for a separate thread for it.",
|
|
11
|
+
"answer": { "cards": [{ "move": "past", "text": "Did we ever decide to retire the Now/Next/Later stage? Answer from the records with file:line sources, or say No record found." }] },
|
|
12
|
+
"expect": { "filed": 1, "cites": ["lib/pmos-verbs.js"] } },
|
|
13
|
+
{ "name": "a reply that needs nothing gets no card",
|
|
14
|
+
"reply": "First I'll find why OOH Digital is ticked in the product filter but has no rows on the Board.",
|
|
15
|
+
"answer": { "cards": [] },
|
|
16
|
+
"expect": { "none": true } },
|
|
17
|
+
{ "name": "made up: a move PMOS does not have is dropped",
|
|
18
|
+
"reply": "PR #1171 is merged.",
|
|
19
|
+
"answer": { "cards": [{ "move": "deploy", "text": "Deploy PR #1171 to production now." }] },
|
|
20
|
+
"expect": { "none": true } },
|
|
21
|
+
{ "name": "made up: a follow card that quotes a line the reply never said is dropped",
|
|
22
|
+
"reply": "PR #1171 is merged. Tell me if any task still sits under \"Not in a stage\".",
|
|
23
|
+
"answer": { "cards": [{ "move": "follow", "text": "Yes, merge it.", "from": "Should I merge PR #1171 now or wait?" }] },
|
|
24
|
+
"expect": { "none": true } },
|
|
25
|
+
{ "name": "made up: ask the past outside an initiative chat is dropped",
|
|
26
|
+
"reply": "Retiring Now/Next/Later everywhere is a bigger change.",
|
|
27
|
+
"answer": { "cards": [{ "move": "past", "text": "Why did we retire Now/Next/Later?" }] },
|
|
28
|
+
"expect": { "none": true } }
|
|
29
|
+
],
|
|
30
|
+
"sharpen": [
|
|
31
|
+
{ "name": "a rough date move becomes a rehearsal, citing what the PM typed",
|
|
32
|
+
"text": "move the legal review 3 days later",
|
|
33
|
+
"answer": { "text": "Rehearse moving the legal review task in Ooh-digital 3 days later: show what it pushes back and which dates or tasks shift, then wait for my yes before changing anything." },
|
|
34
|
+
"expect": { "filed": 1 } },
|
|
35
|
+
{ "name": "a sharper prompt that says the same is not shown",
|
|
36
|
+
"text": "Hotfix, why OOH digital product isn't shown here",
|
|
37
|
+
"answer": { "text": "Hotfix: why isn't the OOH digital product shown here?" },
|
|
38
|
+
"expect": { "none": true } }
|
|
39
|
+
]
|
|
40
|
+
}
|
package/workspace/guide/home.md
CHANGED
|
@@ -9,7 +9,7 @@ timestamp: 2026-11-03
|
|
|
9
9
|
|
|
10
10
|
Home is the page at `/premium.html`. It follows the Agreed design and the "Uncovered features" canvas (initiative `premium-uncovered-features`). The left side is one list. The middle is the chat. The right side is the Viewer. A row opens its item in the Viewer. On a phone the list is the page, and a row opens its conversation with a back bar.
|
|
11
11
|
|
|
12
|
-
Home, the Board, Insights and the Viewer use one
|
|
12
|
+
Home, the Board, Insights and the Viewer use one typeface, Plus Jakarta Sans, with two weights (regular and semibold) and four sizes: 13, 15, 18 and 26 px. Each kind of text has one role, and the role sets its size, weight and line height: a large number and a page title are 26 px, a panel title is 18 px, a group head, a row's name and a sentence are 15 px, and the quiet meta line, a label and a badge are 13 px. The same kind of text looks the same on every page. Rows have room to breathe, so a list row is about 52 to 58 px high. There is no compact setting. Slides and report templates keep their own sizes.
|
|
13
13
|
|
|
14
14
|
## The list
|
|
15
15
|
|
package/workspace/guide/index.md
CHANGED
|
@@ -81,6 +81,7 @@ On a desktop the workspace is one frame. [Layout](layout.md) explains each part.
|
|
|
81
81
|
- [Initiatives › Timeline](initiatives-timeline.md): when each initiative runs, one row per initiative, and how to reorder rows by their grip.
|
|
82
82
|
- [Workflows](workflows.md): Settings › Workflows, the stages each kind of initiative goes through, New workflow in the chat, and `pmos workflow`.
|
|
83
83
|
- [Expected outcomes](outcomes.md): every initiative says what should change once it ships and when to check it. Claude drafts each one from the PRD or the KR, you keep it with ✓, and `pmos outcomes`.
|
|
84
|
+
- [The next prompt, suggested and sharpened](next-prompt.md): after a reply, up to two prompts to send next; while you type a rough prompt, a sharper version in your style (Polish, Prompt engineer, Your own).
|
|
84
85
|
- [Rehearse a plan](rehearse.md): before you approve a date change or a cut, Claude shows what it breaks or helps in other initiatives, goals and program milestones, with the record each effect comes from, and `pmos rehearse`.
|
|
85
86
|
- [Forecasts](forecast.md): how a goal, a delivery, a program and a health budget are forecast, the states, the kept baseline, and `pmos forecast`.
|
|
86
87
|
- [Programs on the Board](programs.md): All products, programs first then products, By product, the program panel and its milestones, and the 60 % side panels.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Guide
|
|
3
|
+
title: "The next prompt, suggested and sharpened"
|
|
4
|
+
description: "After a reply, the chat suggests what to say next. While you type a rough prompt, Claude offers a sharper version. What each card means, the styles, the settings, and the guardrails."
|
|
5
|
+
timestamp: 2026-11-03
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# The next prompt, suggested and sharpened
|
|
9
|
+
|
|
10
|
+
You do not have to remember phrases such as "grill this". The chat suggests them when they fit.
|
|
11
|
+
|
|
12
|
+
## After a reply
|
|
13
|
+
|
|
14
|
+
When Claude finishes a reply, up to two cards can show above the box. Usually there is one.
|
|
15
|
+
|
|
16
|
+
- The card Claude recommends is white, with a blue ring and a blue ✦. Another card is grey.
|
|
17
|
+
- Tap a card to put its text in the box. Nothing is sent. Change the text if you want to, then send it with ↑.
|
|
18
|
+
- The cards go away when you type, or when Claude starts a new reply. They do not time out.
|
|
19
|
+
- When there is no clear next step, no card shows.
|
|
20
|
+
|
|
21
|
+
A card suggests only something that works in PMOS today:
|
|
22
|
+
|
|
23
|
+
- an answer to the question or the offer at the end of the reply;
|
|
24
|
+
- "Grill this …" in an initiative's chat ([Claude proposes](claude-proposes.md));
|
|
25
|
+
- "Why did we …?" in an initiative's chat ([Ask about the past](ask-the-past.md));
|
|
26
|
+
- "Rehearse moving …" before a date change or a cut ([Rehearse a plan](rehearse.md));
|
|
27
|
+
- "Run the drift replay" when the weekly check waits for it ([What you might have missed](what-you-missed.md)).
|
|
28
|
+
|
|
29
|
+
Each card names only the initiatives, tasks and PRs that the reply or your message names.
|
|
30
|
+
|
|
31
|
+
## While you type
|
|
32
|
+
|
|
33
|
+
When you stop typing for about 1.5 seconds on a rough prompt of three or more words, a small spinner card shows while Claude sharpens it. Then one lit **Sharper** card shows. Tap it to put the sharper text in the box. ↶ in the box puts back what you wrote. When the sharper version says the same as yours, no card shows.
|
|
34
|
+
|
|
35
|
+
The sliders icon on the Sharper card sets how Claude sharpens:
|
|
36
|
+
|
|
37
|
+
- **Polish**: clearer and shorter. Your meaning is kept.
|
|
38
|
+
- **Prompt engineer** (the default): the best prompt for the job. It names the real initiative or task and says what a good answer holds. A date move or a cut becomes a rehearsal that waits for your yes.
|
|
39
|
+
- **Your own**: your own wording rules. You write them once in Settings.
|
|
40
|
+
|
|
41
|
+
The same menu has the **Sharpen as I type** switch. Off means no spinner and no Sharper card.
|
|
42
|
+
|
|
43
|
+
## Settings › Claude › Sharpen prompts
|
|
44
|
+
|
|
45
|
+
| Row | What it does |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Suggest the next prompt | On by default. Off: no cards after a reply. |
|
|
48
|
+
| Sharpen as I type | On when Claude's runs use your API key (Settings › Claude › API key), because a sharper version then shows in about 2 seconds. Without a key, each one is a background Claude run that takes 10 seconds or more, so it starts off. You can turn it on anyway. |
|
|
49
|
+
| Sharpen as | Polish, Prompt engineer or Your own. |
|
|
50
|
+
| Your own rules | The rules for Your own, up to 1000 characters. |
|
|
51
|
+
|
|
52
|
+
## The guardrails
|
|
53
|
+
|
|
54
|
+
The suggestions and the sharper prompt go through the same guardrail as every AI job in PMOS:
|
|
55
|
+
|
|
56
|
+
- **Propose only.** A card is text you can put in the box. Nothing is sent, and nothing is written to a record, a session or a repository.
|
|
57
|
+
- **Proven only.** Each suggested move points to the line of PMOS code that makes it work, and PMOS checks that line before the card shows. An answer to the reply points to the line of the reply it answers. A card that PMOS cannot check is not shown.
|
|
58
|
+
- **Replay-tested.** A new version shows nothing until its recorded cases pass, and those include cases that must be dropped.
|
|
59
|
+
- **Audited.** Each run writes a line to the AI audit, with no text of your conversation in it.
|
|
60
|
+
- **Off switch.** `pmos ai off next-prompt` stops the suggestions after a reply. `pmos ai off sharpen-prompt` stops the Sharper card. `pmos ai off` stops every AI job.
|
|
61
|
+
|
|
62
|
+
The reply and the words a card refers to are kept in your PMOS state folder (`next-prompt/`, the newest 30 files), outside every repository. Your choices for these rows are kept there too, in `next-prompt/prefs.json`.
|
|
@@ -35,7 +35,7 @@ Settings is not a tab. While it is open, no tab is selected. Press a tab to go b
|
|
|
35
35
|
| Claude sessions | What a new session starts with: the CLI, the model, the Claude profile and the launch flags for sessions you start, and the flags for automatic sessions. The session limits. Validate consent for this workspace. |
|
|
36
36
|
| Privacy and data | A list of what leaves this computer and when. Whether a TypeSafe key is saved, the local model that answers when there is no key (Off, Winnow or Laya), and the data folder. |
|
|
37
37
|
| Appearance | The theme (Same as system, Light or Dark) and the page that opens first. |
|
|
38
|
-
| Claude | The Claude profile that new Claude sessions start with,
|
|
38
|
+
| Claude | The Claude profile that new Claude sessions start with, the Anthropic API key for Claude's own runs on the API, and Sharpen prompts (see below). |
|
|
39
39
|
| Claude's checks | When Claude grills an initiative by itself (Full, Only at stage exits, or Off) and the monthly credit for its checks ($5, $10, $20 or $50), with what this month used. See below. |
|
|
40
40
|
| Updates | The version of the app and of each workspace's kit, the check for updates, and what changed in each week's kits (what's new). See below. |
|
|
41
41
|
|
|
@@ -85,6 +85,8 @@ Under the update card, **Updates** shows what changed in the published kits. **T
|
|
|
85
85
|
|
|
86
86
|
**API key.** Some runs of Claude, for example Grill, can use the Claude API and not a Claude session. Paste an Anthropic API key and press **Save** to turn this on. The key stays on this computer, in a file only you can read, outside every repository. PMOS never shows the key again: the row only says that a key is set. Press **Remove** to delete it. A key saved here is used before `ANTHROPIC_API_KEY`. A command that a run starts does not get the key. Only the computer that runs the workspace can change it. Set `PMOS_GRILL_API=off` to stop runs on the API.
|
|
87
87
|
|
|
88
|
+
**Sharpen prompts.** Suggest the next prompt (on by default) shows up to two prompts above the chat box after a reply. Sharpen as I type offers a sharper version of a rough prompt. It is on when an API key is set, and off without one, because a background run is too slow to follow your typing. Sharpen as picks Polish, Prompt engineer (the default) or Your own, and Your own rules holds the rules for Your own. The same style and switch are in the menu on the chat's Sharper card. See [The next prompt, suggested and sharpened](next-prompt.md).
|
|
89
|
+
|
|
88
90
|
## Claude's checks: when Claude grills, and what it may spend
|
|
89
91
|
|
|
90
92
|
Claude grills an initiative by itself and files what it finds under the initiative's ✦ (see the Claude proposes guide). There is no button to start it. This section is the only control.
|
|
@@ -88,7 +88,7 @@ const FINDING = { id: 'rf-0123456789', name: 'Partner numbers to Lee', why: 'You
|
|
|
88
88
|
};
|
|
89
89
|
const vClose = async (pg) => { for (let k = 0; k < 4; k++) { const shown = await pg.evaluate(() => { const v = document.querySelector('#czViewer'); return !!v && !v.hidden; }); if (!shown) break; await pg.evaluate(() => window.czViewer && window.czViewer.close()); await sleep(250); } };
|
|
90
90
|
const sizes = (p, sel) => p.evaluate((s) => [...new Set([...document.querySelectorAll(s + ', ' + s + ' *')].filter((e) => e.childNodes.length && [...e.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim())).map((e) => getComputedStyle(e).fontSize))], sel);
|
|
91
|
-
const SCALE = new Set(['
|
|
91
|
+
const SCALE = new Set(['13px', '15px', '18px', '26px']); // the typography roles (batch 26 item 6)
|
|
92
92
|
const panel = (p) => p.evaluate(() => {
|
|
93
93
|
const b = document.querySelector('#czViewer:not([hidden]) .ins-rpd') || document.querySelector('#side:not([hidden]) .ins-rpd'); if (!b) return null;
|
|
94
94
|
return { title: (document.querySelector('#czViewer .cz-vw-title') || {}).textContent || '', kind: (document.querySelector('#czViewer .cz-vw-kind') || {}).textContent || '', sum: (b.querySelector('.ins-rps b') || {}).textContent || '',
|
|
@@ -157,7 +157,7 @@ const WEEKLY = { view: 'view', weeks: 3, day: 'Mon', opens: 4 };
|
|
|
157
157
|
await p.evaluate(() => document.querySelector('#mdHost').remove());
|
|
158
158
|
|
|
159
159
|
/* ── T: the type scale ── */
|
|
160
|
-
const SCALE = new Set(['
|
|
160
|
+
const SCALE = new Set(['13px', '15px', '18px', '26px']); // the typography roles (batch 26 item 6)
|
|
161
161
|
const sizes = await p.evaluate(() => [...new Set([...document.querySelectorAll('#insHero, #insHero *, #nsRow, #nsRow *')].filter((e) => e.childNodes.length && [...e.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim())).map((e) => getComputedStyle(e).fontSize))]);
|
|
162
162
|
ok('T the strip and the drafts use the type scale only', sizes.every((s) => SCALE.has(s)), sizes.join());
|
|
163
163
|
ok('no page errors', !A.errors.length, A.errors.join(' | '));
|