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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.517.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,46 @@
|
|
|
32
32
|
"audit"
|
|
33
33
|
],
|
|
34
34
|
"pmosChanges": [
|
|
35
|
+
{
|
|
36
|
+
"v": "0.517.0",
|
|
37
|
+
"at": "2026-11-04T00:17:56.633Z",
|
|
38
|
+
"f": 4,
|
|
39
|
+
"prs": [
|
|
40
|
+
{
|
|
41
|
+
"n": 1207,
|
|
42
|
+
"t": "User guide in PMOS (option B) and guide pages brought up to date",
|
|
43
|
+
"s": "User guide in PMOS (option B) and guide pages brought up to date",
|
|
44
|
+
"k": "new"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"n": 1210,
|
|
48
|
+
"t": "The report engine: brief, read, find, write, one deck, no draft without a finding",
|
|
49
|
+
"s": "The report engine: brief, read, find, write, one deck, no draft without a finding",
|
|
50
|
+
"k": "new"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"v": "0.516.0",
|
|
56
|
+
"at": "2026-11-04T00:00:07.601Z",
|
|
57
|
+
"f": 4,
|
|
58
|
+
"prs": [
|
|
59
|
+
{
|
|
60
|
+
"n": 1209,
|
|
61
|
+
"t": "Runbook of what Claude does behind the scenes, in the guide",
|
|
62
|
+
"s": "Runbook of what Claude does behind the scenes, in the guide",
|
|
63
|
+
"k": "x",
|
|
64
|
+
"h": "See what Claude does behind the scenes",
|
|
65
|
+
"d": "Claude's background jobs were explained one page at a time, and nothing listed them all together. One guide page lists every job Claude runs by itself: when it runs, what it reads, where you see the result, how to stop it, and what Claude fixes without asking."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"n": 1208,
|
|
69
|
+
"t": "Reports that need you come first, one ✓ each (redesign R)",
|
|
70
|
+
"s": "Reports that need you come first, one ✓ each (redesign R)",
|
|
71
|
+
"k": "new"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
35
75
|
{
|
|
36
76
|
"v": "0.515.0",
|
|
37
77
|
"at": "2026-11-03T23:11:51.264Z",
|
|
@@ -392,76 +432,6 @@
|
|
|
392
432
|
"d": "A blocked step could interrupt you with a question. Now the initiative's workflow decides the next step, and a blocked one shows up only as a ✦ proposal."
|
|
393
433
|
}
|
|
394
434
|
]
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
"v": "0.497.0",
|
|
398
|
-
"at": "2026-11-03T02:09:19.399Z",
|
|
399
|
-
"f": 4,
|
|
400
|
-
"prs": [
|
|
401
|
-
{
|
|
402
|
-
"n": 1174,
|
|
403
|
-
"t": "Count only a real Jira handoff record, not keys in body text",
|
|
404
|
-
"s": "Count only a real Jira handoff record, not keys in body text",
|
|
405
|
-
"k": "fix",
|
|
406
|
-
"h": "Jira counts are honest",
|
|
407
|
-
"d": "A Jira key mentioned in some text counted as a handoff. Now only a real handoff counts."
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
"n": 1175,
|
|
411
|
-
"t": "The Viewer shows what a chat turn changed, with no refresh",
|
|
412
|
-
"s": "The Viewer shows what a chat turn changed, with no refresh",
|
|
413
|
-
"k": "fix",
|
|
414
|
-
"h": "See what a chat changed",
|
|
415
|
-
"d": "After a chat changed something, the Viewer still showed the old version until you refreshed. Now it updates on its own."
|
|
416
|
-
}
|
|
417
|
-
]
|
|
418
|
-
},
|
|
419
|
-
{
|
|
420
|
-
"v": "0.496.0",
|
|
421
|
-
"at": "2026-11-03T00:29:32.573Z",
|
|
422
|
-
"f": 4,
|
|
423
|
-
"prs": [
|
|
424
|
-
{
|
|
425
|
-
"n": 1172,
|
|
426
|
-
"t": "Initiative chats find the initiative's workflow through pmos, never a lane",
|
|
427
|
-
"s": "Initiative chats find the initiative's workflow through pmos, never a lane",
|
|
428
|
-
"k": "fix",
|
|
429
|
-
"h": "Initiative chats find the right workflow",
|
|
430
|
-
"d": "An initiative's chat could miss the workflow it should follow. Now it always finds it, including the ones in your own library."
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
"n": 1170,
|
|
434
|
-
"t": "Keep a rejected ✦ suggestion rejected while its facts hold",
|
|
435
|
-
"s": "Keep a rejected ✦ suggestion rejected while its facts hold",
|
|
436
|
-
"k": "fix",
|
|
437
|
-
"h": "A no stays a no",
|
|
438
|
-
"d": "A ✦ suggestion you turned down could come back the next day. Now it stays rejected while nothing about it changes."
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
"n": 1171,
|
|
442
|
-
"t": "Tasks keep their mapped stage after a workflow switch on Home and Board",
|
|
443
|
-
"s": "Tasks keep their mapped stage after a workflow switch on Home and Board",
|
|
444
|
-
"k": "fix",
|
|
445
|
-
"h": "Tasks keep their stage",
|
|
446
|
-
"d": "Switching an initiative's workflow could move its tasks to the wrong stage. Now they keep the stage they were mapped to."
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
"n": 1173,
|
|
450
|
-
"t": "Calmer Board top bar",
|
|
451
|
-
"s": "Calmer Board top bar",
|
|
452
|
-
"k": "new",
|
|
453
|
-
"h": "A calmer Board top bar",
|
|
454
|
-
"d": "The Board's top bar was crowded. Now it is lighter, with fewer controls in your way."
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
"n": 1165,
|
|
458
|
-
"t": "Pages show something at once while they read",
|
|
459
|
-
"s": "Pages show something at once while they read",
|
|
460
|
-
"k": "new",
|
|
461
|
-
"h": "Pages show something at once",
|
|
462
|
-
"d": "A page stayed blank while it read its data. Now it shows its shape right away and fills in as data arrives."
|
|
463
|
-
}
|
|
464
|
-
]
|
|
465
435
|
}
|
|
466
436
|
]
|
|
467
437
|
}
|
package/payload/KIT-VERSION
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
kernel-source: pmos@
|
|
2
|
-
assembled: 2026-11-
|
|
1
|
+
kernel-source: pmos@2580bd8d
|
|
2
|
+
assembled: 2026-11-04
|
|
3
3
|
mode: vendor
|
|
@@ -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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-04T00:17:54Z"}
|
|
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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-04T00:17:54Z"}
|
|
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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-04T00:17:54Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
package/payload/state/log.md
CHANGED
|
@@ -36,19 +36,22 @@ const json = (r, b, status = 200) => r.fulfill({ status, contentType: 'applicati
|
|
|
36
36
|
srv = spawn(process.execPath, [path.join(__dirname, 'server.js')], { cwd: __dirname, stdio: 'ignore', env: T.env({ PMOS_WS_PORT: String(T.PORT) }) });
|
|
37
37
|
await T.waitForServer(BASE);
|
|
38
38
|
browser = await chromium.launch({ executablePath: exe });
|
|
39
|
-
|
|
39
|
+
/* One clock for the page and the stand-ins: today at 11:00, so "Rail review" (30 minutes on) and the meeting 40 minutes back are today
|
|
40
|
+
* at any hour the suite runs. Unpinned, after 23:30 the review fell on tomorrow and C2 failed. */
|
|
41
|
+
const NOW = new Date(); NOW.setHours(11, 0, 0, 0);
|
|
42
|
+
const W = F.world(NOW);
|
|
40
43
|
const tap = (p, sel) => p.$eval('#czViewer ' + sel, (b) => b.click());
|
|
41
44
|
const text = (p) => p.evaluate(() => (document.querySelector('#czViewer') || {}).innerText || '');
|
|
42
45
|
const weekReads = (S) => S.gets.filter((g) => g.startsWith('/api/calendar-views')).length;
|
|
43
46
|
const ALL = [];
|
|
44
|
-
const open = async (url, o) => { const X = await F.open(browser, BASE, url, { noLive: true, ...o }); ALL.push(X); return X; };
|
|
47
|
+
const open = async (url, o) => { const X = await F.open(browser, BASE, url, { noLive: true, now: NOW, ...o }); ALL.push(X); return X; };
|
|
45
48
|
|
|
46
49
|
/* C1 the strip (on a Saturday or Sunday no day of the Mon–Fri strip is today, so none is pressed) */
|
|
47
50
|
const A = await open('/premium-viewer.html?open=calendar');
|
|
48
51
|
const p = A.page;
|
|
49
52
|
// Viewer kit (XvACal): the calendar opens on the day, with today's summary first; the week and month are in ⋯
|
|
50
53
|
ok('C1 the calendar opens in the Viewer card on the day', await until(() => p.evaluate(() => document.querySelectorAll('#czViewer .vzc-dy').length === 5 && document.querySelectorAll('#czViewer .vzc-de').length > 0), 15000));
|
|
51
|
-
const weekday = ![0, 6].includes(
|
|
54
|
+
const weekday = ![0, 6].includes(NOW.getDay());
|
|
52
55
|
await until(() => p.evaluate(() => [...document.querySelectorAll('#czViewer .vzc-dy')].every((d) => d.getBoundingClientRect().height >= 44)), 8000); // the Meetings stylesheet loads after the day is drawn
|
|
53
56
|
const strip = await p.evaluate(() => [...document.querySelectorAll('#czViewer .vzc-dy')].map((d) => ({ dow: d.querySelector('span').textContent, on: d.getAttribute('aria-pressed'), h: Math.round(d.getBoundingClientRect().height) })));
|
|
54
57
|
ok('C1 the strip has Monday to Friday and today is pressed on a weekday', strip.map((d) => d.dow).join() === 'MON,TUE,WED,THU,FRI' && strip.filter((d) => d.on === 'true').length === (weekday ? 1 : 0), JSON.stringify(strip));
|
|
@@ -390,9 +390,9 @@ const BMR = { ok: true, state: 'ready', model: { tiles: [
|
|
|
390
390
|
const R = await open(), q = R.page;
|
|
391
391
|
await q.click('#moreB'); await q.click('#moreMenu [data-more=\"library\"]');
|
|
392
392
|
/* re-pointed (premium-uncovered-features, IsLibrary): the bar hands New report to Home, Found in your work is cards, the reports are Report · Next · Status */
|
|
393
|
-
const lb = await q.evaluate(() => ({ side: !document.querySelector('#libSide').hidden, nr: document.querySelector('#newRep').getAttribute('href'), found: document.querySelector('#listRows .ins-fdh b').textContent, fcards: [...document.querySelectorAll('#listRows .ins-fcard')].map((c) => c.dataset.f + ':' + [...c.querySelectorAll('.ins-btn[data-fx]')].map((b) => b.textContent).join('/')).join(), heads: [...document.querySelectorAll('#repAsks .ins-rlh span')].map((s) => s.textContent).join('|'), rows: [...document.querySelectorAll('#repNeeds .ins-rl:not(.ins-rlh), #listRows .ins-rl:not(.ins-rlh)')].map((r) => r.querySelector('.nm b').textContent + '|' + r.querySelector('.nx').textContent + '|' + r.querySelector('.st').textContent).join(' / '), setups: document.querySelectorAll('#repNeeds [data-setup], #listRows [data-setup]').length, asks: document.querySelectorAll('#repNeeds [data-ask], #listRows [data-ask]').
|
|
393
|
+
const lb = await q.evaluate(() => ({ side: !document.querySelector('#libSide').hidden, nr: document.querySelector('#newRep').getAttribute('href'), found: document.querySelector('#listRows .ins-fdh b').textContent, fcards: [...document.querySelectorAll('#listRows .ins-fcard')].map((c) => c.dataset.f + ':' + [...c.querySelectorAll('.ins-btn[data-fx]')].map((b) => b.textContent).join('/')).join(), heads: [...document.querySelectorAll('#repAsks .ins-rlh span')].map((s) => s.textContent).join('|'), rows: [...document.querySelectorAll('#repNeeds .ins-rl:not(.ins-rlh), #listRows .ins-rl:not(.ins-rlh)')].map((r) => r.querySelector('.nm b').textContent + '|' + r.querySelector('.nx').textContent + '|' + r.querySelector('.st').textContent).join(' / '), needs: [...document.querySelectorAll('#repNeeds .ins-nrow .nm b')].map((b) => b.textContent).join('|'), setups: document.querySelectorAll('#repNeeds [data-setup], #listRows [data-setup]').length, asks: new Set([...document.querySelectorAll('#repNeeds [data-ask], #listRows [data-ask]')].map((e) => e.dataset.ask)).size, cards: [...document.querySelectorAll('#listRows .ins-dcard')].map((c) => c.dataset.d + (c.querySelector('.ins-pinned') ? '*' : '')).join(), cap: document.querySelector('#repCap').textContent, old: !!document.querySelector('#listSeg, #sugB') }));
|
|
394
394
|
ok('L1 Reports and dashboards opens as a side panel from ⋯; New report in Home hands off there, and Found in your work holds the finding as a card', lb.side && /^\/premium\.html\?ws=w1&ask=insights&q=Make%20a%20new%20report/.test(lb.nr) && lb.found === 'Found in your work · 1' && lb.fcards === 'f-1:Set it up/Not a report' && lb.cap === '9' && !lb.old, JSON.stringify(lb));
|
|
395
|
-
ok('L1 the reports table is Report, Next and Status (what needs you first, redesign A); a draft says "Draft ready for" its date; a request says
|
|
395
|
+
ok('L1 the reports table is Report, Next and Status (what needs you first, redesign A); a draft says "Draft ready for" its date; a request says Working; a ready proposal waits in Needs you (redesign R)', lb.heads === 'Report|Next|Status' && /Draft ready for Oct 14/.test(lb.rows) && /Partner update\|First draft [^|]+\|Runs every other monday/i.test(lb.rows) && /(^|\|)Churn for finance(\||$)/.test(lb.needs) && lb.setups === 1 && lb.asks === 2, JSON.stringify([lb.rows, lb.needs]));
|
|
396
396
|
ok('L1 dashboards are cards; only the pinned one carries the pin', lb.cards === 'all*,pd-1,p:Growth,p:Reliability', lb.cards);
|
|
397
397
|
const rs = []; await q.route('**/api/report-setups/*', (r) => { rs.push([new URL(r.request().url()).pathname.replace('/api/report-setups/', ''), JSON.parse(r.request().postData() || '{}')]); r.fulfill({ contentType: 'application/json', body: '{"ok":true,"drafted":{"slot":"2026-10-23","path":"planning/reports/x/2026-10-23.md"}}' }); });
|
|
398
398
|
const lastRs = () => rs[rs.length - 1] || [null, {}];
|
package/workspace/changelog.json
CHANGED
|
@@ -1,4 +1,44 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "0.517.0",
|
|
4
|
+
"at": "2026-11-04T00:17:56.633Z",
|
|
5
|
+
"f": 4,
|
|
6
|
+
"prs": [
|
|
7
|
+
{
|
|
8
|
+
"n": 1207,
|
|
9
|
+
"t": "User guide in PMOS (option B) and guide pages brought up to date",
|
|
10
|
+
"s": "User guide in PMOS (option B) and guide pages brought up to date",
|
|
11
|
+
"k": "new"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"n": 1210,
|
|
15
|
+
"t": "The report engine: brief, read, find, write, one deck, no draft without a finding",
|
|
16
|
+
"s": "The report engine: brief, read, find, write, one deck, no draft without a finding",
|
|
17
|
+
"k": "new"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"v": "0.516.0",
|
|
23
|
+
"at": "2026-11-04T00:00:07.601Z",
|
|
24
|
+
"f": 4,
|
|
25
|
+
"prs": [
|
|
26
|
+
{
|
|
27
|
+
"n": 1209,
|
|
28
|
+
"t": "Runbook of what Claude does behind the scenes, in the guide",
|
|
29
|
+
"s": "Runbook of what Claude does behind the scenes, in the guide",
|
|
30
|
+
"k": "x",
|
|
31
|
+
"h": "See what Claude does behind the scenes",
|
|
32
|
+
"d": "Claude's background jobs were explained one page at a time, and nothing listed them all together. One guide page lists every job Claude runs by itself: when it runs, what it reads, where you see the result, how to stop it, and what Claude fixes without asking."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"n": 1208,
|
|
36
|
+
"t": "Reports that need you come first, one ✓ each (redesign R)",
|
|
37
|
+
"s": "Reports that need you come first, one ✓ each (redesign R)",
|
|
38
|
+
"k": "new"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
2
42
|
{
|
|
3
43
|
"v": "0.515.0",
|
|
4
44
|
"at": "2026-11-03T23:11:51.264Z",
|
|
@@ -84,8 +84,8 @@ const put = (root, rel, text) => { fs.mkdirSync(path.dirname(path.join(root, rel
|
|
|
84
84
|
const { ctx, pg, errors, posts } = await open();
|
|
85
85
|
await menu(pg);
|
|
86
86
|
const m = await pg.evaluate(() => ({ links: [...document.querySelectorAll('#czMenu a')].map((a) => a.textContent.trim()), tray: [...document.querySelectorAll('#czMenu .ev-tray button')].map((b) => b.getAttribute('aria-label').replace(/\..*$/, '')), rows: document.querySelectorAll('#czMenu .ev-mi, #czMenu [data-cz-more], #czMenu [data-cz-news], #czMenu [data-cz-sources], #czMenu [data-ev-theme]').length }));
|
|
87
|
-
// feedback batch 16 item 5 (canvas FmA1Menu): the three places, then Search and Settings as icons, and nothing else
|
|
88
|
-
ok('U1 the menu holds Home, Board, Intelligence, then Search and Settings as
|
|
87
|
+
// feedback batch 16 item 5 (canvas FmA1Menu): the three places, then Search and Settings as icons, and nothing else; guide-in-app adds Guide between them
|
|
88
|
+
ok('U1 the menu holds Home, Board, Intelligence, then Search, Guide and Settings as three icons, and no New for you, Sources, More or Theme', m.links.join() === 'Home,Board,Intelligence' && m.tray.join() === 'Search (⌘K),Guide,Settings' && m.rows === 0, JSON.stringify(m));
|
|
89
89
|
await snap(pg, 'menu-1440-light');
|
|
90
90
|
await pg.keyboard.press('Escape');
|
|
91
91
|
ok('U2 Escape closes the menu', await until(() => pg.isHidden('#czMenu')));
|
|
@@ -180,7 +180,7 @@ const put = (root, rel, text) => { fs.mkdirSync(path.dirname(path.join(root, rel
|
|
|
180
180
|
await pg.goto(`${BASE}/premium-insights.html?ws=${encodeURIComponent(ws)}`); await pg.waitForSelector('#czFab');
|
|
181
181
|
ok('D1 the choice is kept for the next page', await pg.evaluate(() => document.documentElement.dataset.theme === 'dark'));
|
|
182
182
|
await menu(pg);
|
|
183
|
-
ok('U1 no page has More in its menu', await pg.evaluate(() => !document.querySelector('#czMenu [data-cz-more]') && document.querySelectorAll('#czMenu .ev-tray button').length ===
|
|
183
|
+
ok('U1 no page has More in its menu', await pg.evaluate(() => !document.querySelector('#czMenu [data-cz-more]') && document.querySelectorAll('#czMenu .ev-tray button').length === 3));
|
|
184
184
|
await snap(pg, 'menu-1440-dark');
|
|
185
185
|
await pg.keyboard.press('Escape');
|
|
186
186
|
await pg.keyboard.press('Control+k'); await pg.waitForSelector('#evSearch:not([hidden])'); await pg.keyboard.type('billing');
|
|
@@ -62,6 +62,7 @@ const REPORT = '---\ntype: Report\ntitle: "Password login and sign-up"\n---\n\n#
|
|
|
62
62
|
|
|
63
63
|
function install(page, o = {}) {
|
|
64
64
|
const W = world(o.now || new Date());
|
|
65
|
+
const shift = o.now ? o.now.getTime() - Date.now() : 0; // a pinned clock (o.now): the stand-ins answer in the page's time
|
|
65
66
|
const S = { posts: [], gets: [], scene: o.scene || 'notes', W };
|
|
66
67
|
const json = (r, b, status = 200) => r.fulfill({ status, contentType: 'application/json', body: JSON.stringify(b) });
|
|
67
68
|
const body = (r) => { try { return JSON.parse(r.request().postData() || '{}'); } catch { return {}; } };
|
|
@@ -118,8 +119,8 @@ function install(page, o = {}) {
|
|
|
118
119
|
const u = new URL(r.request().url()), ev = u.searchParams.get('event'), note = u.searchParams.get('note');
|
|
119
120
|
const live = ev === 'ev-live' || note === 'n2';
|
|
120
121
|
/* a note with no calendar event has no event, brief or topics */
|
|
121
|
-
if (!ev && note && note !== 'n1' && note !== 'n2') return json(r, { ok: true, now_ms: Date.now(), event: null, note: { id: note, state: (S.store[note] || {}).state || 'ended' }, brief: null, material: [], topics: [], runs: [], captured: {}, tail: [] });
|
|
122
|
-
const base = { ok: true, now_ms: Date.now(), event: live ? { id: 'ev-live', title: 'Design crit', at: W.LIVE_NOTE.meeting.start, end: W.LIVE_NOTE.meeting.end, attendees: ['Ana', 'Wawan'] } : ev === 'ev-rail' ? { id: 'ev-rail', title: 'Rail review', at: iso(W.RAIL), attendees: ['Sam', 'Wawan'] } : { id: 'ev-sync', title: 'Viewer sync', at: W.NOTE.meeting.start, end: W.NOTE.meeting.end, attendees: ['Ana', 'Dita', 'Wawan'] },
|
|
122
|
+
if (!ev && note && note !== 'n1' && note !== 'n2') return json(r, { ok: true, now_ms: Date.now() + shift, event: null, note: { id: note, state: (S.store[note] || {}).state || 'ended' }, brief: null, material: [], topics: [], runs: [], captured: {}, tail: [] });
|
|
123
|
+
const base = { ok: true, now_ms: Date.now() + shift, event: live ? { id: 'ev-live', title: 'Design crit', at: W.LIVE_NOTE.meeting.start, end: W.LIVE_NOTE.meeting.end, attendees: ['Ana', 'Wawan'] } : ev === 'ev-rail' ? { id: 'ev-rail', title: 'Rail review', at: iso(W.RAIL), attendees: ['Sam', 'Wawan'] } : { id: 'ev-sync', title: 'Viewer sync', at: W.NOTE.meeting.start, end: W.NOTE.meeting.end, attendees: ['Ana', 'Dita', 'Wawan'] },
|
|
123
124
|
note: live ? { id: 'n2', state: 'recording' } : ev === 'ev-rail' ? null : { id: 'n1', state: 'ended' },
|
|
124
125
|
brief: { gist: ['Agree the rail before the Commit.'], purpose: 'Agree the rail before the Commit.', matters: [{ tag: 'Late', tone: 'bad', text: 'The SSO spike', meta: 'due 14 Oct' }, { tag: 'Changed', tone: '', text: 'The report panel design', meta: 'Oct 21' }], last: { id: 'n0', at: '2026-10-15T10:00:00Z', decisions: [{ text: 'a' }], actions: [{ text: 'b' }, { text: 'c' }] }, prep: 'Read the rail PRD.', initiative: { id: 'viewer', title: 'Viewer', ws: 'w1' } },
|
|
125
126
|
material: [{ kind: 'pmos-deck', title: 'Release deck', ref: 'decks/release.md', from: 'you' }, { kind: 'pmos-doc', title: 'Rail PRD', ref: 'planning/prd/rail.md', from: 'you' }, { kind: 'link', title: 'Figma: report panel', url: 'https://x.example/f', topic: 'The report panel' }],
|
|
@@ -189,6 +190,7 @@ async function open(browser, base, url, o = {}) {
|
|
|
189
190
|
const ctx = await browser.newContext({ viewport: { width: o.w || 1280, height: o.h || 900 }, acceptDownloads: true });
|
|
190
191
|
const page = await ctx.newPage(), errors = [];
|
|
191
192
|
page.on('pageerror', (e) => errors.push(String((e && e.message) || e)));
|
|
193
|
+
if (o.now) await page.clock.setSystemTime(o.now); // the page's Date starts at o.now and runs on; timers are real
|
|
192
194
|
const S = await install(page, o);
|
|
193
195
|
await page.addInitScript(RECORDER);
|
|
194
196
|
if (o.init) await page.addInitScript(o.init);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Guide
|
|
3
|
+
title: "What Claude does behind the scenes"
|
|
4
|
+
description: "The runbook of the workspace agent: each job Claude runs by itself, when it runs, what it reads, where its result shows, how to stop it, what it fixes by itself, the rules every job follows, and how to see what ran."
|
|
5
|
+
timestamp: 2026-11-03
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# What Claude does behind the scenes
|
|
9
|
+
|
|
10
|
+
Claude works in the background while the workspace runs. It reads your records and the tools you connected, it drafts, and it checks. It does not decide for you. A result waits for your ✓, most often under the blue ✦ of an initiative or as one ✦ in Home's chat. A background job never sends, posts, pushes or merges anything.
|
|
11
|
+
|
|
12
|
+
This page lists every job, so you know what runs and why. Each row links to the page with the full detail.
|
|
13
|
+
|
|
14
|
+
## The rules every job follows
|
|
15
|
+
|
|
16
|
+
- **Propose-only.** A background job files proposals. Nothing lands on an initiative, a task or a metric until you press ✓. ✕ drops a proposal, and Undo brings back what was there.
|
|
17
|
+
- **Every claim has a source.** An AI job files through one shared guard. The guard checks that each quote is really at the file and line it cites. A claim with no source that checks out is dropped. A proposal with a key that would write, apply, send or run a command is dropped.
|
|
18
|
+
- **Few at a time.** A run shows at most 3 proposals. In a quiet week it shows nothing.
|
|
19
|
+
- **Tested first.** A new version of a job shows nothing until its replay passes: its own known cases, and the guard's own cases (a made-up quote, a missing source, a path outside the repository, a write key). Each of those must be dropped.
|
|
20
|
+
- **Your login, your connections.** A job runs as a background Claude session with your own login, model, profile and connectors. The workspace holds no password or token. `PMOS_HEADLESS=off` sends every job back to a terminal pane.
|
|
21
|
+
- **Your hours.** Scheduled jobs run inside your working hours and never inside your quiet hours.
|
|
22
|
+
- **A spending limit.** Claude's checks spend at most the monthly credit you set in Settings › Claude's checks ($5, $10, $20 or $50). At the limit Claude pauses. It never spends beyond the limit.
|
|
23
|
+
- **Every run is logged.** Each job writes its own ledger in the runtime folder on this computer. Only you see it, and it never goes into a repository.
|
|
24
|
+
|
|
25
|
+
## The jobs
|
|
26
|
+
|
|
27
|
+
| Job | When it runs | What it reads | Where you see it | How to stop it |
|
|
28
|
+
|---|---|---|---|---|
|
|
29
|
+
| [Initiative Driver](initiative-driver.md) | An initiative is created, moved or sent back. The unblock sweep runs every 30 minutes in working hours. At most 3 runs at once. | The initiative record, its tasks and its Jira tickets | The Agent strip of the initiative, and Needs you | Board settings › Agent: Off. `PMOS_DRIVER=off` |
|
|
30
|
+
| [Found elsewhere](claude-proposes.md) | You add an initiative | Drive, Docs, Sheets, Slides, Jira, the calendar, meeting notes, Gmail, Slack and Confluence | The initiative's ✦ | `PMOS_PROPOSE=off` |
|
|
31
|
+
| [New dates, done and tidy names](claude-proposes.md) | Each morning, and when a date passes | The tasks of the initiative, and the evidence that work happened | The initiative's ✦ | `PMOS_PROPOSE=off` |
|
|
32
|
+
| [Grill](claude-proposes.md) | Before an initiative leaves a stage, when a forecast turns at risk, when scope or dates move a lot, and once a month on running work with late work. Also when you write "grill this" in the initiative's chat. | The initiative, your stored research, your meeting notes and the decisions that stand | "Claude grilled it" under the initiative's ✦ | Settings › Claude's checks: Off. `PMOS_GRILL=off` |
|
|
33
|
+
| [You decided this before](ask-the-past.md) | You add an initiative that repeats an earlier decision | `DECISIONS.md`, the decision records, the PM journal, `planning/out-of-scope/` and the initiative records | The initiative's ✦ | `pmos ai off past-repeat` |
|
|
34
|
+
| [Expected outcomes](outcomes.md) | Once a day. At most 3 drafts a day for each product. | The PRD's success criteria, or the anchored key result | "Expected outcome" under the initiative's ✦. Today when a check is due. | `pmos ai off outcomes`. `PMOS_OUTCOMES=off` |
|
|
35
|
+
| [Metric drafts](metric-drafts.md) | A product with no North Star, the first 14 days of a quarter, a program with no goal, and an initiative that gets a PRD | The last 8 weeks of real readings | The page of that product, program or initiative | `PMOS_METRIC_DRAFT=off` |
|
|
36
|
+
| [Horizon scan](horizon-scan.md) | Daily by default, at most once a day. Scan now: at most 3 a day. | The public web for your kept watch list, and your repository | Report documents and proposals you approve | Cadence: Off. `PMOS_SCAN=off` |
|
|
37
|
+
| [What you might have missed](what-you-missed.md) | Each Monday, for the week before. It uses no model. | Records only: tasks, dates, initiatives and Jira status | One ✦ in Home's chat, at most 3 items | `pmos ai off drift`. `PMOS_DRIFT=off` |
|
|
38
|
+
| [Your impact](your-impact.md) | Claude reads once a day. Home shows the week after it ends. | Slack, mail, Jira, your meeting notes, your documents and your key results | Adler's sprout on Home, and your impact log | Settings › General › Your impact. `PMOS_IMPACT=off` |
|
|
39
|
+
| [Morning brief and day check](proactive-engine.md) | The morning brief at 06:45, once you schedule it. The day check every 60 minutes by default (30, 60 or off). | Calendar, Wispr Flow, Slack, Jira and Confluence are on by default. Mail, GitHub, Drive, Figma and websites are off by default. Mail: subjects and senders only. | Today | Each source is a setting. `pmos proactive settings` |
|
|
40
|
+
| [Day tasks](proactive-engine.md) | You press Prepare my day. At most 5 sessions at once. | The sources of the brief, read-only | Today: a draft waits for Approve or Revise | Do not press Prepare my day |
|
|
41
|
+
| [Next prompt and Sharper](next-prompt.md) | After Claude replies, and when you stop typing a rough prompt | The reply and your message | Cards above the chat box. Nothing is sent. | Settings › Claude. `pmos ai off next-prompt`, `pmos ai off sharpen-prompt` |
|
|
42
|
+
| [Rehearse a plan](rehearse.md) | You ask Claude to move a date or cut a task or an initiative | Task links, initiative records, goals and program charters | Your session, before Claude makes the change | `pmos ai off rehearse` |
|
|
43
|
+
| [Data refresh](data-freshness.md) | In working hours: the calendar every 30 minutes, and Jira, My work and your tools every hour. Tracker items on Friday 15:30. | Each tool with your own connection, read-only | Each page shows how old its data is | Settings › Data refresh |
|
|
44
|
+
|
|
45
|
+
Ask about the past runs only when you ask a question in an initiative's chat. It answers from the records, with the file and line of each claim, and says **No record found** when no record answers.
|
|
46
|
+
|
|
47
|
+
## What Claude fixes by itself
|
|
48
|
+
|
|
49
|
+
Some problems are safe to fix with no question. Claude fixes these by itself and tells you only when it cannot.
|
|
50
|
+
|
|
51
|
+
- **A product folder on the wrong branch.** A document repository whose folder is not on its default branch looks empty. The workspace puts it back: it saves the records, checks that the merge has no conflict, merges, and pushes with no force. It never deletes or rewrites a branch. It never touches a code repository. When it cannot do this safely, Today shows one "Needs repair" card in plain words, with **Ask Claude to sort it out**. It tries again after 30 minutes, or after 10 minutes when it only waited for the network. `PMOS_AUTO_REPAIR=0` stops it.
|
|
52
|
+
- **Folders of finished work.** About every 6 hours the workspace removes a linked worktree only when its branch is merged, it holds no unsaved file, nothing used it for 14 days, and no session uses it. The branch is kept. `PMOS_AUTO_CLEAN=0` stops it.
|
|
53
|
+
- **A report source that does not answer.** A scheduled report waits up to 4 hours for a source that failed its check. Today shows "Check <source> for <report>" with **Check again**. Then the report is drafted without that source, and it says so. It never guesses a number.
|
|
54
|
+
- **A failed run.** A metric draft that failed tries again the next day. A Driver run that failed or timed out writes its reason in the ledger.
|
|
55
|
+
- **A source that was not reached.** It is shown as not reached, never as read. Today says which sources were not read.
|
|
56
|
+
|
|
57
|
+
Sync by itself is on by default. `PMOS_AUTO_SYNC=0` stops the sync, the repair and the clean-up.
|
|
58
|
+
|
|
59
|
+
## What a background job never does
|
|
60
|
+
|
|
61
|
+
- It sends, posts, replies, pushes and merges nothing. A message to a person is a draft that you send. A Jira change is a drafted comment in your outbox.
|
|
62
|
+
- It does not create an initiative. The Horizon scan proposes one, and you approve it.
|
|
63
|
+
- It does not record a verdict on an outcome. The verdict is always yours.
|
|
64
|
+
|
|
65
|
+
When you ask an agent session to do a piece of work, it can finish it, including acts that were yours alone. Each line it writes names the agent, so you see who did it. See [PM-only acts](pm-only-acts.md).
|
|
66
|
+
|
|
67
|
+
## See what ran, and turn it off
|
|
68
|
+
|
|
69
|
+
- `pmos ai status`: whether each AI job is on, whether its replay passed, and what its last run filed.
|
|
70
|
+
- `pmos ai log [<job>]`: the last audit lines. Each dropped proposal shows why.
|
|
71
|
+
- `pmos ai off [<job>]` and `pmos ai on [<job>]`: turn every AI job, or one job, off or on. `PMOS_AI=off` in the environment wins over the setting.
|
|
72
|
+
|
|
73
|
+
The AI jobs are `past-repeat`, `decision-memory`, `outcomes`, `drift`, `rehearse`, `next-prompt` and `sharpen-prompt`. A background run cannot change the switch.
|
package/workspace/guide/board.md
CHANGED
|
@@ -1,75 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: Guide
|
|
3
|
-
title: "
|
|
4
|
-
description: "How
|
|
5
|
-
timestamp: 2026-11-
|
|
3
|
+
title: "pmos board: the items of every initiative"
|
|
4
|
+
description: "How pmos board prints the items of every initiative in four columns from a terminal, and where the workspace shows initiatives and their tasks."
|
|
5
|
+
timestamp: 2026-11-03
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
#
|
|
8
|
+
# pmos board: the items of every initiative
|
|
9
9
|
|
|
10
|
-
The Board
|
|
10
|
+
The **Board** place of the workspace shows initiatives, not items: every initiative of the products you pick, by stage, with programs, a timeline and a list. [Programs on the Board](programs.md) explains it. An initiative's tasks show under it in Home's list and in the initiative's page in the Viewer.
|
|
11
11
|
|
|
12
|
-
The
|
|
13
|
-
|
|
14
|
-
A document initiative has no items, so it has no card and no place in the filter.
|
|
15
|
-
|
|
16
|
-
## Open the Board
|
|
17
|
-
|
|
18
|
-
Press **Board** in the navigation, or press `g` then `b`. In the older layout, choose Board in the command palette. The Board opens in a tab.
|
|
19
|
-
|
|
20
|
-
## Filters
|
|
21
|
-
|
|
22
|
-
Three filters decide which cards show. Press a button at the top, or choose an initiative from the list.
|
|
23
|
-
|
|
24
|
-
- **Active** is the default. It shows an item that changed in the last days, an open item of an initiative that is ranked on the Roadmap, and every item that is yours. The number of days is `stall_days` in `planning/plan-rules.json`.
|
|
25
|
-
- **Mine** shows only the items that you own.
|
|
26
|
-
- **An initiative.** Choose one from the list to see all its items. Choose **All initiatives** to go back to Active.
|
|
27
|
-
|
|
28
|
-
Done shows the last 14 days under every filter, however long ago the item last changed. An older Done item is counted in the column ("3 older in the Tree") and stays in the Tree of its initiative.
|
|
29
|
-
|
|
30
|
-
## Add an item
|
|
31
|
-
|
|
32
|
-
Press **Add item**, the one main button of the Board. Type a title, choose the initiative and the stage, and press **Add** or Enter. The item goes into the ledger of that initiative, the same way as in the Breakdown.
|
|
33
|
-
|
|
34
|
-
## Move a card
|
|
35
|
-
|
|
36
|
-
- **On a wide screen,** drag a card to another column. A drop on Done is held for 8 seconds, so you can press **Undo**.
|
|
37
|
-
- **On a phone,** press the card to open its sheet and press a state button. A card moves in 2 taps. From another column it takes 3: first press the column name, then the card, then the state.
|
|
38
|
-
- **From the menu.** Press the three dots on a card, then choose Move to a state. Every card shows its three dots.
|
|
39
|
-
|
|
40
|
-
When you move a card that an agent owns, the card reads "moved by you". The agent's own next move can change it again.
|
|
41
|
-
|
|
42
|
-
A card that reads "Done · your call · not merged" is Done because you said so. The work in the repository is not merged yet.
|
|
43
|
-
|
|
44
|
-
## Release
|
|
45
|
-
|
|
46
|
-
When all the work items of a batch passed their checks, the Board shows a **Release** card above the columns. One press on **Release** grants the whole batch. It is one grant for the batch, and the grant names the initiative and the batch. The factory opens pull requests and never merges them.
|
|
47
|
-
|
|
48
|
-
Only you can press Release. An agent cannot. When the grant writer of the workspace is not available, the button is disabled and the card says "Release arrives in Run 2."
|
|
49
|
-
|
|
50
|
-
The same card also shows in Today when a batch is ready.
|
|
51
|
-
|
|
52
|
-
## Today
|
|
53
|
-
|
|
54
|
-
Today shows three things from the Board:
|
|
55
|
-
|
|
56
|
-
- an item in Review that waits for you;
|
|
57
|
-
- a batch that is ready for Release;
|
|
58
|
-
- an item that an agent marked Done with no evidence. Open it and add evidence, such as `commit:<sha>` or `pr:<number>`.
|
|
59
|
-
|
|
60
|
-
## Signals
|
|
61
|
-
|
|
62
|
-
| signal | meaning |
|
|
63
|
-
|---|---|
|
|
64
|
-
| Blocked | the item has a reason that it cannot go on |
|
|
65
|
-
| no evidence | an agent marked the item Done and gave no evidence |
|
|
66
|
-
| late | the due date passed and the item is not Done |
|
|
67
|
-
| moved by you | you moved a card that an agent owns |
|
|
68
|
-
| Proposed | an item an agent added before D98 that was never kept (since D98 an agent's item is live at once) |
|
|
12
|
+
The command below prints the items themselves, from a terminal.
|
|
69
13
|
|
|
70
14
|
## From a terminal
|
|
71
15
|
|
|
72
|
-
`pmos board` prints the
|
|
16
|
+
`pmos board` prints the items of every initiative as columns: Todo, Doing, Review and Done. It reads the repository, so the workspace server does not need to run.
|
|
73
17
|
|
|
74
18
|
```
|
|
75
19
|
pmos board the Active filter
|