create-pmos 0.227.0 → 0.228.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pmos",
3
- "version": "0.227.0",
3
+ "version": "0.228.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": {
@@ -1,3 +1,3 @@
1
- kernel-source: pmos@87765df
1
+ kernel-source: pmos@3627ad6
2
2
  assembled: 2026-10-14
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-10-14T07:02:16Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-14T07:24:11Z"}
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-14T07:02:16Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-14T07:24:11Z"}
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-14T07:02:16Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-14T07:24:11Z"}
6
6
  status: stable
7
7
  ---
8
8
 
@@ -265,7 +265,7 @@ The task appears in your My Work view and on the initiative's board when the not
265
265
 
266
266
  Under the title, a note shows two lines: **Meeting** and **Initiative**.
267
267
 
268
- - **Meeting** is the calendar event the note was taken in, or **Not on the calendar** for a hallway chat or a call. Press **Change** to select an event of the note's day or the day before, or **Not on the calendar**.
268
+ - **Meeting** is the calendar event the note was taken in, or **Not on the calendar** for a hallway chat or a call. Press **Change** to select an event of the note's day or the day before, or **Not on the calendar**. The list has every meeting the Calendar shows on those days, including meetings imported in Settings › Import.
269
269
  - **Initiative** is the initiative the meeting was about. It says how it was set: **from the calendar event**, **suggested from what was said**, or **chosen by you**. Press **Change** to open the list. The list shows the suggestion first, then the initiatives that are active now, then **None**. Initiatives planned for Next and Later are in the menu under them, each marked with its horizon. When more than one repository is open, a **Repository** menu at the top of the list changes which repository's initiatives you see. If the repository is still being read, the list says so and fills in by itself. Press the initiative's name to open it.
270
270
 
271
271
  When a note has no initiative, the summary suggests one: the open initiative that shares 3 or more words with what was said, when no other initiative shares as many. A suggestion never replaces an initiative you chose.
@@ -72,10 +72,10 @@ function readAll(runtimeDir, { now = Date.now() } = {}) {
72
72
  return out.sort((a, b) => (Date.parse(a.at) || 0) - (Date.parse(b.at) || 0));
73
73
  }
74
74
 
75
- /** Today's meetings as the Record menu reads them (GET /api/calendar-today): every event readAll joins, kept when its start falls on
76
- * the local day of `now`, in the shape the menu and a note's meeting link use: { id, start, end, title, time, minutes, with, src, ... }. Pure. */
77
- function todayOf(events, now = Date.now()) {
78
- const day = localDate(now);
75
+ /** One day's meetings as the Record menu and a note's meeting picker read them (GET /api/calendar-today?date=): every event readAll
76
+ * joins, kept when its start falls on the local day `day` (YYYY-MM-DD), in the shape the menu and a note's meeting link use:
77
+ * { id, start, end, title, time, minutes, with, src, ... }. Pure. */
78
+ function eventsOn(events, day) {
79
79
  const out = [];
80
80
  for (const e of events || []) {
81
81
  const s = Date.parse(e && e.at);
@@ -89,5 +89,7 @@ function todayOf(events, now = Date.now()) {
89
89
  }
90
90
  return out.sort((a, b) => Date.parse(a.start) - Date.parse(b.start));
91
91
  }
92
+ /** Today's meetings (the Record menu): eventsOn the local day of `now`. */
93
+ const todayOf = (events, now = Date.now()) => eventsOn(events, localDate(now));
92
94
 
93
- module.exports = { readAll, asEvent, localIso, todayOf };
95
+ module.exports = { readAll, asEvent, localIso, todayOf, eventsOn };
@@ -5,7 +5,8 @@
5
5
  * layers, layers_total, layers_note, free, context, context_total, (lib/calendar-layers.js)
6
6
  * link_boards } every board a meeting can be linked to: [{ ws, id, name }]
7
7
  * &only=gantt → { ok, view, range, gantt, no_plan, strategy, today } the rows with a plan date or a Jira read, and how many have neither
8
- * GET /api/calendar-today → { ok, date, events } today's meetings for the Record menu (calendar-events.js todayOf)
8
+ * GET /api/calendar-today[?date=YYYY-MM-DD] → { ok, date, events } one day's meetings (default today) for the Record menu and a
9
+ * note's meeting picker (calendar-events.js eventsOn)
9
10
  * POST /api/calendar-links → { ok, link } what a meeting is about (lib/calendar-links.js, below)
10
11
  * tidy, tidy_total, tidy_note } (lib/calendar-tidy.js: suggestions in words, no write)
11
12
  *
@@ -232,10 +233,11 @@ module.exports = {
232
233
  if (url.pathname === '/api/calendar-today') {
233
234
  if (req.method !== 'GET') { ctx.json(res, { ok: false, error: 'GET only' }, 405); return true; }
234
235
  const cal = require('./calendar-events.js');
235
- const now = Date.now();
236
+ const date = url.searchParams.get('date') || today();
237
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) { ctx.json(res, { ok: false, error: 'date must be YYYY-MM-DD' }, 400); return true; }
236
238
  let events = [];
237
- try { events = cal.todayOf(cal.readAll(ctx.runtimeDir, { now }), now); } catch { events = []; }
238
- ctx.json(res, { ok: true, date: today(), events });
239
+ try { events = cal.eventsOn(cal.readAll(ctx.runtimeDir, { now: Date.now() }), date); } catch { events = []; }
240
+ ctx.json(res, { ok: true, date, events });
239
241
  return true;
240
242
  }
241
243
  if (url.pathname !== '/api/calendar-views') return false;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pmos-workspace",
3
- "version": "0.227.0",
3
+ "version": "0.228.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pmos-workspace",
9
- "version": "0.227.0",
9
+ "version": "0.228.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@xterm/addon-fit": "^0.11.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmos-workspace",
3
- "version": "0.227.0",
3
+ "version": "0.228.0",
4
4
  "private": true,
5
5
  "description": "PMOS Terminal Workspace — local companion hosting real PTYs beside the library and gates (D62)",
6
6
  "license": "MIT",
@@ -1191,18 +1191,15 @@ async function link(ctx, n, patch, said) {
1191
1191
  } else banner = { tone: 'bad', text: (r && r.error) || 'the link was not changed' };
1192
1192
  ctx.setState({});
1193
1193
  }
1194
- /** The events of the note's day and the day before, from the Agenda's read. */
1194
+ /** The events of the note's day and the day before, from the list the Calendar draws (GET /api/calendar-today?date=, lib/calendar-events.js
1195
+ * readAll). The Agenda's read held only the calendar memory and today's brief, so an imported meeting was on the Calendar and missing here. */
1195
1196
  async function eventsNear(n) {
1196
1197
  const at = n.created_at || new Date().toISOString();
1197
- const day = dateOfIso(at); const before = dateOfIso(new Date(Date.parse(at) - 86400000).toISOString());
1198
- const months = [...new Set([ymOfIso(at), before.slice(0, 7)])];
1199
- const reads = await Promise.all(months.map((m) => pmGet('/api/proactive/agenda?month=' + m)));
1198
+ const days = [dateOfIso(new Date(Date.parse(at) - 86400000).toISOString()), dateOfIso(at)];
1199
+ const reads = await Promise.all(days.map((d) => pmGet('/api/calendar-today?date=' + d)));
1200
1200
  const out = []; const seen = new Set();
1201
- for (const r of reads) {
1202
- if (!r || !r.days) continue;
1203
- for (const d of [before, day]) for (const e of ((r.days[d] && r.days[d].events) || [])) { const k = e.start + '|' + e.title; if (!seen.has(k)) { seen.add(k); out.push({ ...e, date: d }); } }
1204
- }
1205
- return out.sort((a, b) => String(a.start).localeCompare(String(b.start)));
1201
+ reads.forEach((r, i) => { for (const e of (r && r.events) || []) { const k = e.start + '|' + e.title; if (!seen.has(k)) { seen.add(k); out.push({ ...e, date: days[i] }); } } });
1202
+ return out.sort((a, b) => Date.parse(a.start) - Date.parse(b.start));
1206
1203
  }
1207
1204
  async function meetingSheet(ctx, n) {
1208
1205
  const box = el('div', { class: 'nt-picks', role: 'radiogroup', 'aria-label': 'Meeting' }, el('p', { class: 'nt-hint' }, 'reading your calendar …'));
@@ -1227,7 +1224,7 @@ async function meetingSheet(ctx, n) {
1227
1224
  if (on) pick = String(i);
1228
1225
  const other = notesFor(e).some((x) => x.id !== n.id);
1229
1226
  return opt(String(i), e.title, dayOf(e.start) + ', ' + e.time + (other ? ' · has a note' : ''), on);
1230
- }), evs.length ? null : el('p', { class: 'nt-hint' }, 'No calendar events on these days.'),
1227
+ }), ...(evs.length ? [] : [el('p', { class: 'nt-hint' }, 'No calendar events on these days.')]),
1231
1228
  opt('adhoc', 'Not on the calendar', 'a hallway chat, a call', pick === 'adhoc'));
1232
1229
  }
1233
1230
  const HORIZON_WORDS = { now: 'Now', next: 'Next', later: 'Later' };