create-pmos 0.515.0 → 0.517.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 +41 -71
- package/payload/KIT-VERSION +2 -2
- 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/payload/state/log.md +1 -1
- package/workspace/briefing-premium-calendar-test.js +6 -3
- package/workspace/briefing-premium-insights-test.js +2 -2
- package/workspace/changelog.json +40 -0
- package/workspace/ev-everywhere-test.js +3 -3
- package/workspace/fixtures/premium-viewer-fixtures.js +4 -2
- package/workspace/guide/agent-capabilities.md +73 -0
- 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/docs.md +10 -125
- package/workspace/guide/home.md +8 -5
- package/workspace/guide/index.md +79 -78
- 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-needs-you.md +34 -0
- 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/report-acts.js +189 -0
- 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-insights-premium.js +17 -3
- package/workspace/lib/routes-ready-reports.js +11 -2
- package/workspace/lib/routes-report-design.js +7 -2
- package/workspace/lib/routes-report-setups.js +38 -3
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/premium-vw-meet-test.js +9 -5
- package/workspace/public/pm/cozy-evui.js +1 -0
- package/workspace/public/pm/cozy-insights.css +34 -0
- package/workspace/public/pm/cozy-nav.js +4 -1
- package/workspace/public/pm/home-app.js +3 -1
- package/workspace/public/pm/premium-insights.js +112 -14
- 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/public/premium-intelligence.html +1 -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/test-lists/reports-needs-you.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
|
@@ -37,8 +37,23 @@ const actorLib = require('./actor.js');
|
|
|
37
37
|
const RS = require('./report-setups.js');
|
|
38
38
|
const { parseArgs } = require('./schedule-cli');
|
|
39
39
|
|
|
40
|
-
const COMMANDS = { report: ['draft', 'issue', 'list', 'propose', 'definitions', 'setups', 'finder'] };
|
|
40
|
+
const COMMANDS = { report: ['make', 'read', 'find', 'write', 'check', 'rule', 'draft', 'issue', 'list', 'propose', 'definitions', 'setups', 'finder'] };
|
|
41
41
|
const USAGE = [
|
|
42
|
+
'usage: pmos report make|read|find|write|check|rule — the report engine: brief, read, find, answer, render (any report, any shape)',
|
|
43
|
+
' pmos report make <id> [--ask "<the question>"] [--readers "<who>"] [--source <kind:ref>,…] [--slot <date>]',
|
|
44
|
+
' Steps 1 to 3: derive the brief (readers, question, window, sources; no section list), read every source PMOS reaches,',
|
|
45
|
+
' and find what changed. An ad hoc report needs --ask. Sources: pmos · pack:<state file of readings> · connector:<name> · document:<path>.',
|
|
46
|
+
' pmos report read <id> [--slot <date>] --from <file|->',
|
|
47
|
+
' File the readings you read through a connector or a document: {"readings":[{id,value,unit,at,source,how,label,n,of,target}],',
|
|
48
|
+
' "gaps":[{source,reason}]}. Every reading has a source of the brief, a date and how it was read.',
|
|
49
|
+
' pmos report find <id> [--slot <date>] --from <file|->',
|
|
50
|
+
' File the findings that answer the question: {"findings":[{text,readings:[ids],kind,question}]}. Each cites readings.',
|
|
51
|
+
' pmos report write <id> [--slot <date>] --from <file|->',
|
|
52
|
+
' Step 4 to 6: check the report.json you wrote (the outline is yours), render the document and the deck, write the checks.',
|
|
53
|
+
' Refused when there is no answer with a reading, or when a figure is not a reading {{r:<id>}}.',
|
|
54
|
+
' pmos report check <id> [--slot <date>] the checks of the last write: substance first, then form',
|
|
55
|
+
' pmos report rule <id> list | add <voice|wording|off|keep> "<text or part>" | remove <n>',
|
|
56
|
+
' What the readers taught this report: a voice or wording rule, or a part beyond the ask turned off or kept.',
|
|
42
57
|
'usage: pmos report draft|issue|list — cadence reports (for example the biweekly)',
|
|
43
58
|
' pmos report draft <cadence> [<slot>] [--now <time>] [--redraft]',
|
|
44
59
|
' Write the draft for a slot (default: today) with every number. Refuses a slot that has a draft;',
|
|
@@ -59,8 +74,9 @@ const USAGE = [
|
|
|
59
74
|
' every command: [--json] [--root <dir>]. The cadence is the report skill id without "report-", for example biweekly.',
|
|
60
75
|
];
|
|
61
76
|
const BOOL = new Set(['json', 'redraft', 'help']);
|
|
62
|
-
const VALUE = new Set(['now', 'root']);
|
|
63
|
-
const ALLOWED = {
|
|
77
|
+
const VALUE = new Set(['now', 'root', 'ask', 'readers', 'source', 'slot', 'from']);
|
|
78
|
+
const ALLOWED = { make: ['json', 'now', 'root', 'ask', 'readers', 'source', 'slot'], read: ['json', 'now', 'root', 'slot', 'from', 'source'], find: ['json', 'now', 'root', 'slot', 'from'],
|
|
79
|
+
write: ['json', 'now', 'root', 'slot', 'from'], check: ['json', 'root', 'slot'], rule: ['json', 'root'], draft: ['json', 'redraft', 'now', 'root'], issue: ['root'], list: ['json', 'root'], propose: ['json', 'root'], definitions: ['json', 'root'], setups: ['json', 'root'], finder: ['json', 'root'] };
|
|
64
80
|
const CADENCE_RE = /^[a-z][a-z0-9-]{0,39}$/;
|
|
65
81
|
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
66
82
|
|
|
@@ -129,6 +145,7 @@ async function run(argv, { say = (s) => console.log(s), cwd = process.cwd(), isT
|
|
|
129
145
|
return 0;
|
|
130
146
|
}
|
|
131
147
|
|
|
148
|
+
if (['make', 'read', 'find', 'write', 'check', 'rule'].includes(verb)) return engineVerb(verb, { pos, flags, root, json, say, fail, isTTY, env, stdin, now });
|
|
132
149
|
if (verb === 'definitions' || verb === 'setups' || verb === 'propose' || verb === 'finder') return reportWorkspace(verb, { pos, flags, root, json, say, fail, cwd, isTTY, env, stdin, now });
|
|
133
150
|
|
|
134
151
|
const [cadence, slot] = pos;
|
|
@@ -170,6 +187,98 @@ async function run(argv, { say = (s) => console.log(s), cwd = process.cwd(), isT
|
|
|
170
187
|
return 0;
|
|
171
188
|
}
|
|
172
189
|
|
|
190
|
+
/** The report engine's verbs (lib/report-engine.js). An agent session and the PM may run them; issuing stays the PM's (`pmos report issue`). */
|
|
191
|
+
function engineVerb(verb, { pos, flags, root, json, say, fail, isTTY, env, stdin, now }) {
|
|
192
|
+
const RE = require('./report-engine.js');
|
|
193
|
+
const id = pos[0];
|
|
194
|
+
if (!id || !RE.ID_RE.test(id)) { say(`usage: pmos report ${verb} <id> … (the id is lower case letters, digits and dashes, for example scarlet-assessment)`); return 2; }
|
|
195
|
+
let clock = now == null ? Date.now() : now;
|
|
196
|
+
if (flags.now !== undefined) { clock = Date.parse(flags.now); if (!Number.isFinite(clock)) return fail('--now must be a time, for example 2026-10-16T09:00:00Z', 2); }
|
|
197
|
+
const slot = flags.slot !== undefined ? flags.slot : undefined;
|
|
198
|
+
if (slot !== undefined && !isDate(slot)) return fail('--slot must be a date, YYYY-MM-DD', 2);
|
|
199
|
+
const day = slot || new Date(clock).toISOString().slice(0, 10);
|
|
200
|
+
const who = actorLib.fromCli({ ...(isTTY === undefined ? {} : { isTTY }), ...(env === undefined ? {} : { env }) });
|
|
201
|
+
const readFrom = () => {
|
|
202
|
+
const src = flags.from;
|
|
203
|
+
if (!src) return { error: `--from <file|-> is required: the JSON to file` };
|
|
204
|
+
let text;
|
|
205
|
+
try { text = src === '-' ? (typeof stdin === 'string' ? stdin : fs.readFileSync(0, 'utf8')) : fs.readFileSync(path.resolve(src), 'utf8'); } catch { return { error: `could not read ${src === '-' ? 'standard input' : src}` }; }
|
|
206
|
+
try { const o = JSON.parse(text); return o && typeof o === 'object' ? { body: o } : { error: 'the JSON is an object' }; } catch { return { error: 'that is not JSON' }; }
|
|
207
|
+
};
|
|
208
|
+
const sources = flags.source ? String(flags.source).split(',').map((x) => x.trim()).filter(Boolean) : [];
|
|
209
|
+
const bad = sources.find((x) => !RE.parseSource(x));
|
|
210
|
+
if (bad) return fail(`--source ${bad}: write pmos, pack:<file>, connector:<name> or document:<path>`, 2);
|
|
211
|
+
const summary = (m) => {
|
|
212
|
+
const f = m.findings; const g = m.readings.gaps;
|
|
213
|
+
if (json) { say(JSON.stringify({ ok: true, brief: m.brief, readings: m.readings.readings.length, gaps: g, findings: f.findings, none: f.none, paths: m.paths })); return 0; }
|
|
214
|
+
say(`✓ Brief ${m.paths.brief}: for ${m.brief.readers}. Question: ${m.brief.question}`);
|
|
215
|
+
say(` ${m.readings.readings.length} reading(s); ${g.length ? `${g.length} gap(s): ${g.map((x) => `${x.source} (${x.reason})`).join('; ')}` : 'no gap'}.`);
|
|
216
|
+
say(f.none ? ' No finding, so no draft: nothing to report yet. Read the sources the gaps name and file the readings: pmos report read ' + id + ' --from <file>'
|
|
217
|
+
: ` ${f.findings.length} finding(s): ${f.findings.slice(0, 3).map((x) => x.text).join(' · ')}`);
|
|
218
|
+
if (!f.none) say(` Next: write ${m.paths.report} (the outline is yours) and run: pmos report write ${id}${slot ? ' --slot ' + slot : ''} --from <file>`);
|
|
219
|
+
return 0;
|
|
220
|
+
};
|
|
221
|
+
if (verb === 'make') {
|
|
222
|
+
const m = RE.make(root, id, { slot: day, ask: flags.ask, readers: flags.readers, sources, now: clock });
|
|
223
|
+
if (!m.ok) return fail(m.error);
|
|
224
|
+
return summary(m);
|
|
225
|
+
}
|
|
226
|
+
if (verb === 'read' || verb === 'find') {
|
|
227
|
+
const r = readFrom(); if (r.error) return fail(r.error, 2);
|
|
228
|
+
const add = verb === 'read' ? { add: r.body.readings || [], gaps: r.body.gaps || [] } : { addFindings: r.body.findings || [] };
|
|
229
|
+
const m = RE.make(root, id, { slot: day, sources, ...add, now: clock });
|
|
230
|
+
if (!m.ok) return fail(m.error);
|
|
231
|
+
return summary(m);
|
|
232
|
+
}
|
|
233
|
+
if (verb === 'write') {
|
|
234
|
+
const r = readFrom(); if (r.error) return fail(r.error, 2);
|
|
235
|
+
const w = RE.write(root, id, day, r.body, { actor: who, now: clock });
|
|
236
|
+
if (!w.ok) {
|
|
237
|
+
if (json) { say(JSON.stringify({ ok: false, error: w.error, checks: w.checks || null, none: !!w.none })); return 1; }
|
|
238
|
+
say(`✗ ${w.error}`);
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
if (json) { say(JSON.stringify({ ok: true, path: w.path, report: w.report, checks: w.checks })); return 0; }
|
|
242
|
+
say(`✓ Wrote ${w.path} from ${w.report}. The deck is drawn from the same model.`);
|
|
243
|
+
for (const c of w.checks) say(` ${c.pass ? '✓' : '✗'} ${c.id}: ${c.reason}`);
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
if (verb === 'check') {
|
|
247
|
+
let P; try { P = RE.paths(root, id, day); } catch (e) { return fail(e.message, 2); }
|
|
248
|
+
let c; try { c = JSON.parse(fs.readFileSync(P.checks.abs, 'utf8')); } catch { return fail(`${id} ${day} has no checks yet: pmos report write ${id} --from <file>`); }
|
|
249
|
+
if (json) { say(JSON.stringify({ ok: true, ...c })); return 0; }
|
|
250
|
+
for (const x of c.checks) say(`${x.pass ? '✓' : '✗'} ${x.id}: ${x.reason}`);
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
// rule
|
|
254
|
+
const act = pos[1] || 'list';
|
|
255
|
+
if (act === 'list') {
|
|
256
|
+
const rules = RE.rulesOf(root, id);
|
|
257
|
+
if (json) { say(JSON.stringify({ ok: true, rules })); return 0; }
|
|
258
|
+
if (!rules.length) say(`${id} has no rule yet; the default voice applies.`);
|
|
259
|
+
for (const x of rules) say(`${x.n} ${x.kind} ${x.text || x.part}${x.from ? ` (from ${x.from})` : ''}`);
|
|
260
|
+
return 0;
|
|
261
|
+
}
|
|
262
|
+
if (!actorLib.isPm(who) && !actorLib.isAgent(who)) return fail('only the PM or an agent session can change a report\'s rules');
|
|
263
|
+
if (act === 'add') {
|
|
264
|
+
const kind = pos[2]; const text = pos.slice(3).join(' ');
|
|
265
|
+
const r = RE.addRule(root, id, { kind, text: kind === 'off' || kind === 'keep' ? null : text, part: kind === 'off' || kind === 'keep' ? text : null, from: actorLib.isPm(who) ? 'the PM' : 'the writer', by: who.by, now: clock });
|
|
266
|
+
if (!r.ok) return fail(r.error);
|
|
267
|
+
if (json) { say(JSON.stringify({ ok: true, rule: r.rule })); return 0; }
|
|
268
|
+
say(`✓ Rule ${r.rule.n} kept for ${id}: ${r.rule.text || `${r.rule.kind} ${r.rule.part}`}`);
|
|
269
|
+
return 0;
|
|
270
|
+
}
|
|
271
|
+
if (act === 'remove') {
|
|
272
|
+
const r = RE.removeRule(root, id, Number(pos[2]), { by: who.by, now: clock });
|
|
273
|
+
if (!r.ok) return fail(r.error);
|
|
274
|
+
if (json) { say(JSON.stringify({ ok: true })); return 0; }
|
|
275
|
+
say(`✓ Rule ${pos[2]} removed.`);
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
say('usage: pmos report rule <id> list | add <kind> "<text>" | remove <n>');
|
|
279
|
+
return 2;
|
|
280
|
+
}
|
|
281
|
+
|
|
173
282
|
/** The report workspace's verbs. `propose` is the one an agent run may call; `finder` is the PM's. */
|
|
174
283
|
function reportWorkspace(verb, { pos, flags, root, json, say, fail, isTTY, env, stdin, now }) {
|
|
175
284
|
const E = env === undefined ? process.env : env;
|