create-pmos 0.516.0 → 0.518.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 +33 -65
- 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/changelog.json +32 -0
- package/workspace/ev-everywhere-test.js +3 -3
- package/workspace/guide/board.md +7 -63
- package/workspace/guide/breakdown.md +8 -108
- package/workspace/guide/briefing-premium.md +5 -526
- package/workspace/guide/console-calendar.md +7 -206
- package/workspace/guide/data-freshness.md +26 -4
- package/workspace/guide/docs.md +10 -125
- package/workspace/guide/home.md +8 -5
- package/workspace/guide/index.md +78 -79
- package/workspace/guide/initiatives-and-next-steps.md +6 -19
- package/workspace/guide/layout.md +23 -230
- package/workspace/guide/live-notes.md +5 -7
- package/workspace/guide/my-work.md +8 -172
- package/workspace/guide/notes.md +14 -21
- package/workspace/guide/people.md +6 -39
- package/workspace/guide/report-design.md +2 -2
- package/workspace/guide/report-structure.md +1 -1
- package/workspace/guide/reports-set-up.md +9 -10
- package/workspace/guide/reports.md +17 -1
- package/workspace/guide/settings.md +16 -69
- package/workspace/guide/today.md +12 -188
- package/workspace/lib/refresh-run.js +39 -2
- package/workspace/lib/report-checks.js +3 -0
- package/workspace/lib/report-cli.js +112 -3
- package/workspace/lib/report-engine.js +779 -0
- package/workspace/lib/report-export.js +36 -1
- package/workspace/lib/report-pyramid.js +20 -0
- package/workspace/lib/routes-ready-reports.js +3 -1
- package/workspace/lib/routes-report-design.js +7 -2
- package/workspace/lib/routes-report-setups.js +17 -2
- package/workspace/lib/routes-sources.js +6 -2
- package/workspace/lib/source-heal.js +140 -0
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/cozy-evmodel.js +18 -1
- package/workspace/public/pm/cozy-evui.js +1 -0
- package/workspace/public/pm/cozy-nav.js +9 -6
- package/workspace/public/pm/cozy-settings.js +15 -9
- package/workspace/public/pm/premium-vw-guide.css +36 -0
- package/workspace/public/pm/premium-vw-guide.js +137 -0
- package/workspace/public/pm/premium-vw-open.js +4 -1
- package/workspace/public/pm/premium-vw-page.js +2 -1
- package/workspace/run-tests.js +6 -0
- package/workspace/skills/report-biweekly.skill +7 -0
- package/workspace/skills/report-daily.skill +7 -0
- package/workspace/skills/report-monthly.skill +7 -0
- package/workspace/skills/report-special.skill +2 -0
- package/workspace/skills/report-template.skill +8 -1
- package/workspace/skills/report-weekly.skill +7 -0
- package/workspace/skills/report-write.skill +44 -0
- package/workspace/test-lists/report-engine.json +5 -0
- package/workspace/guide/ask-the-agent.md +0 -46
- package/workspace/guide/briefing-cards.md +0 -52
- package/workspace/guide/briefing.md +0 -159
- package/workspace/guide/calendar-popup.md +0 -46
- package/workspace/guide/command-palette.md +0 -77
- package/workspace/guide/console3-sessions.md +0 -147
- package/workspace/guide/document-sheet.md +0 -89
- package/workspace/guide/initiative-boards.md +0 -123
- package/workspace/guide/initiatives-screen.md +0 -179
- package/workspace/guide/initiatives-timeline.md +0 -55
- package/workspace/guide/phone-companion.md +0 -89
- package/workspace/guide/reports-dashboards.md +0 -70
- package/workspace/guide/reports-page.md +0 -87
- package/workspace/guide/timeline.md +0 -70
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* pm/premium-vw-guide.js — the user guide, read in the Viewer (initiative guide-in-app; canvas Exploring › User guide, option B, Wawan 2026-11-03).
|
|
2
|
+
*
|
|
3
|
+
* The guide ships with the app (workspace/guide/*.md, GET /api/guide). The menu's Guide icon (cozy-nav.js) opens its start page here, and
|
|
4
|
+
* /premium-viewer.html?open=guide&page=<name> opens any page on its own. The guide opens wide (the Viewer's wide mode) unless the PM set a width
|
|
5
|
+
* for it before.
|
|
6
|
+
* Rail every page, grouped by Start here's own headings, with Find a page on top; the open page is marked; a group folds and stays folded.
|
|
7
|
+
* Page the title, then one chip per section (a press scrolls there), then the text. A link to another guide page opens that page in the same
|
|
8
|
+
* Viewer card as a drill-in, so ← comes back. A link to a repository file is drawn as text.
|
|
9
|
+
* Narrow under 720 px (a phone, or a narrow Viewer) the rail hides; the list icon beside the title shows it over the page.
|
|
10
|
+
* Nothing here writes, except the folded groups, kept in this browser.
|
|
11
|
+
* openGuide(page = 'index') -> the pane
|
|
12
|
+
* guideHtml(name, text, groups) -> the page as html (pure)
|
|
13
|
+
* guideLinks(md) -> the markdown with each link to a guide page rewritten to #guide:<name> (pure)
|
|
14
|
+
* contentsOf(indexMd) -> [{ group, pages: [{ page, title }] }] from Start here's headings and links (pure) */
|
|
15
|
+
import { vwOpen, vwStyle } from './premium-viewer.js';
|
|
16
|
+
import { drill, wide, widthOf } from './cozy-viewer.js';
|
|
17
|
+
import { bodyHtml, pageHead, splitDoc, readMinutes } from './premium-vw-doc-model.js';
|
|
18
|
+
|
|
19
|
+
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
20
|
+
const NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
21
|
+
const TOC_ICON = '<svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6h11M9 12h11M9 18h11M4 6h.01M4 12h.01M4 18h.01"/></svg>';
|
|
22
|
+
const FIND_ICON = '<svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M11 4a7 7 0 1 0 0 14a7 7 0 1 0 0-14M20 20l-4-4"/></svg>';
|
|
23
|
+
const FOLD_KEY = 'pmos.guide.folded';
|
|
24
|
+
const CHIPS = 6;
|
|
25
|
+
let TOC = null; // the groups, read once from Start here
|
|
26
|
+
|
|
27
|
+
const store = { get() { try { return JSON.parse(localStorage.getItem(FOLD_KEY) || '[]'); } catch { return []; } }, set(v) { try { localStorage.setItem(FOLD_KEY, JSON.stringify(v)); } catch { /* a private window */ } } };
|
|
28
|
+
|
|
29
|
+
/** Start here's groups: each ## or ### heading from "Read next" on, with the guide pages its list links, in order. A page linked twice keeps its first place. */
|
|
30
|
+
export function contentsOf(md) {
|
|
31
|
+
const out = [], seen = new Set(['index']); let cur = null, on = false;
|
|
32
|
+
for (const l of String(md || '').replace(/\r/g, '').split('\n')) {
|
|
33
|
+
const h = /^#{2,3}\s+(.*)$/.exec(l);
|
|
34
|
+
if (h && /^Read next$/i.test(h[1].trim())) { on = true; cur = null; continue; }
|
|
35
|
+
if (h && on) { cur = { group: h[1].trim(), pages: [] }; out.push(cur); continue; }
|
|
36
|
+
if (!cur) continue;
|
|
37
|
+
for (const m of l.matchAll(/\[([^\]]+)\]\(([a-z0-9][a-z0-9-]*)\.md\)/g)) if (!seen.has(m[2])) { seen.add(m[2]); cur.pages.push({ page: m[2], title: m[1] }); }
|
|
38
|
+
}
|
|
39
|
+
return [{ group: 'Start here', pages: [{ page: 'index', title: 'Start here' }] }, ...out.filter((g) => g.pages.length)];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The rail: Find a page, then every page by group, the open one marked. folded: the group names kept folded. */
|
|
43
|
+
export function railHtml(name, groups, folded = []) {
|
|
44
|
+
return '<nav class="gd-rail" aria-label="Guide pages">'
|
|
45
|
+
+ `<div class="gd-find">${FIND_ICON}<input type="search" placeholder="Find a page" aria-label="Find a page" autocomplete="off" data-gd-find></div>`
|
|
46
|
+
+ (groups || []).map((g) => {
|
|
47
|
+
const here = g.pages.some((x) => x.page === name), open = here || !folded.includes(g.group);
|
|
48
|
+
return `<details class="gd-grp" data-gd-grp="${esc(g.group)}"${open ? ' open' : ''}><summary>${esc(g.group)}</summary><ul>`
|
|
49
|
+
+ g.pages.map((x) => `<li><a href="#guide:${esc(x.page)}"${x.page === name ? ' aria-current="page"' : ''} data-gd-t="${esc(x.title.toLowerCase())}">${esc(x.title)}</a></li>`).join('')
|
|
50
|
+
+ '</ul></details>';
|
|
51
|
+
}).join('')
|
|
52
|
+
+ '<p class="gd-none" data-gd-none hidden>No page has that name.</p></nav>';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Each markdown link to a guide page (`[x](layout.md)`, `[x](layout.md#keys)`) becomes `[x](#guide:layout)`, which the page model keeps as a link. */
|
|
56
|
+
export const guideLinks = (md) => String(md || '').replace(/\]\(([a-z0-9][a-z0-9-]*)\.md(?:#[^)\s]*)?\)/g, '](#guide:$1)');
|
|
57
|
+
|
|
58
|
+
/** One guide page: the rail, then the page with its title, its section chips, the text and a quiet footer. */
|
|
59
|
+
export function guideHtml(name, text, groups = TOC, folded = []) {
|
|
60
|
+
const t = guideLinks(text), h = pageHead(t), sd = splitDoc(t);
|
|
61
|
+
const b = bodyHtml([sd.pre, ...sd.sections.map((s, n) => (n === 0 && h.h1 ? s.body : s.head + '\n' + s.body))].join('\n'));
|
|
62
|
+
const secs = b.heads.filter((x) => x[0] === 2);
|
|
63
|
+
// At most 6 chips show; the rest wait behind "N more", so a long page does not open on a wall of chips.
|
|
64
|
+
const chip = ([, s, id], n) => `<a href="#${esc(id)}" class="gd-chip" data-gd-jump="${esc(id)}"${n >= CHIPS ? ' hidden' : ''}>${esc(s)}</a>`;
|
|
65
|
+
const more = secs.length > CHIPS ? `<button type="button" class="gd-chip gd-more" data-gd-more>${secs.length - CHIPS} more</button>` : '';
|
|
66
|
+
const chips = secs.length > 1 ? `<div class="gd-secs" role="group" aria-label="On this page">${secs.map(chip).join('')}${more}</div>` : '';
|
|
67
|
+
const home = name === 'index' ? '' : '<span class="gap"></span><a href="#guide:index">Start here</a>';
|
|
68
|
+
return `<div class="vwdoc gd"><div class="gd-wrap">${railHtml(name, groups || [], folded)}`
|
|
69
|
+
+ `<article class="cf vwfile gd-read"><header class="cfh vwfh"><h1 class="cft">${esc(h.title || name)}</h1>`
|
|
70
|
+
+ `<div class="vwacts gd-tog"><button type="button" class="vwib" data-gd-toc aria-label="Guide pages" title="Guide pages" aria-expanded="false">${TOC_ICON}</button></div></header>`
|
|
71
|
+
+ chips
|
|
72
|
+
+ `<div class="cfb">${b.html || '<p class="vwmut">This page has no text yet.</p>'}</div>`
|
|
73
|
+
+ `<footer class="cff"><span>Guide · ${readMinutes(text)} min read</span>${home}</footer></article></div></div>`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const failHtml = (why) => `<div class="vwdoc"><div class="vwfnone" role="status"><b>The guide page could not be shown</b><p class="vwmut">${esc(why)}</p></div></div>`;
|
|
77
|
+
|
|
78
|
+
async function read(name) {
|
|
79
|
+
try {
|
|
80
|
+
const r = await fetch('/api/guide?page=' + encodeURIComponent(name), { credentials: 'same-origin' });
|
|
81
|
+
return r.ok ? { ok: true, text: await r.text() } : { ok: false, why: 'There is no guide page called ' + name + '.' };
|
|
82
|
+
} catch { return { ok: false, why: 'The workspace server did not answer.' }; }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function wire(el) {
|
|
86
|
+
const wrap = () => el.querySelector('.gd-wrap'), btn = () => el.querySelector('[data-gd-toc]');
|
|
87
|
+
const show = (on) => { const w = wrap(), b = btn(); if (!w || !b) return; w.classList.toggle('gd-railon', on); b.setAttribute('aria-expanded', String(on)); if (on) { const f = w.querySelector('[data-gd-find]'); if (f) f.focus(); } };
|
|
88
|
+
el.addEventListener('input', (e) => {
|
|
89
|
+
if (!e.target.matches('[data-gd-find]')) return;
|
|
90
|
+
const q = e.target.value.trim().toLowerCase(), r = el.querySelector('.gd-rail'); let any = false;
|
|
91
|
+
r.querySelectorAll('details.gd-grp').forEach((d) => {
|
|
92
|
+
let n = 0; d.querySelectorAll('li').forEach((li) => { const hit = !q || li.firstChild.dataset.gdT.includes(q); li.hidden = !hit; if (hit) n++; });
|
|
93
|
+
d.hidden = !n; if (q && n) d.open = true; if (n) any = true;
|
|
94
|
+
});
|
|
95
|
+
r.querySelector('[data-gd-none]').hidden = any;
|
|
96
|
+
});
|
|
97
|
+
el.addEventListener('toggle', (e) => {
|
|
98
|
+
const d = e.target; if (!d.matches || !d.matches('details.gd-grp') || el.querySelector('[data-gd-find]').value) return;
|
|
99
|
+
const k = d.dataset.gdGrp, f = store.get().filter((x) => x !== k);
|
|
100
|
+
if (!d.open) f.push(k);
|
|
101
|
+
store.set(f);
|
|
102
|
+
}, true);
|
|
103
|
+
el.addEventListener('keydown', (e) => { if (e.key === 'Escape' && wrap() && wrap().classList.contains('gd-railon')) { e.stopPropagation(); show(false); btn().focus(); } });
|
|
104
|
+
el.addEventListener('click', (e) => {
|
|
105
|
+
if (e.target.closest('[data-gd-toc]')) { show(!wrap().classList.contains('gd-railon')); return; }
|
|
106
|
+
const m = e.target.closest('[data-gd-more]');
|
|
107
|
+
if (m) { m.parentElement.querySelectorAll('.gd-chip[hidden]').forEach((c) => { c.hidden = false; }); m.remove(); return; }
|
|
108
|
+
const j = e.target.closest('[data-gd-jump]');
|
|
109
|
+
if (j) { e.preventDefault(); const h = el.querySelector('#' + CSS.escape(j.dataset.gdJump)); if (h) h.scrollIntoView({ block: 'start', behavior: 'smooth' }); return; }
|
|
110
|
+
const a = e.target.closest('a'); if (!a) return;
|
|
111
|
+
const href = a.getAttribute('href') || '';
|
|
112
|
+
const g = /^#guide:([a-z0-9-]+)$/.exec(href);
|
|
113
|
+
if (g) { e.preventDefault(); drill(); openGuide(g[1]); return; }
|
|
114
|
+
if (href === '#') e.preventDefault(); // a link to a repository file: the page model drew it without a target
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Open a guide page in the Viewer. */
|
|
119
|
+
export function openGuide(page = 'index') {
|
|
120
|
+
const name = NAME.test(String(page || '')) ? String(page) : 'index';
|
|
121
|
+
vwStyle('doc'); vwStyle('guide');
|
|
122
|
+
const id = 'guide:' + name;
|
|
123
|
+
let pane = null, done = null;
|
|
124
|
+
pane = vwOpen({ id, kind: 'Guide', title: 'Guide', icon: 'doc', url: '/premium-viewer.html?open=guide&page=' + name,
|
|
125
|
+
render: (el) => { el.innerHTML = done || '<div class="vwdoc"><p class="vwmut" role="status">Opening the guide.</p></div>'; wire(el); } });
|
|
126
|
+
try { if (!widthOf('Guide')) wide(true); } catch { /* a page with no cozy Viewer */ }
|
|
127
|
+
const toc = TOC ? Promise.resolve() : read('index').then((r) => { if (r.ok) TOC = contentsOf(r.text); });
|
|
128
|
+
Promise.all([read(name), toc]).then(([r]) => {
|
|
129
|
+
done = r.ok ? guideHtml(name, r.text, TOC, store.get()) : failHtml(r.why);
|
|
130
|
+
const el = document.querySelector(`.obody.vw[data-vw="${CSS.escape(id)}"]`) || pane;
|
|
131
|
+
if (el && el.isConnected) {
|
|
132
|
+
el.innerHTML = done; el.scrollTop = 0;
|
|
133
|
+
const cur = el.querySelector('.gd-rail [aria-current="page"]'); if (cur) cur.scrollIntoView({ block: 'nearest' });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return pane;
|
|
137
|
+
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* openReport(idOrRow, { ws, name, cycles, onIssue, onChange }) a report path reports/<cadence>/<date>.md or a Reports card row
|
|
9
9
|
* newNote(ws | { ws }) starts an untitled note now and opens it, recording
|
|
10
10
|
* makeWorkItem(noteId, step) Becomes V.4: a ticket drafted in PMOS from a next step (never pushed to Jira here)
|
|
11
|
+
* openGuide(page) a page of the user guide (workspace/guide/<page>.md); no page: Start here
|
|
11
12
|
* The modules load on first use (dynamic import), so this file has no import cycle with the view modules that import it.
|
|
12
13
|
* It also adds the Viewer's style sheet (cozy-vw.css) to the page once. */
|
|
13
14
|
|
|
@@ -19,6 +20,7 @@ export function vzStyle() {
|
|
|
19
20
|
const mtg = () => import('./premium-vw-mtg.js');
|
|
20
21
|
const cal = () => import('./premium-vw-cal.js');
|
|
21
22
|
const rep = () => import('./premium-report-read.js');
|
|
23
|
+
const gd = () => import('./premium-vw-guide.js');
|
|
22
24
|
const plain = (o) => (o && typeof o === 'object' && !o.openDlg && !o.$ ? o : {}); // an old caller passed the shell's deps
|
|
23
25
|
|
|
24
26
|
export async function openMeeting(ref, o = {}) { vzStyle(); return (await mtg()).openMeeting(ref, plain(o)); }
|
|
@@ -27,8 +29,9 @@ export async function openNotes(o = {}) { vzStyle(); return (await cal()).openNo
|
|
|
27
29
|
export async function openReport(ref, o = {}) { vzStyle(); return (await rep()).openReportView(ref, plain(o)); }
|
|
28
30
|
export async function newNote(o) { vzStyle(); return (await mtg()).newNote(typeof o === 'string' ? o : (o && o.ws) || ''); }
|
|
29
31
|
export async function makeWorkItem(noteId, step) { return (await mtg()).workItem(noteId, step); }
|
|
32
|
+
export async function openGuide(page) { vzStyle(); return (await gd()).openGuide(page); }
|
|
30
33
|
|
|
31
|
-
export const views = { openMeeting, openCalendar, openNotes, openReport, newNote, makeWorkItem };
|
|
34
|
+
export const views = { openMeeting, openCalendar, openNotes, openReport, newNote, makeWorkItem, openGuide };
|
|
32
35
|
if (typeof window !== 'undefined') {
|
|
33
36
|
window.czViews = Object.assign(window.czViews || {}, views);
|
|
34
37
|
window.pmViewer = window.czViews;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* pm/premium-vw-page.js — /premium-viewer.html: opens the item its address names in the Viewer card (initiative premium-agreed-design).
|
|
2
2
|
* ?open=meeting¬e=<id> | &event=<id>&date=YYYY-MM-DD ?open=calendar[&tab=notes][&date=] ?open=notes[&initiative=]
|
|
3
|
-
* ?open=report&path=reports/<cadence>/<date>.md each with an optional &ws=
|
|
3
|
+
* ?open=report&path=reports/<cadence>/<date>.md ?open=guide[&page=<name>] each with an optional &ws=
|
|
4
4
|
* Closing the card leaves a line that links to Home. An address that names nothing says so. */
|
|
5
5
|
import { views } from './premium-vw-open.js';
|
|
6
6
|
import { onChange } from './cozy-viewer.js';
|
|
@@ -13,4 +13,5 @@ if (what === 'meeting') views.openMeeting(q.get('note') ? { note: q.get('note')
|
|
|
13
13
|
else if (what === 'calendar') views.openCalendar({ ws, tab: q.get('tab') === 'notes' ? 'notes' : 'cal', date: q.get('date') || '' });
|
|
14
14
|
else if (what === 'notes') views.openNotes({ ws, initiative: q.get('initiative') || '' });
|
|
15
15
|
else if (what === 'report' && q.get('path')) views.openReport(q.get('path'), { ws });
|
|
16
|
+
else if (what === 'guide') views.openGuide(q.get('page') || 'index');
|
|
16
17
|
else gone.hidden = false;
|
package/workspace/run-tests.js
CHANGED
|
@@ -498,6 +498,12 @@ function traceChanges(changes, ctx) {
|
|
|
498
498
|
}
|
|
499
499
|
if (/^(guide|docs)\/|\.md$/.test(f)) continue; // prose: no suite asserts on it except guide.test.js, a unit suite
|
|
500
500
|
if (f === 'test-timings.json') continue; // run order only: no suite reads it
|
|
501
|
+
if (/^skills\/[^/]+\.skill$/.test(f) && get(f) != null) {
|
|
502
|
+
// a built-in skill is prose an agent reads: a suite reads it by its name, or loads the whole folder
|
|
503
|
+
nameHits(f).forEach((s) => picked.add(s));
|
|
504
|
+
for (const s of list) if (/\b(loadDir|readdirSync)\(path\.join\(__dirname, 'skills'\)/.test(get(s) || '')) picked.add(s);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
501
507
|
let why = null;
|
|
502
508
|
const before = picked.size;
|
|
503
509
|
if (get(f) == null) { // removed: only the names in the suites can say who used it
|
|
@@ -23,6 +23,13 @@ Rules that always hold (D71):
|
|
|
23
23
|
7. THE SCRIPT WRITES EVERY NUMBER. In a note you type none: no count, no ratio such as "7 of 12", no percentage, no date, no day count. If a sentence needs a number, write it without the number; the block above the note already shows it. A name is not a number: an initiative id, a file path and a note id may be written as they are.
|
|
24
24
|
8. PROSE ONLY BETWEEN NOTE MARKERS. In the draft file, write only between a `<!-- pmos:note <id> -->` line and its `<!-- /pmos:note -->` line. Never edit, move or delete a marker or any line outside one. Never add a section to the file.
|
|
25
25
|
|
|
26
|
+
THE REPORT ENGINE FIRST (design E). A new biweekly report is written with the report engine:
|
|
27
|
+
- Run `pmos report make biweekly`. It derives the brief from the definition's purpose, audience and sources, reads every source PMOS reaches, and finds what changed since the last issue.
|
|
28
|
+
- If it prints "No finding, so no draft", read the sources its gaps name and file their readings (`pmos report read biweekly --from <file>`). If there is still no finding, there is nothing to report: stop and say so in one line.
|
|
29
|
+
- Otherwise follow `skills/report-write.skill` from its step 2: you choose the outline for the readers; every figure is a reading.
|
|
30
|
+
- If `pmos report make biweekly` refuses because the definition names no purpose, use the procedure below.
|
|
31
|
+
The procedure below is the older path: use it only when the engine refuses the brief, or for a change to a draft that has no `<slot>.report.json`.
|
|
32
|
+
|
|
26
33
|
Procedure:
|
|
27
34
|
1. Find the state directory: `pmos/state/` if it exists, otherwise `planning/`. Call it <state>.
|
|
28
35
|
2. Read the definition: `<state>/reports/definitions/biweekly.md`.
|
|
@@ -22,6 +22,13 @@ Rules that always hold (D71):
|
|
|
22
22
|
6. THE PM'S DEFINITION RULES. The shape of this report is whatever the definition says. Do not substitute your own format.
|
|
23
23
|
7. SHOW THE STEPS. Keep a TodoWrite list of the steps of the procedure below, one item each, and mark each one completed as you finish it. The PM's chat shows "3 of 5 done". If a source you need cannot be reached because its sign-in expired, end with a pmos-ask block: {"kind":"reach","what":"<the source>","why":"sign-in expired","need":"signin"}.
|
|
24
24
|
|
|
25
|
+
THE REPORT ENGINE FIRST (design E). A new daily report is written with the report engine:
|
|
26
|
+
- Run `pmos report make daily`. It derives the brief from the definition's purpose, audience and sources, reads every source PMOS reaches, and finds what changed since the last issue.
|
|
27
|
+
- If it prints "No finding, so no draft", read the sources its gaps name and file their readings (`pmos report read daily --from <file>`). If there is still no finding, there is nothing to report: stop and say so in one line.
|
|
28
|
+
- Otherwise follow `skills/report-write.skill` from its step 2: you choose the outline for the readers; every figure is a reading.
|
|
29
|
+
- If `pmos report make daily` refuses because the definition names no purpose, use the procedure below.
|
|
30
|
+
The procedure below is the older path: use it only when the engine refuses the brief, or for a change to a draft that has no `<slot>.report.json`.
|
|
31
|
+
|
|
25
32
|
Procedure:
|
|
26
33
|
1. Find the state directory: `pmos/state/` if it exists, otherwise `planning/`. Call it <state>.
|
|
27
34
|
2. Read the definition: `<state>/reports/definitions/daily.md`.
|
|
@@ -22,6 +22,13 @@ Rules that always hold (D71):
|
|
|
22
22
|
6. THE PM'S DEFINITION RULES. The shape of this report is whatever the definition says. Do not substitute your own format.
|
|
23
23
|
7. SHOW THE STEPS. Keep a TodoWrite list of the steps of the procedure below, one item each, and mark each one completed as you finish it. The PM's chat shows "3 of 5 done". If a source you need cannot be reached because its sign-in expired, end with a pmos-ask block: {"kind":"reach","what":"<the source>","why":"sign-in expired","need":"signin"}.
|
|
24
24
|
|
|
25
|
+
THE REPORT ENGINE FIRST (design E). A new monthly report is written with the report engine:
|
|
26
|
+
- Run `pmos report make monthly`. It derives the brief from the definition's purpose, audience and sources, reads every source PMOS reaches, and finds what changed since the last issue.
|
|
27
|
+
- If it prints "No finding, so no draft", read the sources its gaps name and file their readings (`pmos report read monthly --from <file>`). If there is still no finding, there is nothing to report: stop and say so in one line.
|
|
28
|
+
- Otherwise follow `skills/report-write.skill` from its step 2: you choose the outline for the readers; every figure is a reading.
|
|
29
|
+
- If `pmos report make monthly` refuses because the definition names no purpose, use the procedure below.
|
|
30
|
+
The procedure below is the older path: use it only when the engine refuses the brief, or for a change to a draft that has no `<slot>.report.json`.
|
|
31
|
+
|
|
25
32
|
Procedure:
|
|
26
33
|
1. Find the state directory: `pmos/state/` if it exists, otherwise `planning/`. Call it <state>.
|
|
27
34
|
2. Read the definition: `<state>/reports/definitions/monthly.md`.
|
|
@@ -13,6 +13,8 @@ output:
|
|
|
13
13
|
|
|
14
14
|
/report-special — prepare a one-off report for THIS repository as a draft.
|
|
15
15
|
|
|
16
|
+
THE REPORT ENGINE FIRST (design E). A one-off report is an ad hoc report of the engine: once the PM has said what it is for, follow `skills/report-write.skill` with an id you make from the topic (lower case, dashes) and the PM's question as `--ask`. You choose the outline; every figure is a reading. The procedure below is the older path: use it only when the engine refuses the brief.
|
|
17
|
+
|
|
16
18
|
Rules that always hold (D71):
|
|
17
19
|
1. DRAFT ONLY. You write a file in this repository. Never send, post, share, email, publish or upload the report anywhere; the PM does that.
|
|
18
20
|
2. READ-ONLY on every source. Never send, reply, forward, post, comment, create, edit, transition, label, archive or delete anything in mail, chat, Jira, Confluence, calendar or any other source.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: report-template
|
|
3
3
|
label: "Saved report (from its template)"
|
|
4
|
-
description: "Prepare a saved report as a draft
|
|
4
|
+
description: "Prepare a saved report as a draft with the report engine (pmos report make, then the report-write skill). The schedule's args name the template. Never sends or posts."
|
|
5
5
|
run: agent
|
|
6
6
|
agent: claude
|
|
7
7
|
output:
|
|
@@ -23,6 +23,13 @@ Rules that always hold (D71):
|
|
|
23
23
|
6. THE SCRIPT WRITES EVERY NUMBER. In a note you type no count, ratio, percentage or date.
|
|
24
24
|
7. PROSE ONLY BETWEEN NOTE MARKERS. Write only between a `<!-- pmos:note <id> -->` line and its `<!-- /pmos:note -->` line. Never edit, move or delete a marker or any line outside one. Never add a section to the file.
|
|
25
25
|
|
|
26
|
+
THE REPORT ENGINE FIRST (design E). A new cycle is written with the report engine, not with the note markers:
|
|
27
|
+
- Run `pmos report make <id>` (the id is the schedule's args). It derives the brief from the template's purpose, audience and sources, and from a saved structure's purpose and questions, reads every source PMOS reaches, and finds what changed.
|
|
28
|
+
- If it prints "No finding, so no draft", read the sources its gaps name and file their readings (`pmos report read <id> --from <file>`). If there is still no finding, there is nothing to report this cycle: stop and say so in one line. Do not draft a report about nothing.
|
|
29
|
+
- Otherwise follow `skills/report-write.skill` from its step 2. The template's sections are the agreed outline only when the last issue was written by the engine; you choose the outline. A saved structure's charts are sources to read: file each value as a reading.
|
|
30
|
+
- A change to a draft that has a `<slot>.report.json` is a change to that report.json: edit it and run `pmos report write <id> --slot <slot> --from <file>` again. A figure stays a reading.
|
|
31
|
+
The procedure below is for a change to a draft written before the engine (a draft with note markers and no `<slot>.report.json`), and for a template whose engine brief is refused.
|
|
32
|
+
|
|
26
33
|
Procedure:
|
|
27
34
|
1. The template id is the schedule's `args`. It must match `^[a-z][a-z0-9-]{0,39}$`. If it is missing or does not match, stop and say which schedule has no valid template id.
|
|
28
35
|
2. Find the state directory: `pmos/state/` if it exists, otherwise `planning/`. Call it <state>.
|
|
@@ -22,6 +22,13 @@ Rules that always hold (D71):
|
|
|
22
22
|
6. THE PM'S DEFINITION RULES. The shape of this report is whatever the definition says. Do not substitute your own format.
|
|
23
23
|
7. SHOW THE STEPS. Keep a TodoWrite list of the steps of the procedure below, one item each, and mark each one completed as you finish it. The PM's chat shows "3 of 5 done". If a source you need cannot be reached because its sign-in expired, end with a pmos-ask block: {"kind":"reach","what":"<the source>","why":"sign-in expired","need":"signin"}.
|
|
24
24
|
|
|
25
|
+
THE REPORT ENGINE FIRST (design E). A new weekly report is written with the report engine:
|
|
26
|
+
- Run `pmos report make weekly`. It derives the brief from the definition's purpose, audience and sources, reads every source PMOS reaches, and finds what changed since the last issue.
|
|
27
|
+
- If it prints "No finding, so no draft", read the sources its gaps name and file their readings (`pmos report read weekly --from <file>`). If there is still no finding, there is nothing to report: stop and say so in one line.
|
|
28
|
+
- Otherwise follow `skills/report-write.skill` from its step 2: you choose the outline for the readers; every figure is a reading.
|
|
29
|
+
- If `pmos report make weekly` refuses because the definition names no purpose, use the procedure below.
|
|
30
|
+
The procedure below is the older path: use it only when the engine refuses the brief, or for a change to a draft that has no `<slot>.report.json`.
|
|
31
|
+
|
|
25
32
|
Procedure:
|
|
26
33
|
1. Find the state directory: `pmos/state/` if it exists, otherwise `planning/`. Call it <state>.
|
|
27
34
|
2. Read the definition: `<state>/reports/definitions/weekly.md`.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: report-write
|
|
3
|
+
label: "Write a report (the report engine)"
|
|
4
|
+
description: "Write any report as a draft, ad hoc or recurring, in any domain: derive the brief, read the sources, find what matters, choose the outline for these readers, and write report.json; PMOS renders the document and the deck. Never sends or posts."
|
|
5
|
+
run: agent
|
|
6
|
+
agent: claude
|
|
7
|
+
output:
|
|
8
|
+
- "<state>/reports/<id>/<slot>.report.json (the answer, the sections you chose, the ask, the parts beyond the ask)"
|
|
9
|
+
- "<state>/reports/<id>/<slot>.md and the deck, rendered by PMOS from it"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
/report-write — write one report for THIS repository as a draft, with the report engine (design E). The args are the report id, and for an ad hoc report the question, for example `scarlet-assessment "Do we keep Scarlet, or move small RSVP events to a SaaS?"`.
|
|
13
|
+
|
|
14
|
+
There is no template and no fixed frame. You choose the outline of this report from its readers and their question. What never changes is the discipline below.
|
|
15
|
+
|
|
16
|
+
Rules that always hold (D71):
|
|
17
|
+
1. DRAFT ONLY. You write files in this repository. Never send, post, share, email, publish or upload the report anywhere; the PM issues it.
|
|
18
|
+
2. READ-ONLY on every source. Never send, reply, forward, post, comment, create, edit, transition, label, archive or delete anything in mail, chat, Jira, Confluence, BigQuery, calendar or any other source.
|
|
19
|
+
3. EVERY FIGURE IS A READING. A number, a percentage, a count or a duration in your words is a reading token `{{r:<reading id>}}`, never typed by hand. `{{r:id}}` writes the value with its unit, `{{r:id|of}}` writes "597 of 733", `{{r:id|n}}` writes the count. PMOS refuses a report with a bare figure. Dates are written in full (21 October 2026); a date is not a figure.
|
|
20
|
+
4. NOTHING INVENTED. A reading has a source of the brief, the date it was read or measured, and how it was read (the query, the filter, the field). A source you cannot reach is a gap with its reason. Never guess a value.
|
|
21
|
+
5. THE ANSWER FIRST. The title is the answer to the readers' question, with its number. If you cannot write that sentence from the readings, there is nothing to report: stop and say so in one line.
|
|
22
|
+
6. THE VOICE. Follow the brief's `voice` lines and its `rules`: neutral and straightforward sentences, one claim per paragraph, the mood never happier than the data (0% is written as 0%, with its why). A leadership report does not carry the engineering appendix; it links to it.
|
|
23
|
+
7. SHOW THE STEPS. Keep a TodoWrite list of the steps below and mark each one completed. If a source needs a sign-in that expired, end with a pmos-ask block: {"kind":"reach","what":"<the source>","why":"sign-in expired","need":"signin"}.
|
|
24
|
+
|
|
25
|
+
Procedure:
|
|
26
|
+
1. Run `pmos report make <id>`. For an ad hoc report add `--ask "<the question>"`, and `--readers "<who>"` when you know them. Name sources the brief must read with `--source`, comma-separated: `connector:<name>=<what it is>` (Jira, BigQuery for GA4, Confluence, …), `document:<path>`, `pack:<state file of readings>`, `pmos` (the PMOS ledgers). It writes `<slot>.brief.json`, `<slot>.readings.json` and `<slot>.findings.json` next to the draft, and prints the gaps.
|
|
27
|
+
- If it refuses because the slot is issued, stop: an issued report is frozen.
|
|
28
|
+
- If it says there is no report with that id, it needs a question: ask the PM once for the question, or take it from the chat line.
|
|
29
|
+
2. Read `<slot>.brief.json`: the readers, the questions, the window, the sources, the last issue, the agreed outline, the carried asks, the voice and the rules.
|
|
30
|
+
3. Read each source that the gaps name, through its connector or the file, read-only. Write what you read as readings in one JSON file: `{"readings":[{"id":"web-login-rate","value":81,"unit":"%","n":597,"of":733,"at":"2026-10-19","source":"ga4","how":"events_20261019, sessions with a password start","label":"Web password login, recorded success"}],"gaps":[{"source":"native-app","reason":"read only on the device"}]}`. Give `target` and `better` ("higher" or "lower") when the reading has a target. Give `flag` when the reading is off what the readers expect. Run `pmos report read <id> --from <file>`. A parameter of a method (a 5-second match window) is a reading too.
|
|
31
|
+
4. Find what answers the readers. Write the findings that answer each question, each citing the readings it rests on, and run `pmos report find <id> --from <file>` with `{"findings":[{"text":"…","readings":["…"],"kind":"answers-question","question":"…"}]}`. The engine adds its own findings: changes since the last issue, misses against a target, initiatives off plan, items due within 14 days, the asks carried over. If `<slot>.findings.json` says `"none": true`, there is nothing to report: stop and say so in one line. Do not write a report about nothing.
|
|
32
|
+
5. Choose the outline for these readers and this question. Any sections, any titles, any order.
|
|
33
|
+
- A recurring report keeps `agreed_outline`, the sections of its last issued issue. Add a section only when a finding needs one, drop one only when it would be empty, and say so in `outline_note` (one line).
|
|
34
|
+
- `earlier_outline` is the shape of an issue written before the engine (the old fixed frame). It is an example, not an agreement: keep what served the readers.
|
|
35
|
+
- Each section title is a finding, not a label: "Sign-up stalls before submit", not "Sign-up". Reading only the titles tells the story.
|
|
36
|
+
- Shapes other reports took, as examples and never a menu: a decision (the lean · the options and what each costs · what could reverse it · your call); a watch (today against yesterday and the week · the drop that moved most · why); a stakeholder update (are the dates on track · what each team needs and by when · open decisions · what could stop it); a review (the summary for decision · the outcomes by segment · the challenges and answers · method); did-it-work (what was promised · what we got · the verdict).
|
|
37
|
+
6. Write `<slot>.report.json` (in a scratch file, then `pmos report write <id> --from <file>`):
|
|
38
|
+
`{"title":"…{{r:…}}…","answer":{"text":"…","supports":["Label: …{{r:…}}…"]},"sections":[{"id":"…","title":"…","blocks":[{"kind":"p","text":"…"},{"kind":"list","items":["…"]},{"kind":"table","columns":["…"],"rows":[["…"]]},{"kind":"bars","title":"…","rows":[["label","{{r:id}}"]]},{"kind":"options","options":[{"name":"…","text":"…"}]},{"kind":"quote","text":"…"}]}],"ask":{"text":"…","who":"…","by":"YYYY-MM-DD","options":["…"]},"beyond":{"why":"…","so_what":"…","now_what":"…","since":"…","would_change":"…","unknown":["…"],"else":["…"],"next_question":"…"},"questions":[{"question":"<a question of the brief>","answered_in":"<section id or answer>","gap":"<why it cannot be answered>"}],"outline_note":"…"}`.
|
|
39
|
+
- `ask` is null when the readers have nothing to decide. When it is a call with no better option on the evidence, give the options and say "your call".
|
|
40
|
+
- BEYOND THE ASK. Answer the readers' next three questions before they ask: why (the cause, from the evidence), so what (the effect on the target and its date), now what (the recommendation, who, by), since the last issue (what moved, and each carried ask), what would change it (the one or two readings that would flip the recommendation), what we don't know (the gaps, counted, never padded), what else is here (at most two findings from a named source the readers did not ask about, when their question depends on them) and the next question (the split they will ask for next). Each part cites a reading. Leave a part out when no reading backs it, and leave out a part the brief's rules turn off.
|
|
41
|
+
- `questions`: map each question of the brief after the first to the section that answers it, or give the gap.
|
|
42
|
+
7. Read what `pmos report write` prints. A refusal names the check: fix the report and run it again. When it passes, it writes `<slot>.md` and `<slot>.checks.json`; the deck, the PDF and the PowerPoint are drawn from the same model, in the report's saved look.
|
|
43
|
+
8. Learn. When the PM's change in the chat is about the words (shorter, plainer, another tone) and it would apply to every issue, keep it: `pmos report rule <id> add wording "<the rule, one line>"`. When the PM removes a part beyond the ask, `pmos report rule <id> add off <part>`. Then change report.json and run `pmos report write` again. A change to a number is a change to a reading: read the source again and file it.
|
|
44
|
+
9. Finish by saying in one line where the draft is and how many readings, findings and gaps it has. Do not commit; the PM's Sync carries the files.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Guide
|
|
3
|
-
title: "Ask the agent from the page"
|
|
4
|
-
description: "How the console's Ask the agent, Fix with the agent, Have the agent draft it, a spike and an early gate start an agent from the page, what the agent may do, and what stays yours."
|
|
5
|
-
timestamp: 2026-10-12
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Ask the agent from the page
|
|
9
|
-
|
|
10
|
-
Five presses in the console (`/`) start an agent from the page. You do not need a terminal, and you do not copy a request anywhere. Each run is listed in Sessions, so you can follow it there.
|
|
11
|
-
|
|
12
|
-
## Ask the agent on a document
|
|
13
|
-
|
|
14
|
-
1. Open a document in Initiatives › Documents, or open a report as a document from Reports.
|
|
15
|
-
2. Select **Proposals**, write what to change, and select **Ask the agent**.
|
|
16
|
-
3. The sheet says that the agent is drafting. You can close the sheet and come back.
|
|
17
|
-
4. When the draft is ready, it shows in **Proposals** with the difference, section by section.
|
|
18
|
-
5. Clear the tick of any section that you do not want, and slide to accept. Or select **Change the request** or **Reject**.
|
|
19
|
-
|
|
20
|
-
The agent runs in the background and can only read: it has the Read, Glob and Grep tools and nothing else. It answers with the revised document. The workspace records that answer as a proposal. The file does not change until you slide to accept it, and the slide is bound to the proposal's hash. If the document changed while the agent worked, the sheet tells you to ask again.
|
|
21
|
-
|
|
22
|
-
**Copy the request** stays beside the button. Use it to give the request to a session that you already have open.
|
|
23
|
-
|
|
24
|
-
On a document's **Health** segment, **Fix with the agent** writes the fix as the request and opens Proposals.
|
|
25
|
-
|
|
26
|
-
## Fix with the agent on a report
|
|
27
|
-
|
|
28
|
-
In Reports, open a section that is not traced and select **Fix with the agent**. The report opens as a document on Proposals, with the fix written in. A report that is not issued yet has no stored document, so the sheet tells you to issue it first.
|
|
29
|
-
|
|
30
|
-
## Lifecycle: a draft, a spike and an early gate
|
|
31
|
-
|
|
32
|
-
These three start an ordinary agent session, the same as Next step › Go. The session opens on the initiative's branch and is listed in Sessions.
|
|
33
|
-
|
|
34
|
-
| Press | What the agent does |
|
|
35
|
-
|---|---|
|
|
36
|
-
| **Have the agent: draft it** on a stage requirement | Drafts that requirement for the initiative, following AGENTS.md. |
|
|
37
|
-
| **Run a 1-day spike first** on an idea | Writes a spike brief: the assumption, the cheapest test, and the result that would change the decision. |
|
|
38
|
-
| **Request an early** gate in Quality gates | Checks the work so far against the PRD and its done-criteria, and writes down what passes and what fails. |
|
|
39
|
-
|
|
40
|
-
The page sends only the task, the initiative and a short label. The prompt is fixed by the workspace. Each prompt tells the agent to leave a draft for you to read, and not to merge, push or send anything outside PMOS. Decisions that are yours, such as a stage decision, still have no start button.
|
|
41
|
-
|
|
42
|
-
## When the agent does not start
|
|
43
|
-
|
|
44
|
-
- **Background runs are switched off here.** `PMOS_HEADLESS=off` is set, so Ask the agent cannot run in the background. Copy the request to a session instead.
|
|
45
|
-
- **This workspace cannot start sessions.** The workspace has no agent to start. Open the workspace from the PMOS app.
|
|
46
|
-
- **The agent took too long and was stopped.** Ask again with a smaller request.
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Guide
|
|
3
|
-
title: "Briefing: cards, time of day, Needs you and Portfolio pulse"
|
|
4
|
-
description: "How the Briefing cards keep one height and flip in place, how to confirm an act on a large screen, how the day part follows the clock, how a Portfolio pulse row opens inline, and how overdue items reach Needs you."
|
|
5
|
-
timestamp: 2026-10-12
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Briefing: cards, time of day, Needs you and Portfolio pulse
|
|
9
|
-
|
|
10
|
-
## Cards
|
|
11
|
-
|
|
12
|
-
Every card in a deck has the same height at rest. Text that does not fit is cut short. The front shows the numbers the card carries as tiles, with a short kind label. Press a card to turn it over. The card turns in about a third of a second. The back grows to fit its content, so the options and the confirm control are never cut off. The other cards in the row keep their size, and the page below the deck moves down. Press the top line of the back to turn it again. When you decide, the card shows a check and a message offers **Undo**. With reduced motion on, the card changes at once.
|
|
13
|
-
|
|
14
|
-
The page background is white. A soft, slow glow of colour drifts behind the page. With reduced motion on, it is one still picture.
|
|
15
|
-
|
|
16
|
-
The tabs show counts: Briefing shows how many things need you, Work shows its inbox, and Initiatives shows new asks to triage. The Sessions button is a bolt icon with no label, and the dock button shows a bolt too. In the demo, the Record button and its arrow are visible when nothing is recording.
|
|
17
|
-
|
|
18
|
-
### Kinds of card
|
|
19
|
-
|
|
20
|
-
The label on a card says what kind of thing happened, for example **Deadline moved**, **Promise out of date**, **Blocked**, **Conflict**, **Risk**, **Waiting on someone** or **Report due**. A win keeps the label **Big win** or **Small win**. A card from your own data has the label **Overdue**, **Due today**, **Blocked**, **Worth asking** or **For you today** (see The Briefing: today's brief). The colour of the card shows how serious it is: red is critical, amber is a warning, green is good news, and the accent colour is neutral.
|
|
21
|
-
|
|
22
|
-
Each kind has a short list of what its card must say. For example, a **Deadline moved** card says what moved, by how much, by when you must decide and the one move. When the card does not know a part, the back of the card says so under **Not known yet**. PMOS does not guess a missing part.
|
|
23
|
-
|
|
24
|
-
A card shows only when it is relevant enough and links to a page that you can open. Critical cards always show. When nothing is relevant enough, there is no card.
|
|
25
|
-
|
|
26
|
-
The icon of a card comes from fixed rules over the kind of the card. A kind the rules do not know gets a neutral icon. No card text leaves your machine to choose an icon.
|
|
27
|
-
|
|
28
|
-
## Confirm an act
|
|
29
|
-
|
|
30
|
-
On a screen with a mouse or trackpad, an act shows a compact button.
|
|
31
|
-
|
|
32
|
-
- An act that sends something out, or that cannot be undone, asks you to press and hold. A ring fills for 0.6 seconds, and the act runs when it is full.
|
|
33
|
-
- Any other act runs on one click.
|
|
34
|
-
- With the keyboard, press Enter or Space on the button, then choose **Confirm** or **Cancel**. Escape closes the step.
|
|
35
|
-
|
|
36
|
-
On a touch screen the slide stays. It is at most 320 pixels wide.
|
|
37
|
-
|
|
38
|
-
## Time of day
|
|
39
|
-
|
|
40
|
-
There is no selector for the part of the day. The Briefing reads the clock and checks it every five minutes. When the part of the day changes, the cards are ranked again only after you have not touched the page for a minute and no card is open, or the next time the page loads. A thin strip in the top bar shows the sun or the moon on the day's arc, with sunrise and sunset. It is worked out on this machine from the date and the time zone. It makes no network request.
|
|
41
|
-
|
|
42
|
-
## Portfolio pulse
|
|
43
|
-
|
|
44
|
-
Press a row of the Portfolio pulse to see it open under the row, on the Briefing. The tab does not change. The open row shows the promised date, the forecast and the slip. Press **Open initiative** inside it to go to the Initiatives tab.
|
|
45
|
-
|
|
46
|
-
## Needs you
|
|
47
|
-
|
|
48
|
-
Needs you also lists your own items that are overdue or due today. Overdue items come first, the most overdue first, then items due today. A row says how many days overdue it is. Done items, parked items, items waiting on someone and items without a date are not listed. At most five show.
|
|
49
|
-
|
|
50
|
-
## Work
|
|
51
|
-
|
|
52
|
-
The Work page shows **Focus** in its right column. There is no Flow today card and no Jobs card: you open a job from a Focus row.
|