create-pmos 0.55.3 → 0.55.4

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.55.3",
3
+ "version": "0.55.4",
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@d183aab
1
+ kernel-source: pmos@46269fd
2
2
  assembled: 2026-10-06
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-06T08:46:09Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T09:30:22Z"}
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-06T08:46:09Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T09:30:22Z"}
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-06T08:46:09Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T09:30:22Z"}
6
6
  status: stable
7
7
  ---
8
8
 
@@ -18,7 +18,7 @@ Press **Prepare my day** to start the day. It runs from the brief to the deliver
18
18
 
19
19
  If the morning-brief session stops before it submits a brief, the Read step says so and gives the reason. **Prepare my day** is then ready again, so press it to try once more. If the session says that its folder is not there, open the repository again from its current folder first.
20
20
 
21
- Each agent job runs in its own session, so you can open any job and follow or steer it. The workspace types the job's prompt into the session when the agent is ready to read, and presses Enter for you. When you approve or revise a job and its session is still open, the workspace uses that same session again.
21
+ Each agent job runs in its own session, so you can open any job and follow or steer it. The workspace types the job's prompt into the session when the agent is ready to read, and presses Enter for you. When you approve or revise a job and its session is still open, the workspace uses that same session again. Prepare again works the same way: when the morning-brief session is still open and has finished its read, or has printed nothing for two minutes, the workspace types the read into that session and runs it again.
22
22
 
23
23
  **Agent results**, at the top of the left column, counts the jobs and lists each finished one with its draft summary or the reason it failed. The other things that wait for you, such as outcome checks, report drafts and sessions, are in **Also waiting for you** at the end of the left column. When the day is folded, they show under it.
24
24
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmos-workspace",
3
- "version": "0.55.3",
3
+ "version": "0.55.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmos-workspace",
3
- "version": "0.55.3",
3
+ "version": "0.55.4",
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",
@@ -3639,6 +3639,18 @@ function briefOfDay(date) {
3639
3639
  try { return JSON.parse(fs.readFileSync(path.join(STATE, 'briefs', date + '.json'), 'utf8')); } catch { return null; }
3640
3640
  }
3641
3641
  const daySessionAlive = (id) => { const s = id && sessions.get(id); return !!s && s.state !== 'exited'; };
3642
+ // An agent CLI does not exit when its work is done: the morning-brief session stays open after it submits the brief. So
3643
+ // "alive" alone does not mean "still reading". The read is over when today's brief arrived after the session started,
3644
+ // or when the pane has printed nothing for BRIEF_IDLE_MS without a brief (it waits on a question, or never got its prompt).
3645
+ const BRIEF_IDLE_MS = 2 * 60 * 1000;
3646
+ function briefSessionDone(run, date, now) {
3647
+ const bs = run && run.brief_session; const s = bs && sessions.get(bs.id);
3648
+ if (!s || s.state === 'exited' || bs.ended_at) return null;
3649
+ let at = 0; try { at = fs.statSync(path.join(STATE, 'briefs', date + '.json')).mtimeMs; } catch { /* no brief yet */ }
3650
+ if (at && at >= Date.parse(bs.started_at || 0)) return 'submitted';
3651
+ if (now - Math.max(s.lastOutputAt || 0, Date.parse(bs.started_at || 0) || 0) >= BRIEF_IDLE_MS) return 'idle';
3652
+ return null;
3653
+ }
3642
3654
  // The skill's own body is the prompt, as fireSchedule hands it over; the line after it names this run's task and mode.
3643
3655
  function daySkillPrompt(run, skillId) {
3644
3656
  const w = getWs(run.ws);
@@ -7178,6 +7190,18 @@ async function handleRequest(req, res) {
7178
7190
  let run = readDayRun(pdate) || dayRunLib.newRun(pdate, pnow);
7179
7191
  run.ws = w.id;
7180
7192
  if (run.brief_session && !run.brief_session.ended_at) {
7193
+ // A session that finished its read (or sits idle) is used again: the skill's prompt is typed into it and run.
7194
+ const done = daySessionAlive(run.brief_session.id) ? briefSessionDone(run, pdate, pnow) : null;
7195
+ if (done) {
7196
+ const sk = daySkillPrompt(run, 'morning-brief');
7197
+ const s = sessions.get(run.brief_session.id);
7198
+ if (!sk.error) {
7199
+ try { firstInput.deliver(s, `${sk.prompt}\n\nThis run: prepare the day again. Read every source again and submit a new brief for today.\r`); } catch { /* typed below as a new session */ }
7200
+ run.brief_session = { id: s.id, started_at: new Date(pnow).toISOString(), ended_at: null };
7201
+ writeDayRun(run);
7202
+ return json(res, { ok: true, started: true, reused: true, session: s.id, run, goals: open.length });
7203
+ }
7204
+ }
7181
7205
  if (daySessionAlive(run.brief_session.id)) { writeDayRun(run); return json(res, { ok: true, running: true, session: run.brief_session.id, run, goals: open.length }); }
7182
7206
  run = dayRunLib.sessionEnded(run, run.brief_session.id, pnow).run;
7183
7207
  }
@@ -7230,7 +7254,8 @@ async function handleRequest(req, res) {
7230
7254
  const bs = run && run.brief_session; const bsess = bs ? sessions.get(bs.id) : null;
7231
7255
  const readFailed = !run || brief ? null
7232
7256
  : !bs ? { session: null, why: 'the morning-brief session did not start.' }
7233
- : (!!bs.ended_at || !bsess || bsess.state === 'exited') ? { session: bs.id, why: (bsess && bsess.note) || 'the session ended without submitting a brief.' } : null;
7257
+ : (!!bs.ended_at || !bsess || bsess.state === 'exited') ? { session: bs.id, why: (bsess && bsess.note) || 'the session ended without submitting a brief.' }
7258
+ : briefSessionDone(run, date, now) === 'idle' ? { session: bs.id, idle: true, why: 'the session has printed nothing for two minutes and has not submitted a brief.' } : null;
7234
7259
  return json(res, { ok: true, ws: w ? w.id : null, today: date, now: new Date(now).toISOString(), run, stage: dayRunLib.stage(run, brief), brief, plan, cards_error: cardsError, read_failed: readFailed,
7235
7260
  settings: { briefSources: st.briefSources, scopes: st.scopes, dayCheck: st.dayCheck, websites: st.websites }, sources,
7236
7261
  check: { every: st.dayCheck.every, last: run ? run.checks.last : null, next: due.next, running: !!(run && run.checks.session_id), log: run ? run.checks.log : [] } });