create-pmos 0.175.0 → 0.176.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-sessions-panel-test.js +2 -0
- package/workspace/guide/console3-sessions.md +2 -0
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/c3-session-term.js +5 -0
- package/workspace/public/pm/sessions-panel.js +10 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.176.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-13T01:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T01:16: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-10-13T01:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T01:16: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-10-13T01:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T01:16:54Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -177,6 +177,8 @@ function startShell(name) {
|
|
|
177
177
|
/* ── D: End asks first, then ends ── */
|
|
178
178
|
await page.click('[data-c3pg="agent-button"]');
|
|
179
179
|
ok('D0 the panel opens again', await waitFor(page, (s) => !!document.querySelector(s), sel));
|
|
180
|
+
ok('D0b it opens on the session opened last: its row is open and marked', await waitFor(page, (i) => { const li = document.querySelector(`[data-c3t="mine"] [data-run="${i}"]`); const end = document.querySelector(`[data-end-session="${i}"]`); return !!li && li.hasAttribute('data-last-open') && !!end && end.offsetParent !== null; }, id)
|
|
181
|
+
&& await page.evaluate((i) => localStorage.getItem('pmos.workspace.c3.last-session') === i, id));
|
|
180
182
|
if (!(await page.isVisible(`[data-end-session="${id}"]`).catch(() => false))) await page.click(sel + ' .nb');
|
|
181
183
|
await page.click(`[data-end-session="${id}"]`);
|
|
182
184
|
ok('D1 End asks first', await waitFor(page, (i) => !!document.querySelector(`[data-end-confirm="${i}"]`), id));
|
|
@@ -9,6 +9,8 @@ timestamp: 2026-10-13
|
|
|
9
9
|
|
|
10
10
|
Press the **Sessions** button in the console3 header to open the panel. It is the bolt icon with no label. Point at it to see its name. When a session needs you, a count shows on it. It shows your sessions in four groups: **On a card**, **Started by me**, **Past (7 days)** and **Automatic**.
|
|
11
11
|
|
|
12
|
+
The panel opens on the session that you opened last. Its row is open, so you can read the conversation and send a message without searching for it. A session counts as opened when you open its row or its terminal.
|
|
13
|
+
|
|
12
14
|
## The dock
|
|
13
15
|
|
|
14
16
|
The dock is folded when you first open the console. To open it, press Ctrl J (⌘J on a Mac), or use **Open the dock** in the **More** menu. The browser keeps your choice: when you leave the dock open, it opens on the Briefing next time. On the other tabs it is folded away, and no rail of buttons is left at the right edge.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.176.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.176.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED
|
@@ -19,6 +19,10 @@ const store = {
|
|
|
19
19
|
export const SIZE_KEY = 'pmos.workspace.c3.term-size';
|
|
20
20
|
export const PAD_KEY = 'pmos.workspace.c3.term-pad';
|
|
21
21
|
export const PAD_H_KEY = 'pmos.workspace.c3.term-pad-h';
|
|
22
|
+
/* the session the PM opened last (its terminal here, or its row in the Sessions panel): the panel opens on it */
|
|
23
|
+
export const LAST_SESSION_KEY = 'pmos.workspace.c3.last-session';
|
|
24
|
+
export const rememberSession = (id) => { if (id) store.set(LAST_SESSION_KEY, String(id)); };
|
|
25
|
+
export const lastSession = () => store.get(LAST_SESSION_KEY) || null;
|
|
22
26
|
const PAD_ROWS = 4; // the default height
|
|
23
27
|
/** The pad's height in rows: at least 2, and at most what leaves the terminal its room in a column `room` px high with `lh` px rows. Pure, for Node. */
|
|
24
28
|
export const clampPad = (rows, room, lh) => Math.max(2, Math.min(Math.round(rows), Math.max(2, Math.floor((room - 200) / (lh || 18)))));
|
|
@@ -122,6 +126,7 @@ function makePad(id, term, tab) {
|
|
|
122
126
|
|
|
123
127
|
export async function openSessionTerm({ id, name } = {}) {
|
|
124
128
|
if (!id) return null;
|
|
129
|
+
rememberSession(id);
|
|
125
130
|
if (!name) { const r = await pmGet('/api/sessions').catch(() => null); const x = r && Array.isArray(r.sessions) ? r.sessions.find((y) => y.id === id) : null; name = x ? x.name : id; }
|
|
126
131
|
const [ok, term] = await Promise.all([loadVendor(), import('./tab-term.js').catch(() => null)]);
|
|
127
132
|
if (!ok || !term) { toast({ text: 'The terminal could not be loaded on this page.', tone: 'error' }); return null; }
|
|
@@ -16,6 +16,7 @@ import { toast } from './c3-toast.js';
|
|
|
16
16
|
import { pmPost } from './http.js';
|
|
17
17
|
import { button } from './primitives.js';
|
|
18
18
|
import { chatFeed } from './c3-session-chat.js';
|
|
19
|
+
import { rememberSession, lastSession } from './c3-session-term.js';
|
|
19
20
|
|
|
20
21
|
const live = new WeakMap();
|
|
21
22
|
const DOT = { working: 'w', queued: 'w', asking: 'n', permission: 'n', attention: 'n', not_started: 'n', failed: 'b', quiet: '', paused: 'n', done: '' };
|
|
@@ -56,7 +57,7 @@ function row(st, s, card, parts) {
|
|
|
56
57
|
li.style.gridTemplateColumns = 'auto minmax(0,1fr) auto';
|
|
57
58
|
xp.style.gridColumn = '1 / -1';
|
|
58
59
|
const key = 'r-' + s.id;
|
|
59
|
-
attachExpand(li, xp, { key, initial: st.open.has(key), onToggle: (on) => { if (on) st.open.add(key); else st.open.delete(key); } });
|
|
60
|
+
attachExpand(li, xp, { key, initial: st.open.has(key), onToggle: (on) => { if (on) { st.open.add(key); rememberSession(s.id); } else st.open.delete(key); } });
|
|
60
61
|
return li;
|
|
61
62
|
}
|
|
62
63
|
const dim = (t) => el('span', { class: 'dim mono', style: 'font-size:var(--fs-2)' }, t);
|
|
@@ -180,7 +181,9 @@ export function mountSessions(host, ctx = {}) {
|
|
|
180
181
|
disposeSessions(host);
|
|
181
182
|
if (ctx && ctx.FIXTURE) return;
|
|
182
183
|
ensureC3Css();
|
|
183
|
-
|
|
184
|
+
// the panel opens on the session the PM opened last: its row starts open, and the first draw brings it into view
|
|
185
|
+
const lastId = lastSession();
|
|
186
|
+
const st = { src: source(), data: null, showAuto: false, last: '', gone: false, timer: null, refresh: null, redraw: null, open: new Set(lastId ? ['r-' + lastId] : []), confirm: null, reveal: lastId,
|
|
184
187
|
openSession: (id) => { const r = st.data && st.data.groups ? [].concat(...Object.values(st.data.groups).filter(Array.isArray)).find((x) => x.id === id) : null;
|
|
185
188
|
import('./c3-session-term.js').then((m) => m.openSessionTerm({ id, name: r ? r.name : id })); } };
|
|
186
189
|
if (st.src.demo) st.openSession = () => toast('In the real workspace this opens the CLI session.');
|
|
@@ -194,6 +197,11 @@ export function mountSessions(host, ctx = {}) {
|
|
|
194
197
|
st.last = key; st.data = r;
|
|
195
198
|
if (r.ok && ctx.onNeeds) ctx.onNeeds(needsYou(r));
|
|
196
199
|
if (!busy()) draw(host, st); else st.last = '';
|
|
200
|
+
if (st.reveal && r.ok) {
|
|
201
|
+
const li = host.querySelector(`[data-run="${CSS.escape(st.reveal)}"]`);
|
|
202
|
+
st.reveal = null;
|
|
203
|
+
if (li) { li.setAttribute('data-last-open', ''); requestAnimationFrame(() => li.scrollIntoView({ block: 'nearest' })); }
|
|
204
|
+
}
|
|
197
205
|
};
|
|
198
206
|
st.timer = setInterval(() => { if (!busy()) st.refresh(); }, 5000);
|
|
199
207
|
if (st.src.subscribe) st.unsub = st.src.subscribe(() => st.refresh());
|