create-pmos 0.120.0 → 0.121.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/initiatives-and-next-steps.md +2 -2
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/next-step-ui.js +8 -4
- package/workspace/server.js +10 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.121.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-08T09:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-08T09:17:45Z"}
|
|
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-08T09:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-08T09:17:45Z"}
|
|
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-08T09:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-08T09:17:45Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Guide
|
|
3
3
|
title: "Guide: initiatives and next steps"
|
|
4
4
|
description: "What the initiative detail shows, top to bottom: status, lifecycle control, and the next step the workspace proposes."
|
|
5
|
-
timestamp: 2026-10-
|
|
5
|
+
timestamp: 2026-10-08
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Guide: initiatives and next steps
|
|
@@ -73,7 +73,7 @@ At most 3 prepared sessions run at once and 8 start each day. Go refuses a start
|
|
|
73
73
|
|
|
74
74
|
### Sources and the typed judgment option
|
|
75
75
|
|
|
76
|
-
Choose
|
|
76
|
+
The plan starts with your default Claude profile from Settings. Choose another profile, or none, in the plan. Prepare again and Hand to agent start under the same default. The session may read only the sources that profile declares and that suit the step: Wispr Flow notes, Gmail, Google Calendar, Confluence, Jira and Slack. They are read-only.
|
|
77
77
|
|
|
78
78
|
You can turn on the Typesafe skill for a run. It helps the session categorise, score and decide yes or no with a typed answer. It sends the question text to an outside service and needs `TYPESAFE_API_KEY` in the session. It is off by default. The session prints each answer as a `JUDGMENT` line, and the review checks its shape.
|
|
79
79
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.121.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.121.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { el } from './dom.js';
|
|
16
16
|
import { state, setState, FIXTURE } from './state.js';
|
|
17
17
|
import { askText } from './dialogs.js';
|
|
18
|
+
import { adoptProfileDefault } from './dock.js';
|
|
18
19
|
|
|
19
20
|
let dataMod = null;
|
|
20
21
|
const dataReady = import('./data.js').then((m) => { dataMod = m; }).catch(() => { dataMod = null; });
|
|
@@ -30,14 +31,17 @@ const iv = (t) => el('span', null, t == null ? '' : String(t));
|
|
|
30
31
|
const ui = Object.create(null);
|
|
31
32
|
let profileList = null;
|
|
32
33
|
const touch = () => setState((s) => ({ nsTick: (s.nsTick || 0) + 1 }));
|
|
33
|
-
const slot = (id) => (ui[id] = ui[id] || { judgment: false, profile:
|
|
34
|
+
const slot = (id) => (ui[id] = ui[id] || { judgment: false, profile: undefined });
|
|
34
35
|
|
|
35
36
|
async function prepare(slug, it) {
|
|
36
37
|
const u = slot(it.id);
|
|
37
38
|
u.loading = true; u.note = null; touch();
|
|
38
39
|
await dataReady;
|
|
39
|
-
|
|
40
|
-
const
|
|
40
|
+
// Read every time: the default profile is the server's, and the list can change while the page is open.
|
|
41
|
+
const rd = await dataMod.nextStepProfiles(); profileList = (rd && rd.profiles) || [];
|
|
42
|
+
// Until the PM picks one here, the step starts under the default Claude profile (Settings). 'none' is a choice, sent as null.
|
|
43
|
+
if (u.profile === undefined) u.profile = adoptProfileDefault(rd) || '';
|
|
44
|
+
const out = await dataMod.nextStepPost('prepare', { initiative_id: slug, item_id: it.id, agent: 'claude', profile: u.profile || null, judgment: u.judgment });
|
|
41
45
|
u.loading = false;
|
|
42
46
|
u.plan = out && out.ok ? out : null;
|
|
43
47
|
if (!out || out.ok === false) u.note = { tone: 'bad', text: (out && out.error) || 'could not prepare' };
|
|
@@ -47,7 +51,7 @@ async function go(slug, it) {
|
|
|
47
51
|
const u = slot(it.id); const pl = u.plan;
|
|
48
52
|
if (!pl || !pl.prompt_sha) return;
|
|
49
53
|
u.loading = true; u.note = null; touch();
|
|
50
|
-
const out = await dataMod.nextStepPost('go', { initiative_id: slug, item_id: it.id, agent: 'claude', profile: u.profile ||
|
|
54
|
+
const out = await dataMod.nextStepPost('go', { initiative_id: slug, item_id: it.id, agent: 'claude', profile: u.profile || null, judgment: u.judgment, confirm: true, prompt_sha: pl.prompt_sha });
|
|
51
55
|
u.loading = false;
|
|
52
56
|
if (!out || out.ok === false) { u.note = { tone: 'bad', text: (out && out.error) || 'nothing was started' }; if (out && out.prompt_sha) u.plan = null; touch(); return; }
|
|
53
57
|
u.plan = null; u.note = { tone: 'ok', text: 'started — ' + (out.notice || out.plan.why || 'the session is running') };
|
package/workspace/server.js
CHANGED
|
@@ -462,6 +462,13 @@ function writePrefs(prefs) {
|
|
|
462
462
|
try { fs.writeFileSync(PREFS_FILE, JSON.stringify(prefs)); return null; }
|
|
463
463
|
catch (e) { warnWriteFail('prefs.json (profile preselection)', e); return `the preference could not be saved — ${String((e && e.code) || 'write failed')}`; }
|
|
464
464
|
}
|
|
465
|
+
// The default profile for an agent, for a start the PM pressed that named no profile at all (`undefined`). An explicit
|
|
466
|
+
// null means "no profile" and is never replaced. A remembered id that no longer reads yields undefined: the start then
|
|
467
|
+
// runs with no profile and says nothing it did not do, rather than failing on a preference the PM did not just choose.
|
|
468
|
+
function defaultProfileFor(agent) {
|
|
469
|
+
const id = readPrefs()[agent];
|
|
470
|
+
return typeof id === 'string' && id && resolveProfileForSpawn(id).ok ? id : undefined;
|
|
471
|
+
}
|
|
465
472
|
// The merged environment a session actually runs under. The overlay goes ON TOP of sessionEnv(),
|
|
466
473
|
// AFTER the marker-stripping (R3) — never instead of it, or a profile would silently re-enable the
|
|
467
474
|
// nested-session markers sessionEnv exists to remove.
|
|
@@ -3738,6 +3745,8 @@ function nextStepsFor(w, id) {
|
|
|
3738
3745
|
}
|
|
3739
3746
|
// Everything a prepare shows, computed WITHOUT creating or writing anything. `go` recomputes it and compares the hash.
|
|
3740
3747
|
function prepareNextStep(body) {
|
|
3748
|
+
// A request that names no profile gets the default Claude profile; `profile: null` is the PM choosing none.
|
|
3749
|
+
if (body.profile === undefined) { const d = defaultProfileFor(body.agent || 'claude'); if (d) body = { ...body, profile: d }; }
|
|
3741
3750
|
const w = getWs(body.ws);
|
|
3742
3751
|
if (!w) return { ok: false, status: 400, error: 'no workspace' };
|
|
3743
3752
|
const id = String(body.initiative_id || '');
|
|
@@ -7446,7 +7455,7 @@ async function handleRequest(req, res) {
|
|
|
7446
7455
|
const budget = handoffBudget();
|
|
7447
7456
|
if (!budget.allowed) return json(res, { ok: false, error: budget.reason, budget }, 409);
|
|
7448
7457
|
const started = startWork({ initiative: r.initiative, ws: r.ws, agent: r.agent, name: r.details.session_name,
|
|
7449
|
-
origin: 'plan-item', initialInput: r.prompt + '\r', planItem: r.item });
|
|
7458
|
+
origin: 'plan-item', initialInput: r.prompt + '\r', planItem: r.item, profile: defaultProfileFor(r.agent) });
|
|
7450
7459
|
if (!started.ok) return json(res, { ok: false, error: started.error }, 409);
|
|
7451
7460
|
// The session's token is never projected; the page gets where it runs and the item it is bound to.
|
|
7452
7461
|
return json(res, { ok: true, session: { id: started.session.id, name: started.session.name, ws: started.session.ws, plan_item: started.session.plan_item || null },
|