create-pmos 0.200.0 → 0.201.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/core-documents.md +1 -1
- package/workspace/lib/routes-core-docs.js +6 -11
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.201.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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:15:18Z"}
|
|
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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:15:18Z"}
|
|
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-13T11:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-13T11:15:18Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -45,7 +45,7 @@ A row that is not started always has a next step:
|
|
|
45
45
|
## How PMOS drafts a document
|
|
46
46
|
|
|
47
47
|
- **When you ask.** Press **Draft it** on a row, or **Ask PMOS to change it** on a draft. PMOS starts one background run. The run reads the sources of that document and writes one draft. It has no tool that sends, posts or edits.
|
|
48
|
-
- **On a schedule.** Every 30 minutes inside your working hours, PMOS drafts each portfolio and board document that has no draft and is due, out of date or not started yet. Due documents go first, then out-of-date ones, then the first draft of documents not started. While no OKR files exist, it also proposes the OKRs.
|
|
48
|
+
- **On a schedule.** Every 30 minutes inside your working hours, PMOS drafts each portfolio and board document that has no draft and is due, out of date or not started yet. Due documents go first, then out-of-date ones, then the first draft of documents not started. While no OKR files exist, it also proposes the OKRs. There is no limit on how many drafts run at once. If a run writes nothing, PMOS tries again on the next tick. If you drop a draft, PMOS does not draft that document again until the next day. It never drafts a document that you write (the product strategy).
|
|
49
49
|
- **The Initiative Driver.** When the current stage of an initiative needs a document that is not there or is stale, the driver drafts it and files a proposal. **Keep** issues the draft. The driver does not propose a stage move while a document of the current stage is due.
|
|
50
50
|
|
|
51
51
|
## Issue a draft
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
*
|
|
14
14
|
* THE RUN. A press on Draft it (and the schedule tick) starts ONE headless run, kind `core-doc` (lib/headless.js), origin
|
|
15
15
|
* `core-doc:<scope>:<key>`. Its tools are Read, Glob, Grep and `pmos coredoc write`; the server pins the entry it may write with
|
|
16
|
-
* PMOS_CORE_DOC_SCOPE and PMOS_CORE_DOC_KEY.
|
|
16
|
+
* PMOS_CORE_DOC_SCOPE and PMOS_CORE_DOC_KEY. There is no cap on how many run at once (PM, 2026-10-13: no run limit).
|
|
17
17
|
*
|
|
18
18
|
* THE TICK (PRD section 4). tick(ctx, { now }) runs every 30 minutes inside the working hours (lib/driver-run.js dayCheckOpen: the day-check
|
|
19
19
|
* window and the quiet hours). For each repository (the lead tree) it drafts every `doc` entry of the portfolio and of each board whose cadence
|
|
20
|
-
* has passed (state `due`) and that has no open draft
|
|
20
|
+
* has passed (state `due`), is out of date or is not started, and that has no open draft and no run; never an entry the PM writes (`by: you`). Initiative
|
|
21
21
|
* documents are the Initiative Driver's (lib/driver.js doc-due). ctx adds to the route ctx: { proSettings(), inQuiet(now, quiet), isLead(w) }.
|
|
22
22
|
*/
|
|
23
23
|
const guard = require('./pm-guard.js');
|
|
@@ -27,11 +27,9 @@ const headless = require('./headless.js');
|
|
|
27
27
|
const text = (v) => (typeof v === 'string' ? v : '');
|
|
28
28
|
const bad = (status, error) => ({ status, body: { ok: false, error } });
|
|
29
29
|
const POSTS = ['draft', 'issue', 'drop'];
|
|
30
|
-
const RUN_CAP = 3;
|
|
31
30
|
const TICK_EVERY_MS = 30 * 60 * 1000;
|
|
32
31
|
|
|
33
32
|
const runs = new Map(); // `${ws}|${scope}|${key}` → session id, for the core-doc runs this server started
|
|
34
|
-
const tried = new Map(); // `${ws}|${scope}|${key}` → the local day the tick last started a run for it
|
|
35
33
|
let lastTick = null;
|
|
36
34
|
|
|
37
35
|
const runKey = (ws, scope, key) => `${ws}|${scope}|${key}`;
|
|
@@ -60,7 +58,6 @@ function startRun(ctx, w, scope, entry, { label, now } = {}) {
|
|
|
60
58
|
if (headless.kindFor({ agent: 'claude', origin }) !== 'core-doc') return { ok: false, status: 409, error: 'Background runs are switched off here (PMOS_HEADLESS=off), so PMOS cannot draft this document.' };
|
|
61
59
|
const k = runKey(w.id, scope, entry.key);
|
|
62
60
|
if (runs.has(k)) return { ok: false, status: 409, error: `PMOS is drafting the ${entry.title.toLowerCase()} already` };
|
|
63
|
-
if (runs.size >= RUN_CAP) return { ok: false, status: 409, error: `${RUN_CAP} documents are being drafted already. Try again when one is done.` };
|
|
64
61
|
const prompt = CD.runPrompt(entry, scope, { today: CD.localDay(now == null ? Date.now() : now), label });
|
|
65
62
|
const s = ctx.spawnSession({ name: `Core document · ${entry.title}`, agent: 'claude', ws: w.id, origin, initialInput: prompt + '\r',
|
|
66
63
|
initiative: scope.startsWith('initiative:') ? scope.slice('initiative:'.length) : undefined,
|
|
@@ -90,7 +87,7 @@ function tick(ctx, { now = Date.now(), force = false } = {}) {
|
|
|
90
87
|
const out = [];
|
|
91
88
|
const list = typeof ctx.workspaceList === 'function' ? ctx.workspaceList() : [ctx.getWs(null)].filter(Boolean);
|
|
92
89
|
// Every candidate first, then the most pressing: due (issued, cadence passed), out of date, then not started (the first draft, and the
|
|
93
|
-
// proposed OKRs while no OKR files exist).
|
|
90
|
+
// proposed OKRs while no OKR files exist). No cap: every candidate starts; a failed run is tried again on the next tick.
|
|
94
91
|
const RANK = { due: 0, stale: 1, missing: 2 };
|
|
95
92
|
const todo = [];
|
|
96
93
|
for (const w of list) {
|
|
@@ -107,17 +104,15 @@ function tick(ctx, { now = Date.now(), force = false } = {}) {
|
|
|
107
104
|
const st = CD.stateOf(entry, g.facts);
|
|
108
105
|
if (!(st.st in RANK) || st.draft) continue;
|
|
109
106
|
const k = runKey(w.id, g.facts.scope, entry.key);
|
|
110
|
-
if (runs.has(k)
|
|
107
|
+
if (runs.has(k)) continue;
|
|
111
108
|
const x = g.facts.store.get(`${g.facts.scope}|${entry.key}`);
|
|
112
|
-
if (x && x.drafts.some((d) => CD.localDay(Date.parse(d.at)) === day)) continue; //
|
|
109
|
+
if (x && x.drafts.some((d) => x.drops.has(d.slot) && CD.localDay(Date.parse(d.at)) === day)) continue; // the PM dropped today's draft: not again until tomorrow
|
|
113
110
|
todo.push({ w, g, entry, k, order: [RANK[st.st], li, ei] });
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
todo.sort((a, b) => a.order[0] - b.order[0] || a.order[1] - b.order[1] || a.order[2] - b.order[2]);
|
|
118
115
|
for (const t of todo) {
|
|
119
|
-
if (runs.size >= RUN_CAP) break;
|
|
120
|
-
tried.set(t.k, day);
|
|
121
116
|
const r = startRun(ctx, t.w, t.g.facts.scope, t.entry, { label: labelOf(t.g.facts), now });
|
|
122
117
|
out.push({ ws: t.w.id, scope: t.g.facts.scope, key: t.entry.key, ok: r.ok, ...(r.ok ? { run: r.run } : { error: r.error }) });
|
|
123
118
|
}
|
|
@@ -175,4 +170,4 @@ async function handle(req, res, url, ctx) {
|
|
|
175
170
|
return send({ status: 200, body: { ok: true } });
|
|
176
171
|
}
|
|
177
172
|
|
|
178
|
-
module.exports = { prefixes: ['/api/core-docs'], handle, tick, startRun,
|
|
173
|
+
module.exports = { prefixes: ['/api/core-docs'], handle, tick, startRun, TICK_EVERY_MS, _runs: runs, _reset: () => { runs.clear(); lastTick = null; } };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.201.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.201.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED