create-pmos 0.505.0 → 0.506.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 +32 -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 +31 -0
- package/workspace/fixtures/decision-pairs.js +94 -0
- package/workspace/guide/ask-the-past.md +46 -0
- package/workspace/guide/claude-proposes.md +29 -2
- package/workspace/guide/index.md +2 -0
- package/workspace/guide/what-you-missed.md +42 -0
- package/workspace/lib/ai-cli.js +63 -0
- package/workspace/lib/ai-guard.js +314 -0
- package/workspace/lib/briefing-premium-agent.js +3 -0
- package/workspace/lib/decision-ledger.js +236 -0
- package/workspace/lib/decision-memory.js +237 -0
- package/workspace/lib/drift-cli.js +98 -0
- package/workspace/lib/drift-facts.js +151 -0
- package/workspace/lib/drift-runs.js +149 -0
- package/workspace/lib/drift.js +227 -0
- package/workspace/lib/grill-cli.js +22 -1
- package/workspace/lib/grill-runs.js +20 -3
- package/workspace/lib/grill.js +15 -8
- package/workspace/lib/past-chat.js +32 -0
- package/workspace/lib/past-cli.js +147 -0
- package/workspace/lib/past-repeat.js +126 -0
- package/workspace/lib/past.js +353 -0
- package/workspace/lib/pmos-verbs.js +9 -0
- package/workspace/lib/proposal-runs.js +20 -0
- package/workspace/lib/route-modules.js +1 -0
- package/workspace/lib/routes-drift.js +62 -0
- package/workspace/lib/settings-store.js +6 -0
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/grill-words.js +4 -2
- package/workspace/public/pm/home-app.js +14 -2
- package/workspace/public/pm/home-drift.js +76 -0
- package/workspace/server.js +19 -0
- package/workspace/skills/grill.skill +4 -2
- package/workspace/test-files.json +1 -1
- package/workspace/test-lists/ask-the-past.json +5 -0
- package/workspace/test-lists/decision-memory.json +6 -0
- package/workspace/test-lists/weekly-drift-check.json +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.506.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,37 @@
|
|
|
32
32
|
"audit"
|
|
33
33
|
],
|
|
34
34
|
"pmosChanges": [
|
|
35
|
+
{
|
|
36
|
+
"v": "0.506.0",
|
|
37
|
+
"at": "2026-11-03T12:09:23.758Z",
|
|
38
|
+
"f": 3,
|
|
39
|
+
"prs": [
|
|
40
|
+
{
|
|
41
|
+
"n": null,
|
|
42
|
+
"t": "Ai-guard, one guard for every AI job (#1191) [skip publish]",
|
|
43
|
+
"s": "Ai-guard, one guard for every AI job (#1191) [skip publish]",
|
|
44
|
+
"k": "new"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"n": null,
|
|
48
|
+
"t": "Decision memory, the grill's earlier-decision angle (#1193) [skip publish]",
|
|
49
|
+
"s": "Decision memory, the grill's earlier-decision angle (#1193) [skip publish]",
|
|
50
|
+
"k": "new"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"n": null,
|
|
54
|
+
"t": "Ask PMOS about the past, with the record behind every answer (#1195) [skip publish]",
|
|
55
|
+
"s": "Ask PMOS about the past, with the record behind every answer (#1195) [skip publish]",
|
|
56
|
+
"k": "new"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"n": 1192,
|
|
60
|
+
"t": "What would I have missed, a weekly check for quiet drift",
|
|
61
|
+
"s": "What would I have missed, a weekly check for quiet drift",
|
|
62
|
+
"k": "new"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
35
66
|
{
|
|
36
67
|
"v": "0.505.0",
|
|
37
68
|
"at": "2026-11-03T10:44:31.649Z",
|
|
@@ -422,19 +453,6 @@
|
|
|
422
453
|
"k": "new"
|
|
423
454
|
}
|
|
424
455
|
]
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
"v": "0.486.0",
|
|
428
|
-
"at": "2026-11-02T03:54:59.832Z",
|
|
429
|
-
"f": 3,
|
|
430
|
-
"prs": [
|
|
431
|
-
{
|
|
432
|
-
"n": 1146,
|
|
433
|
-
"t": "An initiative owns its tasks; the Board reads them (D104, batch 22 item 21)",
|
|
434
|
-
"s": "An initiative owns its tasks; the Board reads them",
|
|
435
|
-
"k": "new"
|
|
436
|
-
}
|
|
437
|
-
]
|
|
438
456
|
}
|
|
439
457
|
]
|
|
440
458
|
}
|
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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T12:09:20Z"}
|
|
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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T12:09:20Z"}
|
|
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-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-11-03T12:09:20Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
package/workspace/changelog.json
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "0.506.0",
|
|
4
|
+
"at": "2026-11-03T12:09:23.758Z",
|
|
5
|
+
"f": 3,
|
|
6
|
+
"prs": [
|
|
7
|
+
{
|
|
8
|
+
"n": null,
|
|
9
|
+
"t": "Ai-guard, one guard for every AI job (#1191) [skip publish]",
|
|
10
|
+
"s": "Ai-guard, one guard for every AI job (#1191) [skip publish]",
|
|
11
|
+
"k": "new"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"n": null,
|
|
15
|
+
"t": "Decision memory, the grill's earlier-decision angle (#1193) [skip publish]",
|
|
16
|
+
"s": "Decision memory, the grill's earlier-decision angle (#1193) [skip publish]",
|
|
17
|
+
"k": "new"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"n": null,
|
|
21
|
+
"t": "Ask PMOS about the past, with the record behind every answer (#1195) [skip publish]",
|
|
22
|
+
"s": "Ask PMOS about the past, with the record behind every answer (#1195) [skip publish]",
|
|
23
|
+
"k": "new"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"n": 1192,
|
|
27
|
+
"t": "What would I have missed, a weekly check for quiet drift",
|
|
28
|
+
"s": "What would I have missed, a weekly check for quiet drift",
|
|
29
|
+
"k": "new"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
2
33
|
{
|
|
3
34
|
"v": "0.505.0",
|
|
4
35
|
"at": "2026-11-03T10:44:31.649Z",
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* fixtures/decision-pairs.js — The real supersede pairs in DECISIONS.md, read by hand on 2026-11-03 (decision memory). decision-memory.test.js checks the ledger finds exactly these, and lib/decision-memory.js replays them before any finding is shown. Add a pair here when a new decision supersedes an old one. */
|
|
2
|
+
'use strict';
|
|
3
|
+
module.exports = {
|
|
4
|
+
"reverted": [
|
|
5
|
+
"D29"
|
|
6
|
+
],
|
|
7
|
+
"pairs": [
|
|
8
|
+
{
|
|
9
|
+
"newer": "D40",
|
|
10
|
+
"older": "D20",
|
|
11
|
+
"where": "DECISIONS.md:83"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"newer": "D43",
|
|
15
|
+
"older": "D27",
|
|
16
|
+
"where": "DECISIONS.md:173"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"newer": "D64",
|
|
20
|
+
"older": "D26",
|
|
21
|
+
"where": "DECISIONS.md:237"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"newer": "D64",
|
|
25
|
+
"older": "D24",
|
|
26
|
+
"where": "DECISIONS.md:237"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"newer": "D64",
|
|
30
|
+
"older": "D25",
|
|
31
|
+
"where": "DECISIONS.md:237"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"newer": "D64",
|
|
35
|
+
"older": "D43",
|
|
36
|
+
"where": "DECISIONS.md:237"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"newer": "D66",
|
|
40
|
+
"older": "D46",
|
|
41
|
+
"where": "DECISIONS.md:243"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"newer": "D66",
|
|
45
|
+
"older": "D50",
|
|
46
|
+
"where": "DECISIONS.md:243"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"newer": "D66",
|
|
50
|
+
"older": "D37",
|
|
51
|
+
"where": "DECISIONS.md:243"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"newer": "D66",
|
|
55
|
+
"older": "D33",
|
|
56
|
+
"where": "DECISIONS.md:243"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"newer": "D66",
|
|
60
|
+
"older": "D53",
|
|
61
|
+
"where": "DECISIONS.md:243"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"newer": "D66",
|
|
65
|
+
"older": "D24",
|
|
66
|
+
"where": "DECISIONS.md:243"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"newer": "D66",
|
|
70
|
+
"older": "D25",
|
|
71
|
+
"where": "DECISIONS.md:243"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"newer": "D101",
|
|
75
|
+
"older": "D79",
|
|
76
|
+
"where": "DECISIONS.md:353"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"newer": "D101",
|
|
80
|
+
"older": "D69",
|
|
81
|
+
"where": "DECISIONS.md:353"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"newer": "D101",
|
|
85
|
+
"older": "D70",
|
|
86
|
+
"where": "DECISIONS.md:353"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"newer": "D101",
|
|
90
|
+
"older": "D71",
|
|
91
|
+
"where": "DECISIONS.md:353"
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Guide
|
|
3
|
+
title: "Ask about the past: why something was decided or dropped, with the record that says so"
|
|
4
|
+
timestamp: 2026-11-03
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Ask about the past
|
|
8
|
+
|
|
9
|
+
Ask in the initiative chat. There is no search box and no button.
|
|
10
|
+
|
|
11
|
+
- "Why did we drop the hosted backend?"
|
|
12
|
+
- "Did we ever decide on a graph store?"
|
|
13
|
+
- "What did we decide about Now, Next and Later?"
|
|
14
|
+
|
|
15
|
+
Claude answers from the records PMOS keeps, never from memory. Each claim has the file and line it rests on, for example `DECISIONS.md:243`. When no record answers the question, Claude says **No record found** and names what it read. It does not guess a reason.
|
|
16
|
+
|
|
17
|
+
A decision that a later one replaced is marked as superseded, with the decision that replaced it.
|
|
18
|
+
|
|
19
|
+
## What it reads
|
|
20
|
+
|
|
21
|
+
- `DECISIONS.md`: each decision and each line of the amendment log
|
|
22
|
+
- the decision records in `okf/products/pmos/adr/`
|
|
23
|
+
- `pm-decisions.md`, the PM journal
|
|
24
|
+
- `planning/out-of-scope/`, the requests that were declined
|
|
25
|
+
- `planning/initiatives/`, each initiative record and its status
|
|
26
|
+
- `discoveries.md`, the run log (it counts less)
|
|
27
|
+
- the decisions in your meeting notes, except a point you marked not right or deleted. A private note is never read.
|
|
28
|
+
|
|
29
|
+
It does not read chat transcripts or Jira tickets, because PMOS keeps no searchable copy of them on your machine. It says so in each answer.
|
|
30
|
+
|
|
31
|
+
## You decided this before
|
|
32
|
+
|
|
33
|
+
When you add an initiative that repeats something decided or declined before, one finding waits under the initiative's ✦. It quotes the earlier record and its line. The next step is to say what is different this time. Keep it to add that step as a task, or drop it. Nothing changes until you keep it. When nothing repeats, nothing shows.
|
|
34
|
+
|
|
35
|
+
It goes through the same guardrail as every AI job: every quote is checked at its line, it is tested on known cases before anything shows, and every run is in the audit. `pmos ai off past-repeat` turns it off.
|
|
36
|
+
|
|
37
|
+
## From a terminal
|
|
38
|
+
|
|
39
|
+
| Command | What it does |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `pmos past ask "<question>"` | The records that answer the question, each with its path:line and its own words, and how sure the match is. "No record found" when none does. `--json` for a script. |
|
|
42
|
+
| `pmos past check "<idea>"` | What was decided or declined before about an idea. |
|
|
43
|
+
| `pmos past verify --text "<answer>"` | Checks that every path:line in an answer is a record PMOS read, at a line that exists. |
|
|
44
|
+
| `pmos past sources` | Which records were read, and which were not on this machine. |
|
|
45
|
+
|
|
46
|
+
Nothing here writes a record, sends anything or calls a model.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Guide
|
|
3
3
|
title: "Claude proposes: the one ✦ on each initiative"
|
|
4
4
|
description: "What Claude finds when you add an initiative that already lives elsewhere, the new dates, done and tidy names it proposes for late tasks, the clean-up of the work that is not in an initiative, how you keep or drop them in the Viewer, Undo, the pmos propose commands, and how Claude grills an initiative by itself (pmos grill)."
|
|
5
|
-
timestamp: 2026-11-
|
|
5
|
+
timestamp: 2026-11-03
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Claude proposes: the one ✦ on each initiative
|
|
@@ -64,14 +64,23 @@ Claude also tests an initiative without being asked. There is no Grill button an
|
|
|
64
64
|
- before it leaves a stage (the stage has one open task or none left),
|
|
65
65
|
- when its forecast turns at risk or will miss,
|
|
66
66
|
- when its scope or dates move a lot (30% more or fewer tasks, or the end moves 14 days or more),
|
|
67
|
+
- when its PRD changes (the first look only notes the PRD; a later change starts a run),
|
|
67
68
|
- once a month, every running initiative that has open tasks: the ones with late work first, then the ones it grilled longest ago. Each one at most once in 30 days, and only while the monthly credit lasts.
|
|
68
69
|
|
|
69
70
|
You can also start one any time: in the initiative's chat, write "grill this" (or "grill it"). The run starts at once in the background, and the chat says so in one line. If it cannot start, for example because another grill is running or this month's credit is spent, the chat says why. The findings arrive under the ✦ as for the other runs.
|
|
70
71
|
|
|
71
|
-
Each finding is a proposal in the group "Claude grilled it", under the same ✦. Each row shows the mark and the name of the angle that found it: Premortem, Red team, Voices, Reframe, Scope
|
|
72
|
+
Each finding is a proposal in the group "Claude grilled it", under the same ✦. Each row shows the mark and the name of the angle that found it: Premortem, Red team, Voices, Reframe, Scope, What-if or Earlier decision. Voices are simulated from your stored research and meeting notes, only with 3 sources or more, and carry the tag "Simulated, not evidence". A What-if carries "Simulated, not the plan". Each finding ends with one next step. ✓ adds that step as a task. ✎ lets you write the step in your own words first; ✓ then adds your words. ✕ drops the finding. A finding never rides on the header's ✓. Above the findings, one quiet line names the angles Claude chose, when and why it ran, and what the run cost. Three findings show at a time; "+N smaller findings" and its ⋯ show the rest. On a phone the findings are cards side by side: swipe for the next. With no findings, nothing shows.
|
|
72
73
|
|
|
73
74
|
When Claude grilled an initiative this week and left findings, Home says so in one line under "Good morning", and its ✦ opens the findings. When it grilled more than one, the line names the newest and says how many more, for example "I grilled Inline login and 5 more this week: 21 findings." The others' findings are under each initiative's own ✦. When a key result will miss its goal, or drifted to at risk, Intelligence's ✦ line names it and the initiative Claude grilled for it; its ✦ opens those findings.
|
|
74
75
|
|
|
76
|
+
### Earlier decision: Claude remembers what you decided
|
|
77
|
+
|
|
78
|
+
On every run Claude checks the plan and the PRD against the decisions that still stand in DECISIONS.md and the ADRs. When the plan goes against one, the finding quotes the decision and the plan word for word, says which file and line each is on, and suggests one of three answers: keep the decision and change the plan, change the decision with a new one that amends it, or drop it with a new one that supersedes it. It never blocks anything.
|
|
79
|
+
|
|
80
|
+
Claude never pushes back with a decision that a later one replaced: such a finding is refused, and the refusal names the decision that replaced it. A quote that is not word for word is refused, and so is a guess (low confidence). Nothing shows until a replay of the real "this replaces that" pairs in DECISIONS.md passes. `PMOS_DECISION_MEMORY=off` or `pmos ai off decision-memory` turns this angle off.
|
|
81
|
+
|
|
82
|
+
- `pmos grill decisions [--all]`: the decisions that stand, one line each with its file and line. With `--all`, also the superseded and reverted ones and what replaced them.
|
|
83
|
+
|
|
75
84
|
Every run counts against a monthly credit cap. A run starts only when the cap holds its whole budget, and it stops at that budget, so the month never goes past the cap. At the cap Claude pauses until the next month.
|
|
76
85
|
|
|
77
86
|
Set when Claude grills, and how much it may spend, in **Settings › Claude's checks** (see the Settings guide), or with these commands:
|
|
@@ -83,5 +92,23 @@ Set when Claude grills, and how much it may spend, in **Settings › Claude's ch
|
|
|
83
92
|
Claude's grill run files with these commands, which refuse outside that run:
|
|
84
93
|
|
|
85
94
|
- `pmos grill find <premortem|redteam|voices|reframe|scope|whatif> --json <file|->`: one finding, with its sources and next step.
|
|
95
|
+
- `pmos grill find decision --json <file|->`: a plan that goes against an earlier decision, with both quotes, keep, change or drop, and the next step.
|
|
86
96
|
- `pmos grill voices --sources <n>`: how many stored sources Voices can use.
|
|
87
97
|
- `pmos grill status`: what is open, kept and dropped.
|
|
98
|
+
|
|
99
|
+
## The guard on every AI job
|
|
100
|
+
|
|
101
|
+
Decision memory, the weekly what-I'd-miss check, ask about the past and the other AI jobs run in your usual Claude session. What they find goes through one guard before you see it:
|
|
102
|
+
|
|
103
|
+
- **Proposals only.** A job files a proposal under ✦. It writes no task, document or decision. Your ✓ does.
|
|
104
|
+
- **Every claim cites.** Each claim names a file and a line, and quotes it. The guard reads that line. A quote that is not there drops the proposal.
|
|
105
|
+
- **Honest confidence.** High needs two sources or more. "No record" is a valid answer.
|
|
106
|
+
- **Replay first.** A job shows nothing until its replay cases pass. Those cases include fabricated quotes that the guard must drop.
|
|
107
|
+
- **Kill switch and audit.** Every filed, dropped and held proposal is a line in the audit, with the reason.
|
|
108
|
+
|
|
109
|
+
The commands:
|
|
110
|
+
|
|
111
|
+
- `pmos ai status`: whether each job is on, whether its replay passed, and what its last run filed.
|
|
112
|
+
- `pmos ai off` or `pmos ai off <job>`: every AI job off, or one job. `PMOS_AI=off` in the environment wins.
|
|
113
|
+
- `pmos ai on` or `pmos ai on <job>`: on again.
|
|
114
|
+
- `pmos ai log`: the last audit lines. Each drop shows its reason.
|
package/workspace/guide/index.md
CHANGED
|
@@ -63,12 +63,14 @@ On a desktop the workspace is one frame. [Layout](layout.md) explains each part.
|
|
|
63
63
|
- [Present while a meeting records](present-in-a-meeting.md): Present in the recording tab, the audience tab, the presenter view, and presenting a window.
|
|
64
64
|
- [Notes](notes.md): listen to a meeting on this machine, see decisions, actions and questions caught and checked against the repository, and get a summary.
|
|
65
65
|
- [Find knowledge without reading whole files](knowledge-graph.md): what `pmos kg` finds, its commands, how to read its numbers, and its limits.
|
|
66
|
+
- [Ask about the past](ask-the-past.md): why something was decided or dropped, answered in the initiative chat from the records, with the line each claim rests on; "You decided this before" on a new initiative.
|
|
66
67
|
- [Initiatives: the Roadmap, the List and the initiative sheet](initiatives-screen.md): how to read and order the initiatives of a repository, open the sheet, make a new initiative, and review the cycle.
|
|
67
68
|
- [Initiatives and the Roadmap: one ranked list](initiatives-roadmap.md): what day one shows, what happened to Now, Next and Later, and `pmos initiative` and `pmos measure` from a terminal.
|
|
68
69
|
- [The Initiative Driver: drafts the agent files for you](initiative-driver.md): when the driver runs, the unblock sweep, the limits, Keep, Send back and Drop, the board modes, and `pmos driver`.
|
|
69
70
|
- [Claude proposes: the one ✦ on each initiative](claude-proposes.md): what Claude finds when you add an initiative, new dates, done and tidy names for late tasks, ✓, ✕, Undo, and `pmos propose`.
|
|
70
71
|
- [Claude drafts metrics without being asked](metric-drafts.md): when Claude drafts the metrics of a product, a program or an initiative, keep, drop, Undo, and `pmos metrics draft`.
|
|
71
72
|
- [Your impact](your-impact.md): what counts as your impact, the weekly check in Home's chat, the switch, and `pmos impact`. Private to you.
|
|
73
|
+
- [What you might have missed](what-you-missed.md): the weekly check for quiet drift, at most three items in Home's chat, its replay, and `pmos drift`.
|
|
72
74
|
- [Adler, Claude's face](adler.md): who Adler is, where he shows, what his six moods mean, and Settings › Adler.
|
|
73
75
|
- [Ready-made dashboards and reports](ready-made-dashboards.md): the dashboard and reports every program, product and initiative has, the Work | Dashboard icon, the Sponsors and Team cuts, late and held reports.
|
|
74
76
|
- [Core documents: what each level keeps](core-documents.md): the core documents of the portfolio, a board and an initiative, their states, how PMOS drafts them, Issue it, and `pmos coredoc write`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Guide
|
|
3
|
+
title: "What you might have missed"
|
|
4
|
+
description: "The weekly check for quiet drift: what it looks for, when it says nothing, how to drop an item, the replay that comes first, how to switch it off, and the pmos drift commands."
|
|
5
|
+
timestamp: 2026-11-03
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# What you might have missed
|
|
9
|
+
|
|
10
|
+
Once a week PMOS looks across your products for work that looks fine on the surface but has quietly drifted. It shows at most three items, as one ✦ in Home's chat. In a quiet week it says nothing.
|
|
11
|
+
|
|
12
|
+
## What it looks for
|
|
13
|
+
|
|
14
|
+
It reads only records. It does not read chats or meetings, and it uses no model, so it costs no credits.
|
|
15
|
+
|
|
16
|
+
- **Gone quiet.** An initiative that is still live and has open tasks, but no task and no record has changed for 14 days.
|
|
17
|
+
- **Slipped again.** An open task whose due date moved later at least twice, with the last move in the week it checks. A milestone comes first.
|
|
18
|
+
- **Jira and PMOS disagree.** The initiative is closed but one of its Jira tickets is still open. Or every Jira ticket was resolved at least 7 days ago and the initiative is still open.
|
|
19
|
+
|
|
20
|
+
Each item shows the records it came from: the task, the dates and when they moved, the Jira key and its status. The facts are read from records. Whether they matter is for you to judge.
|
|
21
|
+
|
|
22
|
+
## When it runs
|
|
23
|
+
|
|
24
|
+
It runs by itself each Monday, inside your day-check hours, for the week before. You never start it. The card stays in Home's chat for the week.
|
|
25
|
+
|
|
26
|
+
## Drop an item
|
|
27
|
+
|
|
28
|
+
Open ⋯ on an item and choose **Not right, drop it**. A dropped item never comes back. Undo brings it back. An item you have already seen comes back only when it gets worse: another slip, two more quiet weeks, or more open tickets.
|
|
29
|
+
|
|
30
|
+
## The replay comes first
|
|
31
|
+
|
|
32
|
+
Nothing shows for a product until its replay has passed. In the product's repository, run `pmos drift replay`. It runs the check on each of the last four weeks of real records, checks that no week has more than three items, and checks that every quote is at the line it cites. The shared guard then runs its own replay.
|
|
33
|
+
|
|
34
|
+
## Switch it off
|
|
35
|
+
|
|
36
|
+
Set `PMOS_DRIFT=off`, or turn Claude's checks off with `pmos ai off drift`. Every result, drop, undo and replay is a line in your own ledger, `drift/drift.jsonl` in the runtime folder. Only you see it. Nothing leaves PMOS, and nothing changes a task, an initiative or a Jira ticket.
|
|
37
|
+
|
|
38
|
+
## Commands
|
|
39
|
+
|
|
40
|
+
- `pmos drift show [--weeks <n>]`: what each of the last weeks would have shown for this repository. It writes nothing.
|
|
41
|
+
- `pmos drift replay`: the replay of the last four weeks of this repository.
|
|
42
|
+
- `pmos drift status`: the last weekly result and the replays on record.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* ai-cli.js — `pmos ai`: the kill switch and the audit of the AI jobs that file through lib/ai-guard.js.
|
|
3
|
+
*
|
|
4
|
+
* pmos ai status [--json] the switch, each job's replay state and its last run
|
|
5
|
+
* pmos ai off [<job>] turn every AI job off, or one job
|
|
6
|
+
* pmos ai on [<job>] turn every AI job on again, or one job
|
|
7
|
+
* pmos ai log [<job>] [--n N] the last audit lines: filed, dropped (with why), held, off, replay
|
|
8
|
+
*
|
|
9
|
+
* A background run never changes the switch: inside one (PMOS_AI_RUN set) off and on refuse. PMOS_AI=off in the environment wins
|
|
10
|
+
* over Settings. Exit codes: 0 done, 1 refused, 2 usage. Nothing is sent. */
|
|
11
|
+
const AG = require('./ai-guard.js');
|
|
12
|
+
|
|
13
|
+
const COMMANDS = { ai: ['status', 'off', 'on', 'log'] };
|
|
14
|
+
const USAGE = [
|
|
15
|
+
'usage: pmos ai status|off|on|log — the AI jobs: their kill switch and what each one filed or dropped',
|
|
16
|
+
' pmos ai status [--json] is each job on, has its replay passed, what did its last run file',
|
|
17
|
+
' pmos ai off [<job>] every AI job off, or one job',
|
|
18
|
+
' pmos ai on [<job>] every AI job on again, or one job',
|
|
19
|
+
' pmos ai log [<job>] [--n N] the last audit lines',
|
|
20
|
+
'A job files only proposals. Each one cites its sources and waits under ✦ for your ✓. Nothing is sent.',
|
|
21
|
+
];
|
|
22
|
+
const flag = (args, k) => { const i = args.indexOf('--' + k); return i >= 0 ? (args[i + 1] === undefined || args[i + 1].startsWith('--') ? true : args[i + 1]) : undefined; };
|
|
23
|
+
const stateOf = (env) => require('./state-root.js').defaultRoot({ env });
|
|
24
|
+
|
|
25
|
+
function run(argv, { say = (s) => console.log(s), env = process.env, stateDir = null } = {}) {
|
|
26
|
+
const args = argv[0] === 'ai' ? argv.slice(1) : argv.slice();
|
|
27
|
+
const verb = args[0];
|
|
28
|
+
if (!verb || ['help', '--help', '-h'].includes(verb)) { for (const l of USAGE) say(l); return verb ? 0 : 1; }
|
|
29
|
+
if (!COMMANDS.ai.includes(verb)) { say(`unknown ai command "${verb}" — one of ${COMMANDS.ai.join(', ')}`); return 2; }
|
|
30
|
+
const dir = stateDir || stateOf(env);
|
|
31
|
+
const job = args[1] && !args[1].startsWith('--') ? args[1] : null;
|
|
32
|
+
|
|
33
|
+
if (verb === 'status') {
|
|
34
|
+
const s = AG.status({ stateDir: dir, settingsDir: dir, env });
|
|
35
|
+
if (flag(args, 'json')) { say(JSON.stringify(s)); return 0; }
|
|
36
|
+
say(`AI jobs: ${s.on ? 'on' : 'off'}${s.settingsOff.length ? ' · off one by one: ' + s.settingsOff.join(', ') : ''}`);
|
|
37
|
+
if (!s.jobs.length) say(' no job has run yet');
|
|
38
|
+
for (const j of s.jobs) {
|
|
39
|
+
const rep = j.replay ? `replay v${j.replay.version} ${j.replay.ok ? 'passed' : 'FAILED'}` : 'no replay yet: everything is held';
|
|
40
|
+
const last = j.last ? ` · last run ${String(j.last.at).slice(0, 16).replace('T', ' ')}: ${j.last.filed} filed, ${j.last.dropped} dropped` : '';
|
|
41
|
+
say(` ${j.job}: ${j.off ? 'off' : 'on'} · ${rep}${last}`);
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
if (verb === 'log') {
|
|
46
|
+
const n = Math.min(500, Math.max(1, Number(flag(args, 'n')) || 20));
|
|
47
|
+
const lines = AG.readAudit(dir, { job, limit: n });
|
|
48
|
+
if (!lines.length) { say('no audit lines yet'); return 0; }
|
|
49
|
+
for (const l of lines) {
|
|
50
|
+
const { at, job: j, event, ...rest } = l;
|
|
51
|
+
say(`${String(at).slice(0, 19).replace('T', ' ')} ${j || '-'} ${event} ${JSON.stringify(rest)}`);
|
|
52
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (env.PMOS_AI_RUN) { say('✗ an AI run never changes its own switch'); return 1; }
|
|
56
|
+
const r = AG.setOff(dir, job, verb === 'off');
|
|
57
|
+
if (!r || !r.ok) { say('✗ ' + ((r && r.error) || 'could not save')); return 1; }
|
|
58
|
+
const envWins = verb === 'on' && AG.off(job, { env, settingsDir: null });
|
|
59
|
+
say(`${job || 'every AI job'}: ${verb}${envWins ? ' in Settings, but ' + envWins + ' wins' : ''}`);
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { run, COMMANDS, USAGE };
|