create-pmos 0.201.0 → 0.202.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-foundation-test.js +3 -2
- package/workspace/c3-phone-test.js +4 -2
- package/workspace/guide/phone-companion.md +4 -0
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/c3.html +2 -2
- package/workspace/public/pm/c3-boot.js +10 -0
- package/workspace/public/pm/c3-phone-boot.js +47 -0
- package/workspace/public/pm/c3-phone.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.202.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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:45:43Z"}
|
|
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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:45:43Z"}
|
|
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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:45:43Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -153,8 +153,9 @@ process.on('unhandledRejection', (e) => { console.error(e); finish(1); });
|
|
|
153
153
|
ok('R2 where canvas is unavailable the page still draws and raises no error', N.up && N.errors.length === 0 && await N.page.evaluate(() => document.querySelectorAll('canvas.c3amb').length === 0), N.errors.join(' | '));
|
|
154
154
|
await N.ctx.close();
|
|
155
155
|
|
|
156
|
-
/* phone width: no horizontal scroll
|
|
157
|
-
|
|
156
|
+
/* phone width: no horizontal scroll. A phone shows the companion (c3-phone-test.js); this holds the desktop layout at that width
|
|
157
|
+
* (lib/c3-full-console.js). */
|
|
158
|
+
const M = await open({ viewport: { width: 400, height: 900 } }, null, () => { try { localStorage.setItem('pmos.c3.testDesk', 'desk'); } catch { /* no storage */ } });
|
|
158
159
|
ok('0 at 400 wide the page does not scroll sideways', M.up && await M.page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1), 'scrollWidth');
|
|
159
160
|
ok('0 no page error (400 wide)', M.errors.length === 0, M.errors.join(' | '));
|
|
160
161
|
await M.ctx.close();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
|
-
/* c3-phone-test.js — the phone companion (initiative c3-phone-companion; PRD done-criteria 1 to 6 and 8): c3-phone.js, its sheets c3-phone-detail.js and its demo notes c3-demo-phone.js
|
|
3
|
+
/* c3-phone-test.js — the phone companion (initiative c3-phone-companion; PRD done-criteria 1 to 6 and 8): c3-phone.js, its sheets c3-phone-detail.js and its demo notes c3-demo-phone.js;
|
|
4
|
+
* c3-boot.js and c3-phone-boot.js, which load the companion alone at phone width.
|
|
4
5
|
* A real server and a real Chromium drive /c3.html in demo mode (clock frozen at Thu 8 Oct 2026 08:12; ?at=HH:MM moves the companion's clock).
|
|
5
6
|
*
|
|
6
|
-
* phone at 400 wide the companion shows and the desktop grid does not
|
|
7
|
+
* phone at 400 wide the companion shows and the desktop grid does not; only the companion's modules load
|
|
7
8
|
* moments 08:12 morning; 10:10 before Checkout sync; 10:45 in the meeting with the Record offer
|
|
8
9
|
* done Done on the waiting item records a write to /api/pm-items/done
|
|
9
10
|
* tell text sent from the ask bar records a capture and clears the bar
|
|
@@ -73,6 +74,7 @@ const writes = (p) => (window.__c3demoWrites || []).filter((w) => w.path === p |
|
|
|
73
74
|
let page = await open(pctx, '/c3.html?demo=1');
|
|
74
75
|
ok('phone: the companion shows at 400 wide', await page.evaluate(shown, '[data-c3ph]'));
|
|
75
76
|
ok('phone: the desktop grid is hidden', !(await page.evaluate(shown, '.c3grid')));
|
|
77
|
+
ok('phone: only the companion loads, not the desktop console', await page.evaluate(() => { const js = performance.getEntriesByType('resource').map((r) => r.name); return js.some((u) => /c3-phone-boot\.js/.test(u)) && !js.some((u) => /c3-shell\.js|calendar-views\.js|c3-initiatives\.js/.test(u)); }));
|
|
76
78
|
ok('phone: no sideways scroll', await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1));
|
|
77
79
|
ok('moments: 08:12 is morning', (await moment(page)) === 'morning', await moment(page));
|
|
78
80
|
ok('phone: the ask bar and the red Record button are in the bottom bar', await page.evaluate(() => !!document.querySelector('[data-c3ph-foot] [data-c3ph-input]') && !!document.querySelector('[data-c3ph-foot] [data-c3ph-record]')));
|
|
@@ -65,6 +65,10 @@ A phone always shows the companion. There is no way to the desktop pages on a ph
|
|
|
65
65
|
|
|
66
66
|
The number of things that wait on you, at the top right, opens the list of all of them.
|
|
67
67
|
|
|
68
|
+
## Loading
|
|
69
|
+
|
|
70
|
+
On a phone, PMOS loads only the companion, not the pages of the computer. This makes the first load faster on a phone connection. If you turn the screen so that it is wider than a phone, the page loads again and shows the pages of the computer.
|
|
71
|
+
|
|
68
72
|
## Limits
|
|
69
73
|
|
|
70
74
|
- No notification on the lock screen, and no spoken brief.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.202.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.202.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED
package/workspace/public/c3.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
|
16
16
|
<link rel="apple-touch-icon" href="/icons/apple-touch-icon.png" />
|
|
17
17
|
<!-- The console3 shell (header, tabs, three columns, dock), served as the default page at / (and still at /c3.html). It
|
|
18
|
-
composes the real views from pm/; the older shell (index.html) is served at /classic.html. Tokens and fonts are shared, so light and dark both resolve. pm/c3-shell.js sets the
|
|
18
|
+
composes the real views from pm/; the older shell (index.html) is served at /classic.html. Tokens and fonts are shared, so light and dark both resolve. pm/c3-boot.js loads the phone companion alone at phone width (c3-phone-boot.js) and the desktop console (pm/c3-shell.js) otherwise; the shell sets the
|
|
19
19
|
theme attribute (default light, like the mockup). The nonce meta is filled by the server the way it is for /, so a press
|
|
20
20
|
from a view (Add, Accept, Allow) carries it. -->
|
|
21
21
|
<link rel="preload" href="/vendor/ibm-plex-mono-400.woff2" as="font" type="font/woff2" crossorigin />
|
|
@@ -30,6 +30,6 @@
|
|
|
30
30
|
<body>
|
|
31
31
|
<div id="c3-root" class="c3 c3pg" data-pm-theme="light"></div>
|
|
32
32
|
<noscript>This page needs JavaScript.</noscript>
|
|
33
|
-
<script type="module" src="/pm/c3-
|
|
33
|
+
<script type="module" src="/pm/c3-boot.js"></script>
|
|
34
34
|
</body>
|
|
35
35
|
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* pm/c3-boot.js — the first script of /c3.html: it picks which page to load (initiative c3-phone-companion).
|
|
2
|
+
* At phone width the companion loads alone (c3-phone-boot.js): about 30 modules instead of the desktop console's 100 and its
|
|
3
|
+
* reads of every tab. The desktop console (c3-shell.js) loads only on a wider screen. Turning a phone to a wide screen reloads
|
|
4
|
+
* the page, so the desktop console starts from the beginning. pmos.c3.testDesk is for the browser suites that test the
|
|
5
|
+
* desktop layout at phone width (lib/c3-full-console.js), as in c3-phone.js phoneWanted. */
|
|
6
|
+
const narrow = typeof matchMedia === 'function' && matchMedia('(max-width:640px)').matches;
|
|
7
|
+
let desk = false;
|
|
8
|
+
try { desk = localStorage.getItem('pmos.c3.testDesk') === 'desk'; } catch { /* no storage */ }
|
|
9
|
+
if (narrow && !desk) import('./c3-phone-boot.js');
|
|
10
|
+
else import('./c3-shell.js');
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* pm/c3-phone-boot.js — the phone companion on its own (initiative c3-phone-companion). c3-boot.js loads it at phone width
|
|
2
|
+
* instead of the desktop console, so a phone reads only what the companion shows. It does what c3-shell.js boot() does for
|
|
3
|
+
* the companion: the demo, the workspace, the theme, then mountPhone. A wider screen reloads into the desktop console. */
|
|
4
|
+
import { pmGet } from './http.js';
|
|
5
|
+
import { ensureC3Css, c3Phone } from './pm-work-view.js';
|
|
6
|
+
import { mountPhone } from './c3-phone.js';
|
|
7
|
+
|
|
8
|
+
const q = new URLSearchParams(location.search);
|
|
9
|
+
const DEMO = q.get('demo') === '1';
|
|
10
|
+
const store = { get(k) { try { return localStorage.getItem(k); } catch { return null; } } };
|
|
11
|
+
|
|
12
|
+
/* A GET to /api/ with no ws is sent for this page's workspace, as c3-shell.js withWs() does. */
|
|
13
|
+
function withWs(ws) {
|
|
14
|
+
const f = window.fetch.bind(window);
|
|
15
|
+
window.fetch = (input, init) => {
|
|
16
|
+
try {
|
|
17
|
+
if (typeof input === 'string' && ws && input.startsWith('/api/') && !/[?&]ws=/.test(input) && (!init || !init.method || init.method === 'GET')) input += (input.includes('?') ? '&' : '?') + 'ws=' + encodeURIComponent(ws);
|
|
18
|
+
} catch { /* leave the request as it is */ }
|
|
19
|
+
return f(input, init);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function boot() {
|
|
24
|
+
const root = document.getElementById('c3-root');
|
|
25
|
+
let ws = q.get('ws') || '';
|
|
26
|
+
if (DEMO) { const m = await import('./c3-demo.js'); m.installDemo(); if (window.__c3demoReady) await window.__c3demoReady; if (!ws) ws = m.DEMO_WS; root.setAttribute('data-c3-demo', '1'); }
|
|
27
|
+
const pref = q.get('theme') || store.get('pmos.c3.theme') || 'light';
|
|
28
|
+
const theme = pref === 'dark' || (pref === 'system' && typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
|
|
29
|
+
document.documentElement.setAttribute('data-pm-page-theme', theme);
|
|
30
|
+
root.setAttribute('data-pm-theme', theme);
|
|
31
|
+
try { if (localStorage.getItem('pmos.c3.phone')) localStorage.setItem('pmos.c3.phone', ''); } catch { /* no storage */ } // the dropped Full console choice
|
|
32
|
+
ensureC3Css();
|
|
33
|
+
c3Phone(root);
|
|
34
|
+
if (!DEMO || !ws) {
|
|
35
|
+
const list = await pmGet('/api/workspaces').then((j) => (j && j.workspaces) || []).catch(() => []);
|
|
36
|
+
if (!ws || !list.some((w) => w.id === ws)) ws = (list[0] && list[0].id) || ws;
|
|
37
|
+
}
|
|
38
|
+
withWs(ws);
|
|
39
|
+
root.replaceChildren();
|
|
40
|
+
root.classList.add('c3-phone-on');
|
|
41
|
+
mountPhone(root, { ws, demo: DEMO });
|
|
42
|
+
if (q.get('focus') || q.get('fdate')) import('./c3-focus.js').then((m) => m.openFocus({ event: { id: q.get('focus') || '' }, date: q.get('fdate') || '', phone: true })).catch(() => { /* the focus page is not available */ });
|
|
43
|
+
const mq = matchMedia('(max-width:640px)');
|
|
44
|
+
mq.addEventListener('change', () => { if (!mq.matches) location.reload(); });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
boot().catch((e) => { const r = document.getElementById('c3-root'); if (r) r.textContent = 'PMOS could not start: ' + String((e && e.message) || e); });
|
|
@@ -74,7 +74,7 @@ export function mountPhone(root, ctx = {}) {
|
|
|
74
74
|
iconButton({ icon: 'mic', ariaLabel: 'Dictate', size: 'sm', attrs: { 'data-c3ph-dictate': '' }, onClick: () => { input.focus(); toast('Use the mic on your keyboard to talk. PMOS files what you say.'); } }));
|
|
75
75
|
const recBtn = button({ label: '', variant: 'outline', attrs: { class: 'c3ph-recdot', 'data-c3ph-record': '', 'aria-label': 'Record a conversation or meeting', title: 'Record a conversation or meeting' }, onClick: () => startRec(null) });
|
|
76
76
|
recBtn.replaceChildren(el('span', { class: 'c3ph-reddot', 'aria-hidden': 'true' }));
|
|
77
|
-
const foot = el('div', { class: 'c3ph-ft', 'data-c3ph-foot': '' });
|
|
77
|
+
const foot = el('div', { class: 'c3ph-ft', 'data-c3ph-foot': '' }, form, recBtn); // shown at once; syncRec swaps in the recording bar
|
|
78
78
|
host.append(head, bannerHost, body, foot);
|
|
79
79
|
root.append(host);
|
|
80
80
|
|