create-pmos 0.53.2 → 0.54.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/guide/proactive-engine.md +1 -0
- package/workspace/package-lock.json +1 -1
- package/workspace/package.json +1 -1
- package/workspace/public/pm/components.css +2 -0
- package/workspace/public/pm/today-copy.js +4 -0
- package/workspace/public/pm/today-goals.js +40 -6
- package/workspace/test-files.json +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.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-06T02:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-06T02:54:46Z"}
|
|
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-06T02:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-06T02:54:46Z"}
|
|
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-06T02:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-06T02:54:46Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -16,6 +16,7 @@ At the top of Today you can list what you want done today. A goal is one line of
|
|
|
16
16
|
- Open **Goals for today** and type a goal. Press Enter to add it. A day has at most 7 goals, each at most 140 characters.
|
|
17
17
|
- Press **Done**, **Drop**, **Reopen** or **Remove** on a goal. A goal is open, done or dropped.
|
|
18
18
|
- Press **Prepare my day**. The workspace makes the daily 06:45 morning-brief schedule if this repository has none, and runs it now. The session reads your goals, your calendar, and the mentions of you in Slack, Jira and Confluence. It ties each meeting, mention and step that moves a goal to that goal.
|
|
19
|
+
- While the press runs, the button says **Starting…**. When the session starts, its terminal tab opens and the goals section says when it started; **Open the session** opens the tab again. If the session cannot start, the section says why in red.
|
|
19
20
|
- Each goal shows its steps: yours first, then the agent's. A step comes from the brief, or from a Today card on the goal's initiative. A goal with no step says so. The session does not invent a step.
|
|
20
21
|
- A step is under a goal only when the brief names the goal, or when the step and the goal name the same initiative. The workspace never matches words.
|
|
21
22
|
- An agent step that names an initiative has **Prepare**. It shows the step, the branch and the prompt, the same as background preparation. **Queue it** approves that exact prompt. Background preparation must be on in the settings. Otherwise the queue says so and nothing is queued.
|
package/workspace/package.json
CHANGED
|
@@ -2184,6 +2184,8 @@
|
|
|
2184
2184
|
}
|
|
2185
2185
|
.td-goal__prep { display: inline-flex; align-items: center; gap: 8px; }
|
|
2186
2186
|
.td-goals__bar { display: flex; gap: 8px; }
|
|
2187
|
+
.td-goals__run { margin: 0; font-size: 12px; line-height: 16px; color: var(--foreground); }
|
|
2188
|
+
.td-goals__run--failed { color: var(--destructive); }
|
|
2187
2189
|
.td-goals__sub { margin: 4px 0 0; font-size: 12px; font-weight: 600; color: var(--muted-foreground); }
|
|
2188
2190
|
.td-card {
|
|
2189
2191
|
display: flex;
|
|
@@ -67,6 +67,10 @@ export const COPY = {
|
|
|
67
67
|
prepareDay: 'Prepare my day',
|
|
68
68
|
prepareDayHint: 'Starts a session that reads your calendar and your Slack, Jira and Confluence mentions, and ties what it finds to your goals.',
|
|
69
69
|
started: 'The session started. The steps show here when it is done.',
|
|
70
|
+
starting: 'Starting…',
|
|
71
|
+
runStarted: (at) => `Started at ${at}. The session is reading your calendar and mentions; the steps show here when it is done.`,
|
|
72
|
+
runFailed: (why) => `Not started. ${why}`,
|
|
73
|
+
openSession: 'Open the session',
|
|
70
74
|
coverage: { planned: 'has steps', 'needs-plan': 'no step yet', done: 'done', dropped: 'dropped' },
|
|
71
75
|
done: 'Done', drop: 'Drop', reopen: 'Reopen', remove: 'Remove',
|
|
72
76
|
you: 'You', agent: 'Agent', mention: 'mention',
|
|
@@ -49,12 +49,35 @@ async function press(ws, body) {
|
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// "Prepare my day", per repository: { state: 'busy' | 'started' | 'failed', at, session, error }. The session runs in the
|
|
53
|
+
// background, so the section says what happened and offers to open it; a toast alone is gone before the PM looks.
|
|
54
|
+
const runs = new Map();
|
|
55
|
+
|
|
52
56
|
async function prepareDay(ws) {
|
|
57
|
+
const cur = runs.get(ws);
|
|
58
|
+
if (cur && cur.state === 'busy') return;
|
|
59
|
+
runs.set(ws, { state: 'busy' });
|
|
60
|
+
rerender();
|
|
53
61
|
const r = await pmPost('/api/proactive/goals/plan', { ws });
|
|
54
|
-
|
|
62
|
+
const sid = r && r.result && r.result.sessionId;
|
|
63
|
+
if (r && r.ok) {
|
|
64
|
+
const session = sid ? { id: sid, name: 'morning-brief' } : null;
|
|
65
|
+
runs.set(ws, { state: 'started', at: Date.now(), session });
|
|
66
|
+
toast({ text: G.started });
|
|
67
|
+
if (session) openSession(session);
|
|
68
|
+
} else {
|
|
69
|
+
const error = (r && r.error) || G.unreached;
|
|
70
|
+
runs.set(ws, { state: 'failed', at: Date.now(), error });
|
|
71
|
+
toast({ text: G.runFailed(error), tone: 'destructive' });
|
|
72
|
+
}
|
|
73
|
+
rerender();
|
|
55
74
|
load(ws);
|
|
56
75
|
}
|
|
57
76
|
|
|
77
|
+
async function openSession(session) {
|
|
78
|
+
try { const m = await import('./handoff-box.js'); await m.openSessionTab(null, session); } catch (e) { console.error('[pm] could not open the session:', e); }
|
|
79
|
+
}
|
|
80
|
+
|
|
58
81
|
async function prepareStep(ws, st) {
|
|
59
82
|
const r = await pmPost('/api/proactive/prepare/plan', { ws, initiative_id: st.initiative_id });
|
|
60
83
|
if (!r || r.ok === false) { toast({ text: G.refused((r && r.error) || G.unreached), tone: 'destructive' }); return; }
|
|
@@ -140,15 +163,26 @@ export function goalsSection({ ws, setState } = {}) {
|
|
|
140
163
|
if (goals.length < max) {
|
|
141
164
|
const f = field({ label: G.inputLabel, value: draft, placeholder: G.inputHint, hideLabel: true, attrs: { 'data-goals': 'input', maxlength: '140' },
|
|
142
165
|
onCommit: async (v) => {
|
|
143
|
-
draft = v;
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
if (!String(v).trim()) { draft = v; return; }
|
|
167
|
+
// clear before the press: its reload re-renders the section, and a rebuild must not bring the text back
|
|
168
|
+
draft = '';
|
|
169
|
+
if (await press(ws, { action: 'add', text: v })) { if (f.control.resetCommitted) f.control.resetCommitted(''); f.control.value = ''; rerender(); }
|
|
170
|
+
else { draft = v; rerender(); }
|
|
146
171
|
} });
|
|
147
172
|
f.control.addEventListener('input', () => { draft = f.control.value; }); // a rebuild keeps what is typed
|
|
148
173
|
kids.push(f);
|
|
149
174
|
} else kids.push(el('p', { class: 'td-goals__note' }, G.full(max)));
|
|
175
|
+
const run = runs.get(ws);
|
|
176
|
+
const busy = !!run && run.state === 'busy';
|
|
150
177
|
kids.push(el('div', { class: 'td-goals__bar' },
|
|
151
|
-
button({ label: G.prepareDay, attrs: { 'data-goals': 'prepare-day', title: G.prepareDayHint
|
|
178
|
+
button({ label: busy ? G.starting : G.prepareDay, attrs: { 'data-goals': 'prepare-day', title: G.prepareDayHint, 'aria-busy': busy ? 'true' : 'false' },
|
|
179
|
+
disabled: !openN || busy, onClick: () => prepareDay(ws) }),
|
|
180
|
+
run && run.state === 'started' && run.session
|
|
181
|
+
? button({ label: G.openSession, variant: 'ghost', attrs: { 'data-goals': 'open-session' }, onClick: () => openSession(run.session) }) : null));
|
|
182
|
+
if (run && run.state !== 'busy') {
|
|
183
|
+
kids.push(el('p', { class: 'td-goals__run' + (run.state === 'failed' ? ' td-goals__run--failed' : ''), 'data-goals': 'run', 'data-run': run.state,
|
|
184
|
+
role: run.state === 'failed' ? 'alert' : 'status' }, run.state === 'failed' ? G.runFailed(run.error) : G.runStarted(hhmm(run.at))));
|
|
185
|
+
}
|
|
152
186
|
if (plan) {
|
|
153
187
|
const lines = [];
|
|
154
188
|
if (!plan.brief) lines.push(G.noBrief);
|
|
@@ -168,5 +202,5 @@ export function goalsSection({ ws, setState } = {}) {
|
|
|
168
202
|
|
|
169
203
|
export function goalsSig(ws) {
|
|
170
204
|
const c = cache.get(ws) || {};
|
|
171
|
-
return JSON.stringify([open, c.data && c.data.plan, c.error, [...prepared.keys()]]);
|
|
205
|
+
return JSON.stringify([open, draft === '', c.data && c.data.plan, c.error, [...prepared.keys()], runs.get(ws) || null]);
|
|
172
206
|
}
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"pm-r20-test.js",
|
|
79
79
|
"pm-r21-test.js",
|
|
80
80
|
"pm-r22-test.js",
|
|
81
|
+
"pm-today-goals-test.js",
|
|
81
82
|
"pm-r23-test.js",
|
|
82
83
|
"pm-r24-test.js",
|
|
83
84
|
"pm-r25-test.js",
|
|
@@ -168,6 +169,7 @@
|
|
|
168
169
|
"pm-r20-test.js": 4,
|
|
169
170
|
"pm-r21-test.js": 4,
|
|
170
171
|
"pm-r22-test.js": 32,
|
|
172
|
+
"pm-today-goals-test.js": 8,
|
|
171
173
|
"pm-r23-test.js": 13,
|
|
172
174
|
"pm-r24-test.js": 4,
|
|
173
175
|
"pm-r25-test.js": 9,
|