create-pmos 0.503.0 → 0.504.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 +14 -14
- 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/changelog.json +13 -0
- package/workspace/lib/transcript-read.js +38 -3
- 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.504.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": {
|
|
@@ -32,6 +32,19 @@
|
|
|
32
32
|
"audit"
|
|
33
33
|
],
|
|
34
34
|
"pmosChanges": [
|
|
35
|
+
{
|
|
36
|
+
"v": "0.504.0",
|
|
37
|
+
"at": "2026-11-03T05:59:07.712Z",
|
|
38
|
+
"f": 3,
|
|
39
|
+
"prs": [
|
|
40
|
+
{
|
|
41
|
+
"n": 1189,
|
|
42
|
+
"t": "The Working card ends when Claude's answer ends",
|
|
43
|
+
"s": "The Working card ends when Claude's answer ends",
|
|
44
|
+
"k": "fix"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
35
48
|
{
|
|
36
49
|
"v": "0.503.0",
|
|
37
50
|
"at": "2026-11-03T05:42:41.752Z",
|
|
@@ -422,19 +435,6 @@
|
|
|
422
435
|
"k": "fix"
|
|
423
436
|
}
|
|
424
437
|
]
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
"v": "0.484.0",
|
|
428
|
-
"at": "2026-11-02T02:00:11.221Z",
|
|
429
|
-
"f": 3,
|
|
430
|
-
"prs": [
|
|
431
|
-
{
|
|
432
|
-
"n": 1143,
|
|
433
|
-
"t": "Program chats get the header pill; a phone shows every PDF page (batch 22 items 17, 18)",
|
|
434
|
-
"s": "Program chats get the header pill; a phone shows every PDF page (batch 22 items 17, 18)",
|
|
435
|
-
"k": "fix"
|
|
436
|
-
}
|
|
437
|
-
]
|
|
438
438
|
}
|
|
439
439
|
]
|
|
440
440
|
}
|
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-11-03T05:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T05:59:04Z"}
|
|
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-11-03T05:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T05:59:04Z"}
|
|
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-11-03T05:
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T05:59:04Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
package/workspace/changelog.json
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "0.504.0",
|
|
4
|
+
"at": "2026-11-03T05:59:07.712Z",
|
|
5
|
+
"f": 3,
|
|
6
|
+
"prs": [
|
|
7
|
+
{
|
|
8
|
+
"n": 1189,
|
|
9
|
+
"t": "The Working card ends when Claude's answer ends",
|
|
10
|
+
"s": "The Working card ends when Claude's answer ends",
|
|
11
|
+
"k": "fix"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
2
15
|
{
|
|
3
16
|
"v": "0.503.0",
|
|
4
17
|
"at": "2026-11-03T05:42:41.752Z",
|
|
@@ -236,9 +236,20 @@ function newHarnessAcc() {
|
|
|
236
236
|
// more. `ai-title` and `attachment` records are CLI bookkeeping and are deliberately not
|
|
237
237
|
// turn-taking, and neither is a SYNTHETIC assistant record: counting one as "the assistant
|
|
238
238
|
// finished speaking" is exactly how a false `needs you` would be manufactured.
|
|
239
|
-
lastRole: null
|
|
239
|
+
lastRole: null, // 'assistant' | 'user' | null
|
|
240
|
+
msgId: null, // the newest real model message's id: a new one closes the older messages' calls (feedHarness)
|
|
241
|
+
cmdFrom: undefined }; // the turn before a /command record, given back when the CLI answers the command itself
|
|
240
242
|
}
|
|
241
243
|
|
|
244
|
+
// The text of a user record, for the turn rules below: string content, or its text blocks joined.
|
|
245
|
+
function userRecordText(um) {
|
|
246
|
+
if (typeof um.content === 'string') return um.content;
|
|
247
|
+
return (Array.isArray(um.content) ? um.content : []).filter((c) => c && c.type === 'text' && typeof c.text === 'string').map((c) => c.text).join('\n');
|
|
248
|
+
}
|
|
249
|
+
const INTERRUPTED = /^\s*\[Request interrupted by user/;
|
|
250
|
+
const LOCAL_OUT = /^\s*<(local-command-stdout|local-command-stderr)>/;
|
|
251
|
+
const LOCAL_IN = /^\s*<(bash-input|bash-stdout|bash-stderr)>|^\s*Caveat: The messages below/;
|
|
252
|
+
|
|
242
253
|
function feedHarness(acc, raw, clean) {
|
|
243
254
|
for (const line of raw.split('\n')) {
|
|
244
255
|
if (!line) continue;
|
|
@@ -253,13 +264,27 @@ function feedHarness(acc, raw, clean) {
|
|
|
253
264
|
}
|
|
254
265
|
// tool_result blocks live inside `user` records; harvest the ids they resolve.
|
|
255
266
|
if (r.type === 'user') {
|
|
267
|
+
if (r.isSidechain) continue; // a subagent's own records: its calls and results never hold the main session's turn
|
|
256
268
|
const um = r.message || {};
|
|
269
|
+
let result = false;
|
|
257
270
|
for (const c of (Array.isArray(um.content) ? um.content : [])) {
|
|
258
271
|
if (c && c.type === 'tool_result' && c.tool_use_id) {
|
|
272
|
+
result = true;
|
|
259
273
|
if (!acc.openUse.delete(c.tool_use_id)) acc.resolved.add(c.tool_use_id);
|
|
260
274
|
}
|
|
261
275
|
}
|
|
262
|
-
|
|
276
|
+
const said = result ? '' : userRecordText(um);
|
|
277
|
+
// batch 25 item 15: only a prompt or a tool result gives the model the turn. The CLI's own records after a finished
|
|
278
|
+
// answer (a meta note, a compact summary, a local command such as /model and its output, a `!` shell line) start no
|
|
279
|
+
// model turn, so counting them left the chat on "Working" for hours after Claude had answered.
|
|
280
|
+
if (result) acc.lastRole = 'user';
|
|
281
|
+
else if (INTERRUPTED.test(said)) { acc.lastRole = 'assistant'; acc.openUse.clear(); } // Esc / Stop: the model stopped, the PM is up
|
|
282
|
+
else if (LOCAL_OUT.test(said)) { if (acc.cmdFrom !== undefined) acc.lastRole = acc.cmdFrom; acc.cmdFrom = undefined; } // a local command answered itself
|
|
283
|
+
else if (r.isMeta || r.isCompactSummary || r.isVisibleInTranscriptOnly || LOCAL_IN.test(said)) { /* bookkeeping: not turn-taking */ }
|
|
284
|
+
else {
|
|
285
|
+
if (/<command-name>/.test(said)) acc.cmdFrom = acc.lastRole; // /name: a prompt command takes the turn; a local one gives it back above
|
|
286
|
+
acc.lastRole = 'user'; // a prompt was submitted
|
|
287
|
+
}
|
|
263
288
|
continue;
|
|
264
289
|
}
|
|
265
290
|
if (r.type === 'attachment') {
|
|
@@ -274,6 +299,13 @@ function feedHarness(acc, raw, clean) {
|
|
|
274
299
|
}
|
|
275
300
|
if (r.type !== 'assistant') continue;
|
|
276
301
|
const m = r.message || {};
|
|
302
|
+
if (m.model && m.model !== SYNTHETIC && !r.isSidechain && m.id && m.id !== acc.msgId) {
|
|
303
|
+
// A new model message starts only once every call of the one before it has its result: the model cannot go on without
|
|
304
|
+
// them. So a call of an older message that is still unresolved is a phantom (a crash, a killed pane, a resumed chat), never
|
|
305
|
+
// a call in flight, and it must not hold the turn (batch 25 item 15: a chat showed "Working · 169:28" under its answer).
|
|
306
|
+
for (const [id, info] of acc.openUse) if (info.msg !== m.id) acc.openUse.delete(id);
|
|
307
|
+
acc.msgId = m.id;
|
|
308
|
+
}
|
|
277
309
|
if (m.model && m.model !== SYNTHETIC) {
|
|
278
310
|
acc.model = clean(m.model);
|
|
279
311
|
acc.turns++; // only real model turns count
|
|
@@ -298,7 +330,7 @@ function feedHarness(acc, raw, clean) {
|
|
|
298
330
|
const name = clean(prettyTool(c.name));
|
|
299
331
|
acc.toolCounts[name] = (acc.toolCounts[name] || 0) + 1;
|
|
300
332
|
acc.toolTotal++;
|
|
301
|
-
if (c.id && !acc.resolved.delete(c.id)) acc.openUse.set(c.id, { verb: name, ts: r.timestamp || null });
|
|
333
|
+
if (c.id && !r.isSidechain && !acc.resolved.delete(c.id)) acc.openUse.set(c.id, { verb: name, ts: r.timestamp || null, msg: m.id || null });
|
|
302
334
|
}
|
|
303
335
|
}
|
|
304
336
|
}
|
|
@@ -320,6 +352,9 @@ function harnessOf(acc) {
|
|
|
320
352
|
// the strong `needs you` claim can be built) is UNREACHABLE for it. Not a guard that rejects
|
|
321
353
|
// the phantom: a value it cannot construct. Reordering these branches silently converts a
|
|
322
354
|
// corpse into "waiting on you", which is the one lie this surface must not tell.
|
|
355
|
+
// A phantom stays only while nothing came after it: once a NEWER model message exists, the session demonstrably went
|
|
356
|
+
// on past that call, so feedHarness drops it (batch 25 item 15). A crash with the call as its newest record still lands
|
|
357
|
+
// on `tool`, exactly as above.
|
|
323
358
|
if (out.openCall) out.turn = 'tool'; // awaiting a tool — OR the PM's approval of one
|
|
324
359
|
else if (acc.lastRole === 'assistant') out.turn = 'user'; // the model stopped; the human is up
|
|
325
360
|
else if (acc.lastRole === 'user') out.turn = 'agent'; // a prompt/result landed; the model is up
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.504.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.504.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@anthropic-ai/sdk": "^1.3.0",
|
package/workspace/package.json
CHANGED