create-pmos 0.219.0 → 0.220.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 +1 -1
- 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/c3-phone-test.js +1 -0
- package/workspace/guide/phone-companion.md +2 -2
- package/workspace/lib/routes-phone-day.js +4 -2
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/c3-demo-phone.js +1 -1
- package/workspace/public/pm/c3-phone-detail.js +4 -2
- package/workspace/public/pm/c3-phone.css +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.220.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": {
|
package/payload/KIT-VERSION
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Eval calibration log"
|
|
4
4
|
description: "Append-only record of every PM override of an evaluator verdict."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T05:03:17Z"}
|
|
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-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T05:03:17Z"}
|
|
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-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T05:03:17Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -236,6 +236,7 @@ const writes = (p) => (window.__c3demoWrites || []).filter((w) => w.path === p |
|
|
|
236
236
|
ok('day: working hours show what the agent finished for you', await waitFor(page, () => !!document.querySelector('[data-c3ph-moment] [data-c3ph-fin="t-0000000000a1"]'), null, 8000));
|
|
237
237
|
await page.click('[data-c3ph-fin-open="t-0000000000a1"]');
|
|
238
238
|
ok('day: Read it opens the draft, and approving it waits for the desk', await waitFor(page, () => { const d = document.querySelector('[data-c3ph-draft="t-0000000000a1"]'); return !!d && /31 Oct/.test(d.textContent) && /on your computer/.test(d.textContent); }, null, 5000));
|
|
239
|
+
ok('day: the draft reads as a document, not raw markdown (headings, bold, a list)', await page.evaluate(() => { const m = document.querySelector('[data-c3ph-draft="t-0000000000a1"] .ds-md'); return !!m && !!m.querySelector('h1') && !!m.querySelector('h2') && !!m.querySelector('strong') && m.querySelectorAll('li').length === 2 && !/(^|\s)(#|\*\*)/.test(m.textContent); }));
|
|
239
240
|
await page.close();
|
|
240
241
|
page = await open(pctx, '/c3.html?demo=1&at=17:40');
|
|
241
242
|
ok('day: 17:40 is the evening recap, with the evening icon', (await moment(page)) === 'recap' && await page.evaluate(() => document.querySelector('[data-c3ph-part]')?.dataset.c3phPart === 'evening'), await moment(page));
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Guide
|
|
3
3
|
title: "Guide: the phone companion"
|
|
4
4
|
description: "At phone width the console shows a companion: one moment of your day, your items one at a time, Tell PMOS and Record."
|
|
5
|
-
timestamp: 2026-10-
|
|
5
|
+
timestamp: 2026-10-14
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Guide: the phone companion
|
|
@@ -20,7 +20,7 @@ The top card shows where you are in your day and why it is useful now. PMOS choo
|
|
|
20
20
|
| In the meeting | A meeting is in progress | **Record this meeting?** with **Record** and **Not this one**. Recording opens focus (see below). |
|
|
21
21
|
| Just ended | A meeting ended less than 20 minutes ago | **What came out of it?** If you recorded the meeting, the card shows the summary, the decisions, the actions and the open questions from its notes, the same notes as on the Notes page. While PMOS writes the notes, the card says so. If you did not record it, **Tell PMOS** puts the meeting name in the bar so you can type the result. |
|
|
22
22
|
| Free time | 15 minutes or more before the next meeting | The items that fit in the time: overdue items first, then items due today, at most two. Each has **Done** and **Later today**. Under them, what the agent finished for you. |
|
|
23
|
-
| Finished for you | After noon, before 17:00, with no meeting near | The drafts that the agent finished today, newest first. **Read it** shows the draft. Approve a draft, or send it back with a note, on your computer: nothing is sent from the phone. Under them, the items that fit. |
|
|
23
|
+
| Finished for you | After noon, before 17:00, with no meeting near | The drafts that the agent finished today, newest first. **Read it** shows the draft as a document, with its headings, lists and tables, the same as on your computer. Approve a draft, or send it back with a note, on your computer: nothing is sent from the phone. Under them, the items that fit. |
|
|
24
24
|
| Evening recap | From 17:00 | How today went: the meetings, the decisions in their notes, the items you marked done and the agent's drafts. Then what moved, what is still open, and one thing for tonight with **Done** and **Tomorrow**. |
|
|
25
25
|
| End of day | From 20:00, and before 05:00 | Today in one line, the meetings of the next working day (tap one to see its brief), and how many items carry over |
|
|
26
26
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* READ ONLY, and built only from what PMOS already holds. Nothing is invented. The companion reads it for three moments:
|
|
7
7
|
* finished working hours, "Finished for you": the agent's tasks of today's day run (goals/<date>.run.json, lib/day-run.js) that have a
|
|
8
|
-
* draft. { id, title, summary, body, at, status, link, source }; status 'review' (waits for the PM's approval at the desk),
|
|
8
|
+
* draft. { id, title, summary, body, at, status, link, source }; body keeps its lines (markdown, at most 8000 characters); status 'review' (waits for the PM's approval at the desk),
|
|
9
9
|
* 'done' (an auto task) or 'sent'. Newest first, at most 5.
|
|
10
10
|
* recap evening: how the day went. meetings = today's meetings that have ended; decided = the decisions in the final notes of today's
|
|
11
11
|
* meetings; done = the PM's own items marked done today; finished = the agent's drafts of today. moved = at most 5 rows of
|
|
@@ -21,6 +21,8 @@ const { todayAgenda, notesAdapter } = require('./routes-brief-page.js');
|
|
|
21
21
|
const pad = (n) => String(n).padStart(2, '0');
|
|
22
22
|
const localDate = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
23
23
|
const clip = (s, n) => { const t = String(s || '').replace(/\s+/g, ' ').trim(); return t.length > n ? t.slice(0, n - 1) + '…' : t; };
|
|
24
|
+
// the draft's text keeps its lines: the companion draws it as a document (markdown, c3-md.js)
|
|
25
|
+
const clipDoc = (s, n) => { const t = String(s || '').replace(/\r\n?/g, '\n').replace(/\n{3,}/g, '\n\n').trim(); return t.length > n ? t.slice(0, n - 1) + '…' : t; };
|
|
24
26
|
const WD = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
25
27
|
const MO = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
26
28
|
const FINISHED = ['review', 'done', 'sent'];
|
|
@@ -36,7 +38,7 @@ function nextWorkday(now) {
|
|
|
36
38
|
function finishedOf(run) {
|
|
37
39
|
const tasks = run && Array.isArray(run.tasks) ? run.tasks : [];
|
|
38
40
|
return tasks.filter((t) => t && FINISHED.includes(t.status) && t.draft && t.draft.summary)
|
|
39
|
-
.map((t) => ({ id: t.id, title: clip(t.title, 200), summary: clip(t.draft.summary, 300), body:
|
|
41
|
+
.map((t) => ({ id: t.id, title: clip(t.title, 200), summary: clip(t.draft.summary, 300), body: clipDoc(t.draft.body, 8000), at: t.draft.at || null, status: t.status, link: t.draft.link || t.link || null, source: t.source || null }))
|
|
40
42
|
.sort((a, b) => String(b.at || '').localeCompare(String(a.at || '')));
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.220.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pmos-workspace",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.220.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED
|
@@ -35,7 +35,7 @@ const at = (d, hh, mm) => new Date(2026, 9, d, hh, mm).toISOString();
|
|
|
35
35
|
export const demoDay = () => ({
|
|
36
36
|
ok: true, date: '2026-10-08',
|
|
37
37
|
finished: [
|
|
38
|
-
{ id: 't-0000000000a1', title: 'Reply to Priya on the Checkout v2 date', summary: 'A reply that moves v2 to 31 Oct and keeps beta on 30 Oct, with the reason in one line.', body: '
|
|
38
|
+
{ id: 't-0000000000a1', title: 'Reply to Priya on the Checkout v2 date', summary: 'A reply that moves v2 to 31 Oct and keeps beta on 30 Oct, with the reason in one line.', body: '# Reply to Priya\n\nHi Priya,\n\n**Checkout v2 moves to 31 Oct**: the sandbox keys arrive two days late.\n\n## What stays\n\n- Beta stays on 30 Oct for the two partners already set up.\n- The `checkout_v2` flag stays off until then.', at: at(8, 12, 52), status: 'review', link: null, source: 'my-work' },
|
|
39
39
|
{ id: 't-0000000000a2', title: 'Weekly status for leadership', summary: 'Green on Checkout v2 with the new date; amber on Returns, where the interview slipped a week.', body: '', at: at(8, 12, 40), status: 'done', link: null, source: 'brief' },
|
|
40
40
|
],
|
|
41
41
|
recap: { meetings: 5, decided: 2, done: 1, finished: 2,
|
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
* Done and Later today when the row is the PM's own Work item. opts: { onDone(r), onLater(r) }
|
|
8
8
|
* openAll(rows, opts) every row that waits, as a list; a press opens that row (openNeed). opts as openNeed.
|
|
9
9
|
* openDraft(t) a draft the agent finished today (GET /api/phone-day finished): what it is, its summary, its text and its
|
|
10
|
-
* link.
|
|
10
|
+
* link. The text is drawn as a document (c3-md.js, as the desk's Work sheet and the document sheet draw it):
|
|
11
|
+
* headings, lists, tables, bold. Approving or revising it waits for the desk, where the whole draft and its sources are.
|
|
11
12
|
* Nothing here writes: the buttons call back into c3-phone.js, which owns the writes and their Undo. */
|
|
12
13
|
import { el } from './dom.js';
|
|
13
14
|
import { button, row } from './primitives.js';
|
|
14
15
|
import { pmGet } from './http.js';
|
|
15
16
|
import { c3ic } from './pm-work-view.js';
|
|
16
17
|
import { openSheet, closeSheet } from './c3-sheet.js';
|
|
18
|
+
import { parseMd, toDom } from './c3-md.js';
|
|
17
19
|
|
|
18
20
|
const p2 = (n) => String(n).padStart(2, '0');
|
|
19
21
|
const hm = (iso) => { const d = new Date(iso); return p2(d.getHours()) + ':' + p2(d.getMinutes()); };
|
|
@@ -88,7 +90,7 @@ export function openDraft(t) {
|
|
|
88
90
|
const body = el('div', { class: 'c3ph-sheetbody', 'data-c3ph-draft': t.id },
|
|
89
91
|
el('span', { class: 'c3ph-step' }, (t.status === 'review' ? 'Waits for you' : t.status === 'sent' ? 'Sent' : 'Finished').toUpperCase() + (t.at ? ' · ' + hm(t.at) : '')),
|
|
90
92
|
line(t.summary),
|
|
91
|
-
|
|
93
|
+
t.body ? el('div', { class: 'ds-md wk-agent-md c3ph-md' }, toDom(parseMd(String(t.body)), document)) : null,
|
|
92
94
|
t.link ? el('div', { class: 'chips2' }, link(t.link, 'Open the source')) : null,
|
|
93
95
|
line(t.status === 'review' ? 'Approve it, or send it back with a note, on your computer. Nothing is sent from the phone.' : 'Nothing more is needed from you.'));
|
|
94
96
|
return openSheet({ title: t.title, icon: 'file-text', body });
|
|
@@ -59,3 +59,8 @@
|
|
|
59
59
|
.c3 .c3ph-stats b{font-size:20px;font-variant-numeric:tabular-nums}
|
|
60
60
|
.c3 .c3ph-stats span{font-size:11px;color:var(--muted-foreground);line-height:1.25}
|
|
61
61
|
.c3 .c3ph-pts{display:grid;gap:2px}
|
|
62
|
+
/* the agent's draft in its sheet, drawn as a document (c3-md.js): its headings, lists and tables, at the phone's reading size */
|
|
63
|
+
.c3 .c3ph-md{max-width:none;padding-top:8px;border-top:1px solid var(--border);font-size:var(--fs-3);line-height:1.55}
|
|
64
|
+
.c3 .c3ph-md h1,.c3 .c3ph-md h2{font-size:var(--fs-4);margin:12px 0 4px}
|
|
65
|
+
.c3 .c3ph-md p{margin:6px 0}
|
|
66
|
+
.c3 .c3ph-md .tw{max-width:100%}
|