create-pmos 0.59.3 → 0.60.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.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/payload/KIT-VERSION +1 -1
  3. package/payload/planning/evals/eval-calibration.md +1 -1
  4. package/payload/planning/okrs/health-budgets.md +1 -1
  5. package/payload/scripts/delivery-index.js +85 -7
  6. package/payload/scripts/workflow-state.js +3 -3
  7. package/payload/state/discoveries.md +1 -1
  8. package/workspace/fixtures/initiatives-api/sheet.json +29 -7
  9. package/workspace/guide/index.md +3 -3
  10. package/workspace/guide/initiatives-screen.md +25 -1
  11. package/workspace/guide/layout.md +6 -6
  12. package/workspace/guide/proactive-engine.md +1 -0
  13. package/workspace/guide/today.md +23 -1
  14. package/workspace/lib/calendar-memory.js +257 -0
  15. package/workspace/lib/console-state.js +1 -1
  16. package/workspace/lib/doc-category.js +3 -1
  17. package/workspace/lib/engine/delivery-index.js +85 -7
  18. package/workspace/lib/engine/workflow-state.js +3 -3
  19. package/workspace/lib/initiative-files.js +59 -1
  20. package/workspace/lib/initiative-rows.js +14 -2
  21. package/workspace/lib/mobile-nav.js +1 -1
  22. package/workspace/lib/plan-tree.js +44 -5
  23. package/workspace/lib/proactive-cli.js +16 -1
  24. package/workspace/lib/routes-initiatives.js +165 -9
  25. package/workspace/package-lock.json +1 -1
  26. package/workspace/package.json +1 -1
  27. package/workspace/public/index.html +1 -1
  28. package/workspace/public/pm/components.css +70 -0
  29. package/workspace/public/pm/dest-initiatives.js +7 -1
  30. package/workspace/public/pm/frame-copy.js +2 -2
  31. package/workspace/public/pm/initiative-sheet.js +42 -10
  32. package/workspace/public/pm/initiatives-api.js +15 -0
  33. package/workspace/public/pm/initiatives-copy.js +13 -0
  34. package/workspace/public/pm/initiatives-ui.js +14 -0
  35. package/workspace/public/pm/registry.js +1 -1
  36. package/workspace/public/pm/today-agenda.js +305 -0
  37. package/workspace/public/pm/today-copy.js +54 -2
  38. package/workspace/public/pm/today-day.js +23 -3
  39. package/workspace/public/pm/today-goals.js +7 -1
  40. package/workspace/server.js +53 -2
  41. package/workspace/skills/morning-brief.skill +6 -1
  42. package/workspace/test-files.json +2 -0
  43. package/workspace/test-lists/scan-consistency.json +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pmos",
3
- "version": "0.59.3",
3
+ "version": "0.60.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": {
@@ -1,3 +1,3 @@
1
- kernel-source: pmos@ad3caaf
1
+ kernel-source: pmos@45d7d1e
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-06T14:43:28Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T15:12:25Z"}
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-06T14:43:28Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T15:12:25Z"}
6
6
  status: stable
7
7
  ---
8
8
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * const D = require('./delivery-index');
7
7
  * const idx = D.deliveryIndex(root, ids); // { ok, reason?, byBranch:Set, byMention:Set }
8
- * D.attribution(idx, id) // 'branch' | 'mention' | null | 'unknown'
8
+ * D.attribution(idx, id) // 'branch' | 'mention' | 'change' | null | 'unknown'
9
9
  * D.isDeliveryPath('workspace/server.js') // true — a build path, not planning prose
10
10
  *
11
11
  * WHY THIS EXISTS. This derivation shipped inside `workspace/server.js` as a module-private
@@ -101,13 +101,13 @@ const deliveryCache = new Map(); // root -> { head, index }
101
101
  * any commit subject into a delivery claim
102
102
  * @returns {{ok:boolean, reason?:string, byBranch:Set<string>, byMention:Set<string>}}
103
103
  */
104
- function deliveryIndex(root, ids) {
104
+ function deliveryIndex(root, ids, opts) {
105
105
  const t = trunkRef(root);
106
106
  if (!t) {
107
107
  return {
108
108
  ok: false,
109
109
  reason: 'no trunk branch (main/master) is reachable from this repository — delivery cannot be derived',
110
- byBranch: new Set(), byMention: new Set(),
110
+ byBranch: new Set(), byMention: new Set(), byChange: new Set(),
111
111
  };
112
112
  }
113
113
  const hit = deliveryCache.get(root);
@@ -119,7 +119,7 @@ function deliveryIndex(root, ids) {
119
119
  return {
120
120
  ok: false,
121
121
  reason: `git could not read the history at ${t.ref}${r.err ? ` — ${r.err}` : ''}`,
122
- byBranch: new Set(), byMention: new Set(),
122
+ byBranch: new Set(), byMention: new Set(), byChange: new Set(),
123
123
  };
124
124
  }
125
125
  const byBranch = new Set();
@@ -137,11 +137,87 @@ function deliveryIndex(root, ids) {
137
137
  // the safe direction and the one the surface already errs in.
138
138
  for (const id of known) if (id.length > 3 && msg.includes(id)) byMention.add(id);
139
139
  }
140
- const index = { ok: true, byBranch, byMention };
140
+ // 3. THE CHANGE THAT CARRIED THE SPEC (scan-consistency R1). See changeSignal below.
141
+ const byChange = changeSignal(root, t.head, known, opts);
142
+ const index = { ok: true, byBranch, byMention, byChange };
141
143
  deliveryCache.set(root, { head: t.head, index });
142
144
  return index;
143
145
  }
144
146
 
147
+ /*
148
+ * THE THIRD SIGNAL — a change on the trunk that touched this initiative's OWN documents and build
149
+ * paths together (scan-consistency R1).
150
+ *
151
+ * Signals 1 and 2 both need the id spelled in a commit message. On this repository most pull
152
+ * requests ship on `claude/<slug>-<suffix>` branches and their commits name the area (`feat(workspace):
153
+ * …`), not the id, so 102 of 283 initiatives read `build pending` although their PRD, record and code
154
+ * merged in one pull request. The tie is concrete and git holds it: the pull request that changed
155
+ * `planning/initiatives/<id>.md` (or the PRD the record names) ALSO changed build files.
156
+ *
157
+ * A UNIT is one first-parent commit of the trunk: a merge commit (its diff against the first parent
158
+ * is the whole pull request), a squash merge, or a direct commit. Two guards keep it from becoming a
159
+ * similarity score:
160
+ * · the unit must change at least one build path (isDeliveryPath) — a docs-only pull request
161
+ * delivers nothing;
162
+ * · the unit may touch the documents of at most MAX_CO_INITIATIVES initiatives. A sweep that edits
163
+ * forty records while changing a script is evidence for none of them.
164
+ * A merged branch whose name, less its random suffix, IS a known id (`claude/jira-wbs-kpamaz`) counts
165
+ * too, when its pull request changed build paths.
166
+ */
167
+ const MAX_CO_INITIATIVES = 2;
168
+ const RECORD_DIRS = ['planning/initiatives', 'pmos/state/initiatives', 'state/initiatives'];
169
+ /** { [repo-relative path]: Set<id> } — each record and every `*_path` its frontmatter names. */
170
+ function documentOwners(root, ids, recordsDir) {
171
+ const fs = require('fs');
172
+ const path = require('path');
173
+ const dirs = recordsDir ? [recordsDir] : RECORD_DIRS.map((d) => path.join(root, d));
174
+ const owners = new Map();
175
+ const add = (rel, id) => {
176
+ const k = String(rel || '').trim().replace(/^["']|["']$/g, '').replace(/^\.?\//, '');
177
+ if (!k || /\s/.test(k) || k.includes('..')) return;
178
+ if (!owners.has(k)) owners.set(k, new Set());
179
+ owners.get(k).add(id);
180
+ };
181
+ for (const id of ids) {
182
+ for (const dir of dirs) {
183
+ const file = path.join(dir, id + '.md');
184
+ let text;
185
+ try { text = fs.readFileSync(file, 'utf8'); } catch { continue; }
186
+ add(path.relative(root, file).split(path.sep).join('/'), id);
187
+ const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
188
+ if (fm) for (const m of fm[1].matchAll(/^[a-z_]*_path[ \t]*:[ \t]*(\S.*?)[ \t]*$/gm)) add(m[1], id);
189
+ break;
190
+ }
191
+ }
192
+ return owners;
193
+ }
194
+ function changeSignal(root, head, known, opts) {
195
+ const out = new Set();
196
+ if (!known.length) return out;
197
+ const owners = documentOwners(root, known, opts && opts.recordsDir);
198
+ const ids = new Set(known);
199
+ const r = gitCap(root, ['log', '--first-parent', '--diff-merges=first-parent', '--format=%x1e%s%x1f', '--name-only', head]);
200
+ if (!r.ok) return out;
201
+ for (const chunk of r.out.split('\x1e')) {
202
+ if (!chunk.trim()) continue;
203
+ const cut = chunk.indexOf('\x1f');
204
+ const subject = cut < 0 ? chunk : chunk.slice(0, cut);
205
+ const files = cut < 0 ? [] : chunk.slice(cut + 1).split('\n').map((s) => s.trim()).filter(Boolean);
206
+ if (!files.some(isDeliveryPath)) continue;
207
+ const touched = new Set();
208
+ for (const f of files) for (const id of owners.get(f) || []) touched.add(id);
209
+ if (touched.size && touched.size <= MAX_CO_INITIATIVES) for (const id of touched) out.add(id);
210
+ const b = /^Merge (?:pull request #\d+ from|branch ')\s*(?:[^/\s]+\/)?(?:claude|feature|feat|fix|chore)\/([A-Za-z0-9][\w.-]*?)'?(?:\s|$)/.exec(subject.trim());
211
+ if (b) {
212
+ const slug = b[1];
213
+ const bare = slug.replace(/-[a-z0-9]{4,8}$/, '');
214
+ if (ids.has(slug)) out.add(slug);
215
+ else if (bare !== slug && ids.has(bare)) out.add(bare);
216
+ }
217
+ }
218
+ return out;
219
+ }
220
+
145
221
  /*
146
222
  * The branches that actually MERGED — a strictly narrower signal than `byBranch`, and the two are
147
223
  * kept apart on purpose.
@@ -251,12 +327,13 @@ function declaredDelivery(root, declared) {
251
327
  * caller that collapses the two reports "nothing was delivered" for a repository whose history it
252
328
  * failed to read, which is a claim the missing evidence cannot support.
253
329
  *
254
- * @returns {'branch'|'mention'|'unknown'|null}
330
+ * @returns {'branch'|'mention'|'change'|'unknown'|null}
255
331
  */
256
332
  function attribution(index, id) {
257
333
  if (!index || !index.ok) return 'unknown';
258
334
  if (index.byBranch.has(id)) return 'branch';
259
335
  if (index.byMention.has(id)) return 'mention';
336
+ if (index.byChange && index.byChange.has(id)) return 'change';
260
337
  return null;
261
338
  }
262
339
 
@@ -264,6 +341,7 @@ function attribution(index, id) {
264
341
  function attributionEvidence(signal, id, extra) {
265
342
  if (signal === 'branch') return `an initiative/${id} branch merged to the trunk`;
266
343
  if (signal === 'mention') return 'a commit on the trunk names this initiative and changes build files';
344
+ if (signal === 'change') return 'a change merged to the trunk carried this initiative\'s own documents and build files together';
267
345
  if (signal === 'declared') return `delivered_by ${String(extra || '').slice(0, 8)} — verified on the trunk, and it changes build paths`;
268
346
  if (signal === 'unknown') return 'the trunk history could not be read — delivery cannot be derived here';
269
347
  return 'no commit on the trunk is attributable to this initiative';
@@ -274,5 +352,5 @@ function _resetCache() { deliveryCache.clear(); }
274
352
 
275
353
  module.exports = {
276
354
  deliveryIndex, attribution, attributionEvidence, declaredDelivery, mergedBranches,
277
- isDeliveryPath, trunkRef, _resetCache,
355
+ isDeliveryPath, trunkRef, documentOwners, _resetCache,
278
356
  };
@@ -438,7 +438,7 @@ function buildCommits(root, range, lane, opts) {
438
438
  if (declared && declared.declared && !declared.ok) {
439
439
  return { unknown: false, failedDeclaration: declared, first: null, count: 0, sample: null, signal: null, attributed: true };
440
440
  }
441
- const index = (opts && opts.deliveryIndex) || delivery.deliveryIndex(root, listInitiatives(root));
441
+ const index = (opts && opts.deliveryIndex) || delivery.deliveryIndex(root, listInitiatives(root), { recordsDir: layout(root).initiatives });
442
442
  signal = delivery.attribution(index, id);
443
443
  if (declared && declared.ok) {
444
444
  // A verified declaration attributes the work regardless of what the conventions found. It is
@@ -478,7 +478,7 @@ function buildCommits(root, range, lane, opts) {
478
478
  count++;
479
479
  if (first === null) { first = i; sample = hit; }
480
480
  }
481
- if (whole && id && signal === 'branch' && first === null) {
481
+ if (whole && id && (signal === 'branch' || signal === 'change') && first === null) {
482
482
  // The branch merged and every commit it carried was written on the branch, so no trunk commit
483
483
  // subject names the id. The merge itself is the evidence, and saying "0 commits" over a merged
484
484
  // branch would be the under-claim in a new place.
@@ -1657,7 +1657,7 @@ function main(argv) {
1657
1657
  // reason the commit range is: `deliveryIndex` memoises per trunk head, so a per-initiative build
1658
1658
  // would be cheap but the intent — one read, shared — is what keeps the rows consistent with each
1659
1659
  // other even if the trunk moved mid-run.
1660
- const deliveryIdx = delivery.deliveryIndex(root, ids);
1660
+ const deliveryIdx = delivery.deliveryIndex(root, ids, { recordsDir: layout(root).initiatives });
1661
1661
  const rows = ids.map((i) => computeWorkflow(i, { root, range, changeRange, deliveryIndex: deliveryIdx }));
1662
1662
  if (json) { process.stdout.write(JSON.stringify(rows, null, 2) + '\n'); return 0; }
1663
1663
  if (!rows.length) { process.stdout.write('\n no initiative records found — is this a PMOS repo?\n\n'); return 1; }
@@ -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-06T14:43:28Z"}
5
+ generated: {by: process:create-pmos, at: "2026-10-06T15:12:25Z"}
6
6
  status: stable
7
7
  ---
8
8
 
@@ -54,27 +54,32 @@
54
54
  {
55
55
  "id": "intake",
56
56
  "label": "Intake",
57
- "state": "done"
57
+ "state": "done",
58
+ "owed": null
58
59
  },
59
60
  {
60
61
  "id": "spec",
61
62
  "label": "Spec",
62
- "state": "done"
63
+ "state": "done",
64
+ "owed": null
63
65
  },
64
66
  {
65
67
  "id": "build",
66
68
  "label": "Build",
67
- "state": "current"
69
+ "state": "current",
70
+ "owed": null
68
71
  },
69
72
  {
70
73
  "id": "evaluate",
71
74
  "label": "Evaluate",
72
- "state": "todo"
75
+ "state": "todo",
76
+ "owed": null
73
77
  },
74
78
  {
75
79
  "id": "accept",
76
80
  "label": "Accept",
77
- "state": "todo"
81
+ "state": "todo",
82
+ "owed": null
78
83
  }
79
84
  ],
80
85
  "waiting": {
@@ -90,14 +95,31 @@
90
95
  {
91
96
  "kind": "prd",
92
97
  "label": "PRD",
93
- "path": "planning/prd/partner-sso.md"
98
+ "path": "planning/prd/partner-sso.md",
99
+ "source": "record"
94
100
  },
95
101
  {
96
102
  "kind": "rubric",
97
103
  "label": "Rubric",
98
- "path": "planning/evals/partner-sso.md"
104
+ "path": "planning/evals/partner-sso.md",
105
+ "source": "record"
106
+ },
107
+ {
108
+ "kind": "explainer",
109
+ "label": "Explainer",
110
+ "path": "planning/explainers/partner-sso-surface-explainer.md",
111
+ "source": "knowledge-graph",
112
+ "shared": false
113
+ },
114
+ {
115
+ "kind": "code",
116
+ "label": "Code",
117
+ "path": "workspace/lib/partner-sso.js",
118
+ "source": "git",
119
+ "commits": 2
99
120
  }
100
121
  ],
122
+ "derived": null,
101
123
  "history": [
102
124
  {
103
125
  "at": "2026-10-04T09:00:00Z",
@@ -13,15 +13,15 @@ This guide describes the PMOS workspace as it works today. It ships with the app
13
13
  On a desktop the workspace is one frame. [Layout](layout.md) explains each part.
14
14
 
15
15
  1. **The top bar.** Repository ▾, the five places (Docs included), search (⌘K), Sync when the repository is not in sync, and Settings.
16
- 2. **The place.** One of Today, Initiatives, Board or Reports, or Docs (⌘K or `g d`). It fills the screen under the bar.
16
+ 2. **The place.** One of Agenda, Initiatives, Board or Reports, or Docs (⌘K or `g d`). It fills the screen under the bar.
17
17
  3. **The detail.** The item you opened: an initiative with its status, next steps and artifacts, or the profiles. It opens beside the place and closes with ×.
18
- 4. **The agent dock.** Terminals, documents, conversations and web pages. It is open on Today and a thin rail elsewhere.
18
+ 4. **The agent dock.** Terminals, documents, conversations and web pages. It is open on Agenda and a thin rail elsewhere.
19
19
 
20
20
  ## Where things are
21
21
 
22
22
  | You want | Go to |
23
23
  |---|---|
24
- | What is waiting for you now | Today |
24
+ | What is waiting for you now | Agenda |
25
25
  | The initiatives of a repository, or of every repository | Initiatives. Choose **All repositories** in Repository ▾ for every repository. |
26
26
  | The sessions of a repository, by initiative | The agent dock. ⌘K → **Branches and sessions** lists the branches. |
27
27
  | The items of an initiative | Board, or Breakdown in the initiative detail |
@@ -2,7 +2,7 @@
2
2
  type: Guide
3
3
  title: "Initiatives: the Roadmap, the List and the initiative sheet"
4
4
  description: "How to read and order the initiatives of a repository on the Roadmap and the List, open the initiative sheet, make a new initiative, and review the cycle."
5
- timestamp: 2026-10-05
5
+ timestamp: 2026-10-06
6
6
  ---
7
7
 
8
8
  # Initiatives: the Roadmap, the List and the initiative sheet
@@ -11,6 +11,12 @@ The Initiatives place shows every initiative of the selected repository. Each in
11
11
 
12
12
  Press **Roadmap** or **List** at the top to change the view. The workspace keeps your choice in this browser.
13
13
 
14
+ ### Re-scan
15
+
16
+ The workspace reads the stage, the files and the breakdown of each initiative from the repository. It reads them again when an initiative record changes, and at the latest after ten minutes. A change that does not touch a record, for example a pull request merged on the trunk, can show late.
17
+
18
+ To read the repository again now, use **Re-scan the repository**. It is in the **⋯** menu of an initiative sheet, and in the command menu (⌘K). A toast shows **Re-scanning…**, and another shows the time when the read ends. Then the view updates. Re-scan writes nothing. It works the same on PMOS itself and on a tenant repository.
19
+
14
20
  ## The Roadmap
15
21
 
16
22
  The Roadmap has three columns: Now, Next and Later. Each column is a ranked list of cards. The line at the top reads, for example, "Now · 5 KR · 3 health". It counts the initiatives in Now by what they serve: a key result (KR) or a health budget. When the rules set an advisory cap for Now, the line shows it. The cap only advises. It never stops a move.
@@ -56,6 +62,24 @@ From the top:
56
62
 
57
63
  An initiative that is finished reads "Accepted". An initiative on hold, closed or cancelled reads that word instead of a stage. After 5 days with no activity, the line adds "idle 5 d".
58
64
 
65
+ ### How the stage is read
66
+
67
+ The stage is the first stage with an open step at or after the furthest stage that has evidence. Work that went past a step, for example a build that merged before a contract was logged, is not held at the earlier stage. The earlier stage shows a warning mark, and its tooltip names the step that is still open, for example "Skipped: contract is still open". An accepted initiative has no current stage.
68
+
69
+ The build counts as done when the trunk holds evidence for this initiative: a merged `initiative/<id>` branch, a commit that names the id and changes build files, or a merged change that changed this initiative's own documents (its record, or a file the record names) and build files together. A change that touched the documents of more than two initiatives is not evidence for any of them.
70
+
71
+ ### The Files tab
72
+
73
+ The Files tab lists every file that belongs to the initiative, in three groups:
74
+
75
+ - **Named by the record.** The record, and each file its frontmatter names with a key that ends in `_path`: `prd_path`, `rubric_path`, `explainer_path`, `design_path` and others. A file the record names that does not exist is shown as missing.
76
+ - **Linked documents.** The documents the library joins to the initiative: a document that declares its `initiative_id`, a document the record names, a file name that starts with the id.
77
+ - **Changed for it in git.** The files that the commits for this initiative changed and that still exist. These are its own branch, trunk commits that name the id, and merged changes that carried its documents. The file opens read-only.
78
+
79
+ ### A breakdown read from the spec
80
+
81
+ When nobody has planned items for an initiative, the Breakdown tab shows the items of its spec above the empty Breakdown: the user stories, or the entries of the Requirements section of the PRD that the record names. Each item shows the state of the whole initiative: **Done** after you accept it, **Built** when its build is on the trunk, and **Todo** before that. These items are read-only and nothing is written. To track an item, add it to the Breakdown. The card and the row show the same count, for example "0 of 8 · from board-delivery-truth-prd.md".
82
+
59
83
  The More button in the sheet has:
60
84
 
61
85
  - **Move to Now**, **Move to Next**, **Move to Later**.
@@ -15,7 +15,7 @@ The top bar has these parts, from left to right:
15
15
 
16
16
  - **Repository ▾** names the current repository. Press it to choose another repository, or **All repositories** to see the work of every repository at once. All repositories replaces the old Portfolio mode.
17
17
  - **Branches and sessions** is in ⌘K. It opens a sheet with every branch of the repository (main first) and how many sessions run in each. Press a branch to see its sessions, open one, end one, or start a session there. **+ branch** makes a branch, and **+ session** starts one with a branch, an agent and a profile. With All repositories, the sheet lists every repository.
18
- - **Today, Initiatives, Board, Reports and Docs** are the five places. Press one to show it. The Today count shows how many items need you. Docs shows whether each document is the same as its Google Docs and Confluence copy.
18
+ - **Agenda, Initiatives, Board, Reports and Docs** are the five places. Press one to show it. The Agenda count shows how many items need you. Docs shows whether each document is the same as its Google Docs and Confluence copy.
19
19
  - **Search or capture ⌘K** opens the command palette. Type to find an initiative, a repository, an open tab or a command.
20
20
  - **Sync** shows only when the current repository is not in sync with its remote. Press it to fetch, bring in the work of the other machine, record your changes and push. If the repository has not fetched in the last 10 minutes, Sync also shows, because a push from another machine is not visible until a fetch. When the repository fetched recently and is in sync, Sync is not shown. If Sync stops, the message names the step that stopped.
21
21
  - **Sync on its own.** If you forget to press Sync, the workspace syncs for you. It syncs each repository once when the workspace starts. It also syncs a repository that has records not yet pushed when no record changed for 5 minutes. In a document repository it syncs every changed file on any branch. In a code repository it syncs only on the default branch (for example `main`), and only when every commit not yet pushed changes records and no code. If you close the tab while records are not yet pushed, the browser asks you first. To turn automatic sync off, start the workspace with `PMOS_AUTO_SYNC=0`.
@@ -37,11 +37,11 @@ Settings holds settings only, in seven sections:
37
37
  - **Update the kit** does what `npx create-pmos@latest --update` does in a terminal. It changes only the kit's own files under `pmos/` (skills, scripts, templates and guides). Your records in `state/`, `planning/` and `okf/product/` do not change. The last lines of the output show under the button. The changed files are under `pmos/`, which Sync treats as records, so Sync (or automatic sync) sends them with your other records. To read them first, look at `git diff pmos/` before you sync.
38
38
  - **Update the workspace** does what `pmos upgrade` does in a terminal. It asks you first. The workspace stops, installs the new version and starts again, and the page reloads when the new version starts. Sessions keep running in tmux. Press it on the computer that runs the workspace. From a phone it is refused, because the phone cannot see the restart through. When the workspace runs from a PMOS checkout, update it with `git pull` instead.
39
39
 
40
- Your work is never in Settings. It is in Today, Initiatives, Board and Reports.
40
+ Your work is never in Settings. It is in Agenda, Initiatives, Board and Reports.
41
41
 
42
42
  ## The agent dock
43
43
 
44
- The dock holds your terminals, documents, conversations, skills and web pages. It is open on Today. On every other place it is a 44-pixel rail at the right edge.
44
+ The dock holds your terminals, documents, conversations, skills and web pages. It is open on Agenda. On every other place it is a 44-pixel rail at the right edge.
45
45
 
46
46
  - Press ⌘J (Ctrl-J), or the button on the rail, to open the dock. Press ⌘J again, or the fold button in the dock, to fold it to the rail.
47
47
  - The dock never opens by itself. A tab that opens while the dock is a rail waits in the dock until you open it.
@@ -67,13 +67,13 @@ When the workspace needs an answer from you, for example the name for a rename o
67
67
 
68
68
  ## Colour and size
69
69
 
70
- The workspace is neutral. A primary button is the text colour on the page colour, in both themes. The one brand colour marks the Today dot and the Today count, and nothing else. The bar, the dock and the bottom bar follow the theme; only a terminal stays dark. Corners are square. Controls are icons from one set, not text symbols. On a touch screen every field is 16 pixels, so the phone does not zoom when you tap it, and every control is at least 44 pixels high.
70
+ The workspace is neutral. A primary button is the text colour on the page colour, in both themes. The one brand colour marks the Agenda dot and the Agenda count, and nothing else. The bar, the dock and the bottom bar follow the theme; only a terminal stays dark. Corners are square. Controls are icons from one set, not text symbols. On a touch screen every field is 16 pixels, so the phone does not zoom when you tap it, and every control is at least 44 pixels high.
71
71
 
72
72
  ## Keys
73
73
 
74
74
  | Key | What it does |
75
75
  |---|---|
76
- | g t, g i, g b, g r, g d | Show Today, Initiatives, Board, Reports or Docs. |
76
+ | g t, g i, g b, g r, g d | Show Agenda, Initiatives, Board, Reports or Docs. |
77
77
  | ⌘K (Ctrl-K) | Open or close the command palette. |
78
78
  | ⌘J (Ctrl-J) | Open or fold the dock. |
79
79
  | ⌘⇧J (Ctrl-Shift-J) | Focus: give the dock the whole window, or show the place again. |
@@ -89,7 +89,7 @@ A key that you type in a field, or in a terminal, goes to the field or the termi
89
89
 
90
90
  ## On a phone
91
91
 
92
- A phone shows one panel at a time. The tabs at the bottom are **Today, Initiatives, Board, Reports and Agent**. Agent shows the dock, with your terminals. Search or capture ⌘K is pinned at the top of Today.
92
+ A phone shows one panel at a time. The tabs at the bottom are **Agenda, Initiatives, Board, Reports and Agent**. Agent shows the dock, with your terminals. Search or capture ⌘K is pinned at the top of Agenda.
93
93
 
94
94
  The bar at the top has Back (when you are deeper than a tab), Repository, the name of the screen, ⌘K, Sync (when the repository is not in sync, or has not fetched in the last 10 minutes) and Settings. Settings opens over the current tab. Back returns to the tab.
95
95
 
@@ -180,6 +180,7 @@ Text that you type in a setting (the name, the stalled days, the quiet hours) or
180
180
  - `pmos proactive settings` shows the settings. Add `--enabled`, `--trigger NAME=on|off`, `--stalled-days`, `--quiet HH:MM-HH:MM|none`, `--pause-learning`, `--background-prepare on|off`, `--brief-source NAME=on|off`, `--scope SERVICE:NAME=watch|search|ignore`, `--day-check 30|60|off`, `--website URL`, `--no-website URL`, `--brief-scoring on|off` or `--name` to change one.
181
181
  - `pmos proactive goals` lists today's goals with their steps. `pmos proactive goals add TEXT [--initiative ID]` adds one. `done N`, `drop N`, `reopen N` and `remove N` change the Nth goal. `pmos proactive goals plan` does the same as **Prepare my day**.
182
182
  - `pmos proactive brief` shows today's brief. `pmos proactive brief submit --file PATH` submits one. `pmos proactive brief submit --file PATH --merge` merges one into the stored brief of the same day. `pmos proactive brief schedule` makes the 06:45 schedule for the current repository.
183
+ - `pmos proactive calendar` shows what the calendar memory holds (the number of events, the days it covers and when it was read) and the window the next morning brief reads: 90 days back and 31 ahead when the memory is empty or older than 7 days, else from today to 31 days ahead. It only reads.
183
184
  - `pmos proactive day` shows the stage of the day and its tasks. `pmos proactive day show TASK` prints one task with its item, its draft and the notes of each revision. Sessions read it.
184
185
  - `pmos proactive day deliver TASK --summary TEXT --body-file PATH [--link URL]` delivers the draft of a working task. `pmos proactive day sent TASK [--link URL]` reports that the approved step was done. `pmos proactive day fail TASK --reason TEXT` reports that a task cannot be done. Sessions run these three.
185
186
  - `pmos proactive day approve TASK`, `pmos proactive day revise TASK --note TEXT` and `pmos proactive day retry TASK` are your decisions, the same as the buttons. `pmos proactive day check` starts a check now.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  type: Guide
3
3
  title: "Today: what needs you"
4
- description: "The two-column day (your jobs and the agent's jobs), the eight kinds of card on Today, the one button on each card, the count, the empty state, and the pmos today command."
4
+ description: "The Agenda month and the calendar it remembers, the two-column day (your jobs and the agent's jobs), the eight kinds of card on Today, the one button on each card, the count, the empty state, and the pmos today command."
5
5
  timestamp: 2026-10-06
6
6
  ---
7
7
 
@@ -32,6 +32,28 @@ Each job session is named "Job ·" and the first words of the job, so the sessio
32
32
 
33
33
  **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. Your goals for today come under it, above the calendar. 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.
34
34
 
35
+ ### The Agenda month
36
+
37
+ The menu calls this page **Agenda**. At the top of the left column is the month, with today marked. Each week starts with its number, for example W41.
38
+
39
+ - Press a day to see its agenda under the month. Three tiles open the agenda: the time in meetings, the meeting that matters most, and your prep.
40
+ - Press a week number to see the agenda of that week, day by day.
41
+ - Press a meeting to see its memory in the right column. The month marks every day of the same meeting, so you see when it happens again.
42
+
43
+ Meetings that repeat and have nothing for you fold into one line, for example "+4 repeating, nothing for you". Press it to see them.
44
+
45
+ Each day of the month answers three questions:
46
+
47
+ - **How full is the day?** The bar covers 09:00 to 18:00. Each block is a meeting. A dark block is an important meeting.
48
+ - **What matters?** The ★ line names the one meeting of the day that matters. A meeting matters when you present or decide, when people from outside the company or leadership join, or when 8 people or more join. A meeting whose prep is at risk also shows.
49
+ - **How ready are you?** The badge shows the prep steps done out of the steps needed, for example 1/3. It is red when the free time before the meeting is shorter than 30 minutes for each step left. A past day shows how many one-to-ones and important meetings have no notes.
50
+
51
+ The switch above the month shows one answer at a time: **Overview** (all three), **Full** (the time in meetings), **Key** (the meeting that matters), **Prep** (how ready you are) or **Free** (the free blocks of 90 minutes or more).
52
+
53
+ The memory of a meeting says what kind of meeting it is (one-to-one, onboarding or group), how many times it was held, how many are to come, and why it matters. **Before this meeting** lists the prep. **Last time** is folded: open it to read the notes and what stayed open.
54
+
55
+ The month comes from the calendar memory. The morning-brief session reads your calendar 90 days back and 31 days ahead the first time, and from today to 31 days ahead after that, and sends it with the brief. The workspace keeps 100 days back and 45 days ahead, in `calendar-memory.json` in the state folder. Nothing on the Agenda writes to your calendar. To see what the memory holds, run `pmos proactive calendar`.
56
+
35
57
  ### One day for every repository
36
58
 
37
59
  The day is yours, not a repository's. Every repository shows the same calendar, goals, jobs and mentions. To narrow the day, use the **Show** switch at the top of Today: