create-pmos 0.51.0 → 0.53.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 (212) hide show
  1. package/package.json +1 -1
  2. package/payload/KIT-VERSION +2 -2
  3. package/payload/mods/pmos-cockpit/README.md +13 -0
  4. package/payload/mods/pmos-cockpit/hooks/lib/commands.mjs +2 -1
  5. package/payload/mods/pmos-cockpit/hooks/lib/grants.mjs +41 -11
  6. package/payload/mods/pmos-cockpit/hooks/lib/guard.mjs +228 -8
  7. package/payload/mods/pmos-cockpit/hooks/register.tsx +11 -3
  8. package/payload/planning/evals/eval-calibration.md +1 -1
  9. package/payload/planning/okrs/health-budgets.md +1 -1
  10. package/payload/scripts/plan-items-stage.js +271 -0
  11. package/payload/scripts/pmos-log.sh +18 -7
  12. package/payload/scripts/workflow-state.js +28 -2
  13. package/payload/state/discoveries.md +1 -1
  14. package/payload/state/log.md +1 -1
  15. package/workspace/bin/pmos.js +15 -1
  16. package/workspace/cut-stub.js +40 -0
  17. package/workspace/first-paint-audit.js +145 -0
  18. package/workspace/fixtures/capture/requirements/capture-2026-10-04-1.md +10 -0
  19. package/workspace/fixtures/initiatives-api/list.json +176 -0
  20. package/workspace/fixtures/initiatives-api/post-403.json +5 -0
  21. package/workspace/fixtures/initiatives-api/post-ok.json +10 -0
  22. package/workspace/fixtures/initiatives-api/roadmap.json +208 -0
  23. package/workspace/fixtures/initiatives-api/sheet.json +112 -0
  24. package/workspace/fixtures/report-api/draft.json +177 -0
  25. package/workspace/fixtures/reports-page/draft-biweekly-2026-10-16.md +97 -0
  26. package/workspace/fixtures/today-api/provider-rows.json +204 -0
  27. package/workspace/fixtures/today-api/seam-probe-kinds.json +5 -0
  28. package/workspace/guide/board.md +81 -0
  29. package/workspace/guide/breakdown.md +154 -0
  30. package/workspace/guide/command-palette.md +75 -0
  31. package/workspace/guide/index.md +27 -17
  32. package/workspace/guide/initiatives-roadmap.md +130 -0
  33. package/workspace/guide/initiatives-screen.md +89 -0
  34. package/workspace/guide/initiatives-timeline.md +57 -0
  35. package/workspace/guide/integrated-work.md +94 -0
  36. package/workspace/guide/knowledge-graph.md +3 -68
  37. package/workspace/guide/layout.md +98 -32
  38. package/workspace/guide/live-notes.md +3 -3
  39. package/workspace/guide/pm-only-acts.md +89 -0
  40. package/workspace/guide/pm-only-lines.md +61 -0
  41. package/workspace/guide/reports-page.md +80 -0
  42. package/workspace/guide/reports.md +73 -0
  43. package/workspace/guide/timeline.md +70 -0
  44. package/workspace/guide/today.md +85 -0
  45. package/workspace/guide/validate-with-typesafe.md +1 -1
  46. package/workspace/lib/actor.js +91 -0
  47. package/workspace/lib/board-cache.js +32 -2
  48. package/workspace/lib/board-cli.js +108 -0
  49. package/workspace/lib/board-fold.js +232 -0
  50. package/workspace/lib/breakdown-export.js +80 -0
  51. package/workspace/lib/capture.js +98 -0
  52. package/workspace/lib/engine/plan-items-stage.js +271 -0
  53. package/workspace/lib/engine/workflow-state.js +28 -2
  54. package/workspace/lib/factory-join.js +158 -0
  55. package/workspace/lib/grant-mint.js +113 -0
  56. package/workspace/lib/health-rules-factory.js +92 -0
  57. package/workspace/lib/health-rules-plan.js +164 -0
  58. package/workspace/lib/health.js +79 -0
  59. package/workspace/lib/initiative-cli.js +222 -0
  60. package/workspace/lib/initiative-display.js +183 -0
  61. package/workspace/lib/initiative-needs.js +127 -0
  62. package/workspace/lib/initiative-rows.js +206 -0
  63. package/workspace/lib/initiative-writer.js +141 -0
  64. package/workspace/lib/issues.js +206 -0
  65. package/workspace/lib/item-cli.js +195 -0
  66. package/workspace/lib/item-spans.js +137 -0
  67. package/workspace/lib/measure-cli.js +100 -0
  68. package/workspace/lib/measurements.js +189 -0
  69. package/workspace/lib/mobile-nav.js +57 -53
  70. package/workspace/lib/needs-providers.js +120 -0
  71. package/workspace/lib/placements.js +440 -0
  72. package/workspace/lib/plan-items.js +922 -0
  73. package/workspace/lib/plan-ledgers.js +85 -0
  74. package/workspace/lib/plan-rules.js +72 -0
  75. package/workspace/lib/plan-tree.js +367 -0
  76. package/workspace/lib/pm-guard.js +174 -0
  77. package/workspace/lib/pm-lines-needs.js +331 -0
  78. package/workspace/lib/pmos-verbs.js +66 -0
  79. package/workspace/lib/proactive.js +7 -4
  80. package/workspace/lib/report-cli.js +152 -0
  81. package/workspace/lib/report-draft.js +579 -0
  82. package/workspace/lib/report-needs.js +213 -0
  83. package/workspace/lib/route-modules.js +128 -0
  84. package/workspace/lib/routes-board.js +91 -0
  85. package/workspace/lib/routes-capture.js +52 -0
  86. package/workspace/lib/routes-initiatives.js +371 -0
  87. package/workspace/lib/routes-reports.js +163 -0
  88. package/workspace/lib/routes-timeline.js +197 -0
  89. package/workspace/lib/routes-today.js +32 -0
  90. package/workspace/lib/today-cli.js +99 -0
  91. package/workspace/lib/today.js +333 -0
  92. package/workspace/lib/triage.js +163 -0
  93. package/workspace/lib/verify-work-cli.js +81 -0
  94. package/workspace/lib/work-check-needs.js +99 -0
  95. package/workspace/package-lock.json +1 -1
  96. package/workspace/package.json +5 -5
  97. package/workspace/public/index.html +29 -19
  98. package/workspace/public/pm/app.js +299 -30
  99. package/workspace/public/pm/bd-board.js +113 -0
  100. package/workspace/public/pm/bd-drag.js +59 -0
  101. package/workspace/public/pm/bd-model.js +152 -0
  102. package/workspace/public/pm/bd-timeline.js +233 -0
  103. package/workspace/public/pm/bd-tree.js +244 -0
  104. package/workspace/public/pm/board-copy.js +57 -0
  105. package/workspace/public/pm/breakdown-api.js +58 -0
  106. package/workspace/public/pm/breakdown-copy.js +138 -0
  107. package/workspace/public/pm/components.css +3054 -0
  108. package/workspace/public/pm/cycle-review.js +125 -0
  109. package/workspace/public/pm/data.js +40 -187
  110. package/workspace/public/pm/dest-board.js +438 -0
  111. package/workspace/public/pm/dest-initiatives.js +134 -0
  112. package/workspace/public/pm/dest-reports.js +270 -0
  113. package/workspace/public/pm/dest-settings.js +217 -0
  114. package/workspace/public/pm/dest-today.js +176 -0
  115. package/workspace/public/pm/dialogs.js +88 -0
  116. package/workspace/public/pm/display-word.js +56 -0
  117. package/workspace/public/pm/dock.js +105 -0
  118. package/workspace/public/pm/fixture.js +8 -227
  119. package/workspace/public/pm/frame-copy.js +94 -0
  120. package/workspace/public/pm/handoff-box.js +82 -0
  121. package/workspace/public/pm/http.js +88 -0
  122. package/workspace/public/pm/icons.js +53 -0
  123. package/workspace/public/pm/initiative-list.js +218 -0
  124. package/workspace/public/pm/initiative-sheet.js +261 -0
  125. package/workspace/public/pm/initiatives-api.js +59 -0
  126. package/workspace/public/pm/initiatives-copy.js +215 -0
  127. package/workspace/public/pm/initiatives-timeline-copy.js +59 -0
  128. package/workspace/public/pm/initiatives-timeline.js +410 -0
  129. package/workspace/public/pm/initiatives-ui.js +123 -0
  130. package/workspace/public/pm/item-sheet.js +251 -0
  131. package/workspace/public/pm/keep-card.js +204 -0
  132. package/workspace/public/pm/lifecycle.js +7 -1
  133. package/workspace/public/pm/mobile.css +49 -20
  134. package/workspace/public/pm/mobile.js +157 -29
  135. package/workspace/public/pm/modes-live.js +7 -883
  136. package/workspace/public/pm/modes.js +32 -1024
  137. package/workspace/public/pm/new-initiative-sheet.js +74 -0
  138. package/workspace/public/pm/next-step-ui.js +3 -2
  139. package/workspace/public/pm/palette-copy.js +51 -0
  140. package/workspace/public/pm/palette.js +312 -0
  141. package/workspace/public/pm/panel-breakdown.js +702 -0
  142. package/workspace/public/pm/panel-cockpit.js +63 -295
  143. package/workspace/public/pm/panel-detail.js +25 -172
  144. package/workspace/public/pm/panel-initiatives.js +1 -19
  145. package/workspace/public/pm/panel-repos.js +31 -81
  146. package/workspace/public/pm/panel-tabs.js +197 -110
  147. package/workspace/public/pm/panel-trees.js +5 -2
  148. package/workspace/public/pm/portfolio-report.js +61 -0
  149. package/workspace/public/pm/primitives.js +656 -0
  150. package/workspace/public/pm/print.css +33 -0
  151. package/workspace/public/pm/provider-cards.js +136 -0
  152. package/workspace/public/pm/registry.js +194 -0
  153. package/workspace/public/pm/release-card.js +110 -0
  154. package/workspace/public/pm/report-view.js +309 -0
  155. package/workspace/public/pm/reports-copy.js +114 -0
  156. package/workspace/public/pm/roadmap.js +271 -0
  157. package/workspace/public/pm/sig-watch.js +41 -0
  158. package/workspace/public/pm/state.js +8 -4
  159. package/workspace/public/pm/status-banner.js +13 -5
  160. package/workspace/public/pm/tab-doc.js +2 -4
  161. package/workspace/public/pm/tab-term.js +12 -2
  162. package/workspace/public/pm/tab-web.js +3 -2
  163. package/workspace/public/pm/timeline-copy.js +48 -0
  164. package/workspace/public/pm/today-cards.js +244 -0
  165. package/workspace/public/pm/today-copy.js +97 -0
  166. package/workspace/public/pm/tokens.css +16 -18
  167. package/workspace/public/pm/topbar.js +102 -0
  168. package/workspace/public/pm/triage-card.js +60 -0
  169. package/workspace/public/pm/undo-hold.js +103 -0
  170. package/workspace/public/pm/view-addrepo.js +2 -1
  171. package/workspace/public/pm/view-livenotes.js +3 -1
  172. package/workspace/public/pm/view-today.js +7 -162
  173. package/workspace/public/vendor/Sortable.min.js +2 -0
  174. package/workspace/public/vendor/lucide-sprite.js +79 -0
  175. package/workspace/replaced-tests.json +2864 -0
  176. package/workspace/run-tests.js +117 -6
  177. package/workspace/server.js +312 -36
  178. package/workspace/sheet-answer.js +61 -0
  179. package/workspace/skills/measure.skill +41 -0
  180. package/workspace/skills/report-biweekly.skill +23 -25
  181. package/workspace/skills/tracker-refresh.skill +50 -0
  182. package/workspace/test-files.json +20 -4
  183. package/workspace/test-lists/base.json +6 -0
  184. package/workspace/test-lists/run2-a.json +6 -0
  185. package/workspace/test-lists/run2-b.json +13 -0
  186. package/workspace/test-lists/run2-c.json +19 -0
  187. package/workspace/test-lists/run2-d.json +22 -0
  188. package/workspace/test-lists/run3-0.json +5 -0
  189. package/workspace/test-lists/run3-a.json +5 -0
  190. package/workspace/test-lists/run3-b.json +6 -0
  191. package/workspace/test-lists/run3-c.json +15 -0
  192. package/workspace/test-lists/run3-d.json +6 -0
  193. package/workspace/test-lists/run4-a.json +8 -0
  194. package/workspace/test-lists/run4-b.json +6 -0
  195. package/workspace/test-lists/run4-c.json +13 -0
  196. package/workspace/test-lists/run4-d.json +9 -0
  197. package/workspace/test-lists/run5-a.json +6 -0
  198. package/workspace/test-lists/run5-b.json +6 -0
  199. package/workspace/test-lists/run5-c.json +15 -0
  200. package/workspace/test-run.js +27 -1
  201. package/workspace/third-party/README.md +44 -0
  202. package/workspace/third-party/lucide-static-1.52.0.LICENSE +43 -0
  203. package/workspace/third-party/sortablejs-1.15.7.LICENSE +21 -0
  204. package/workspace/design-parity.js +0 -673
  205. package/workspace/public/pm/tab-task.js +0 -86
  206. package/workspace/public/pm/view-guide.js +0 -141
  207. package/workspace/public/pm/view-knowledge.js +0 -225
  208. package/workspace/public/pm/view-memory.js +0 -122
  209. package/workspace/public/pm/view-portfolio.js +0 -153
  210. package/workspace/public/pm/view-reports.js +0 -190
  211. package/workspace/public/pm/view-scheduled.js +0 -161
  212. package/workspace/public/pm/view-skills.js +0 -216
@@ -0,0 +1,215 @@
1
+ /* pm/initiatives-copy.js — every word the Initiatives destination shows (pm-os-absorb Run 2, slice 2D).
2
+ *
3
+ * Pure data and pure functions. No DOM and no import, so `glossary.test.js` can load this file in Node and check every
4
+ * string against the glossary rules. The Roadmap, the List, the initiative sheet, the New-initiative form, the Cycle
5
+ * review card, the triage card and the Breakdown's empty state write their words here and nowhere else. The register is
6
+ * instructional (skills/domains/technical-writing-ste.skill): short sentences, one verb for one act.
7
+ *
8
+ * One word is right here and wrong on the Breakdown: Accepted is what a finished initiative reads (PRD R3). It is
9
+ * exempted below, with its reason; every other rule of the glossary holds.
10
+ */
11
+
12
+ const MON = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
13
+
14
+ /** "2026-10-30" -> "30 Oct", read as a calendar day. */
15
+ export function shortDate(ymd) {
16
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(String(ymd || ''));
17
+ return m ? Number(m[3]) + ' ' + MON[Number(m[2]) - 1] : '';
18
+ }
19
+
20
+ export const GLOSSARY = {
21
+ exempt: { accept: 'Accepted is the word a finished initiative reads on this surface (PRD R3).' },
22
+ guide: 'initiatives-screen.md',
23
+ };
24
+
25
+ export const COPY = {
26
+ title: 'Initiatives',
27
+ views: 'Initiatives view',
28
+ roadmap: 'Roadmap',
29
+ list: 'List',
30
+ newInitiative: 'New initiative',
31
+ reading: 'Reading…',
32
+ readFailed: (why) => `Could not read the initiatives: ${why}`,
33
+ noRepo: 'Add a repository to see its initiatives.',
34
+ emptyAll: 'No initiatives yet. Add one with New initiative.',
35
+ flags: (n) => (n === 1 ? '1 line of the placements ledger could not be read.' : `${n} lines of the placements ledger could not be read.`),
36
+
37
+ horizons: { now: 'Now', next: 'Next', later: 'Later' },
38
+ /** "Now · 5 KR · 3 health", with the advisory cap when the rules set one. */
39
+ nowLine: (n) => `Now · ${n.kr} KR · ${n.health} health${n.cap ? ' · cap ' + n.cap : ''}`,
40
+ overCap: (count, cap) => `${count} in Now. The advisory cap is ${cap}.`,
41
+ emptyColumn: { now: 'Nothing in Now.', next: 'Nothing in Next.', later: 'Nothing in Later.' },
42
+ dormant: (n) => `${n} dormant`,
43
+ hideDormant: (n) => `Hide ${n} dormant`,
44
+ unconfirmed: 'unconfirmed',
45
+ checkBy: (d) => `check-by ${d}`,
46
+ waitingYou: 'waiting on you',
47
+ waitingAgent: 'waiting on agent',
48
+ due: (d) => `due ${d}`,
49
+ healthUnknown: 'unknown',
50
+ attention: 'Waiting on you',
51
+ proposed: 'proposed',
52
+
53
+ menu: {
54
+ more: 'More',
55
+ open: 'Open',
56
+ toTop: 'To top',
57
+ up: 'Up',
58
+ down: 'Down',
59
+ moveNow: 'Move to Now',
60
+ moveNext: 'Move to Next',
61
+ moveLater: 'Move to Later',
62
+ setCheckBy: 'Set check-by',
63
+ },
64
+ aria: {
65
+ more: (t) => `More for ${t}`,
66
+ reorder: (t) => `Reorder ${t}`,
67
+ open: (t) => `Open ${t}`,
68
+ select: (t) => `Select ${t}`,
69
+ column: (h) => `${h} column`,
70
+ },
71
+ moved: {
72
+ top: (t) => `${t} is at the top.`,
73
+ now: (t) => `${t} moved to Now.`,
74
+ next: (t) => `${t} moved to Next.`,
75
+ later: (t) => `${t} moved to Later.`,
76
+ checkBy: (t, d) => (d ? `Check-by of ${t} is ${d}.` : `Check-by of ${t} is cleared.`),
77
+ },
78
+ refused: (why) => `Not done. ${why}`,
79
+
80
+ /* List */
81
+ noObjective: 'No objective',
82
+ healthBudgets: 'Health budgets',
83
+ /** "41% on 2 Oct → 55%": shown only when a measurement exists. */
84
+ measured: (m) => `${m.value}${m.unit || ''} on ${shortDate(m.as_of)}${m.target !== null && m.target !== undefined ? ' → ' + m.target + (m.unit || '') : ''}`,
85
+ select: 'Select',
86
+ /** Shown where there is no touch screen: the ⋯ button is not on a desk card, so the screen says where the menu is. */
87
+ menuHintCard: 'To open the menu of a card, right-click it or press the menu key.',
88
+ menuHintRow: 'To open the menu of a row, right-click it or press the menu key.',
89
+ done: 'Done',
90
+ selectedN: (n) => `${n} selected`,
91
+ bulkNext: 'Move to Next',
92
+ bulkLater: 'Move to Later',
93
+ bulkLifecycle: 'Change lifecycle',
94
+ bulkMax: 'Select 20 initiatives at most.',
95
+ bulkLifecycleTitle: (n) => (n === 1 ? 'Change the lifecycle of 1 initiative' : `Change the lifecycle of ${n} initiatives`),
96
+ lifecycleChoose: 'Set to',
97
+ bulkLifecycleLater: 'Changing the lifecycle of several initiatives arrives in Run 2.',
98
+ lifecycleHold: 'On hold',
99
+ lifecycleClose: 'Close',
100
+ lifecycleCancel: 'Mark cancelled',
101
+ lifecycleReopen: 'Reopen',
102
+ /** The state a lifecycle line sets, as a noun. A menu item is a verb ("Close"); the title and the toast name the state ("Closed"). */
103
+ lifecycleState: { 'on-hold': 'On hold', closed: 'Closed', cancelled: 'Cancelled', active: 'Active' },
104
+ lifecycleTitle: (state, n) => (n === 1 ? `Set 1 initiative to ${state}` : `Set ${n} initiatives to ${state}`),
105
+ lifecycleBody: (state, n) => `This writes one lifecycle line${n === 1 ? '' : ' for each of the ' + n + ' initiatives'}. Only you can do it.`,
106
+ reason: 'Reason (optional)',
107
+ confirm: 'Confirm',
108
+ cancel: 'Cancel',
109
+ lifecycleDone: (state, n) => (n === 1 ? `Set to ${state}.` : `Set ${n} initiatives to ${state}.`),
110
+ moveDone: (n, h) => (n === 1 ? `Moved 1 initiative to ${h}.` : `Moved ${n} initiatives to ${h}.`),
111
+
112
+ /* the sheet */
113
+ sheet: {
114
+ stages: 'Stages',
115
+ tabs: 'Initiative sections',
116
+ breakdown: 'Breakdown',
117
+ files: 'Files',
118
+ history: 'History',
119
+ waitingYou: (act) => `Waiting on you: ${act}`,
120
+ waitingAgent: (act) => `Waiting on agent: ${act}`,
121
+ nothingOwed: 'Nothing is owed.',
122
+ openGate: 'Open gate',
123
+ handToAgent: 'Hand to agent',
124
+ noFiles: 'No files yet.',
125
+ noHistory: 'No history yet.',
126
+ reading: 'Reading…',
127
+ readFailed: (why) => `Could not read the initiative: ${why}`,
128
+ changeAnchor: 'Change anchor',
129
+ copyCli: 'Copy CLI',
130
+ exportBreakdown: 'Export breakdown',
131
+ copied: (text) => `Copied: ${text}`,
132
+ copyFailed: 'The browser did not allow the copy.',
133
+ exported: 'Breakdown copied as text.',
134
+ exportFailed: (why) => `Could not export the breakdown: ${why}`,
135
+ anchorLabel: 'Anchor',
136
+ anchorHint: 'KR 2.1 or health:tech',
137
+ anchorTitle: 'Change the anchor',
138
+ anchorBody: 'The anchor names the KR or health budget this initiative serves. Only you can change it.',
139
+ anchorSaved: (a) => `The anchor is ${a}.`,
140
+ anchorShape: 'Enter a KR id such as KR 2.1, or health: and an id.',
141
+ anchorNoRecord: 'The record of this initiative could not be read.',
142
+ save: 'Save',
143
+ checkByTitle: 'Set the check-by date',
144
+ checkByLabel: 'Check-by date',
145
+ clear: 'Clear',
146
+ close: 'Close',
147
+ menuMore: (t) => `More for ${t}`,
148
+ },
149
+
150
+ /* New initiative */
151
+ newForm: {
152
+ title: 'New initiative',
153
+ titleLabel: 'Title',
154
+ laneLabel: 'Lane',
155
+ laneHint: 'feature, chore, discovery',
156
+ anchorLabel: 'Anchor',
157
+ anchorHint: 'KR 2.1 or health:tech',
158
+ anchorOther: 'Another anchor',
159
+ anchorPick: 'Choose an anchor',
160
+ lands: 'It starts in Later. Move it to Now when it becomes real work.',
161
+ add: 'Add',
162
+ noTitle: 'Enter a title.',
163
+ noAnchor: 'Choose an anchor. An initiative with no anchor is refused.',
164
+ added: (t) => `Added ${t} to Later.`,
165
+ open: 'Open',
166
+ },
167
+
168
+ /* Cycle review (Today, kind 7) */
169
+ cycle: {
170
+ cardKind: 'Cycle review',
171
+ review: 'Review',
172
+ sheetTitle: 'Cycle review',
173
+ reading: 'Reading…',
174
+ nothing: 'Nothing to review.',
175
+ confirmNow: 'Now, unconfirmed',
176
+ confirmNowHint: 'These read Now because they are active. Confirm each one, or move it back.',
177
+ confirm: 'Confirm',
178
+ moveBack: 'Move back',
179
+ proposals: 'Agent proposals',
180
+ proposalsHint: 'An agent proposed these moves. Keep one to apply it, or drop it.',
181
+ proposalLine: (h, who) => `${h}${who ? ' · ' + who : ''}`,
182
+ keep: 'Keep',
183
+ drop: 'Drop',
184
+ checkBys: 'Check-by dates passed',
185
+ checkBysHint: 'Set a new date, or move the initiative to Next.',
186
+ setCheckBy: 'Set check-by',
187
+ moveNext: 'Move to Next',
188
+ kept: 'Kept.',
189
+ dropped: 'Dropped.',
190
+ confirmed: (t) => `${t} is confirmed in Now.`,
191
+ movedBack: (t) => `${t} moved back to Later.`,
192
+ killOpen: 'Open',
193
+ summary: (n) => (n === 1 ? '1 item to review' : `${n} items to review`),
194
+ },
195
+
196
+ /* triage (Today, kind 6) */
197
+ triage: {
198
+ add: 'Add',
199
+ adding: 'Adding…',
200
+ added: (t) => `Added ${t} to Later.`,
201
+ addFailed: (why) => `Not added. ${why}`,
202
+ unreadable: 'The proposal line of the card could not be read.',
203
+ },
204
+
205
+ /* the Breakdown's empty state */
206
+ breakThisDown: {
207
+ label: 'Break this down',
208
+ head: 'Start from this list',
209
+ addAll: (n) => `Add ${n} items`,
210
+ or: 'Or type the first item yourself.',
211
+ type: 'Type items',
212
+ none: 'No starter list is set. Type the first item.',
213
+ adding: 'Adding…',
214
+ },
215
+ };
@@ -0,0 +1,59 @@
1
+ /* pm/initiatives-timeline-copy.js — every word Initiatives › Timeline shows (pm-os-absorb Run 4, slice 4C).
2
+ *
3
+ * Pure data and pure functions. No DOM and no import, so `glossary.test.js` can load this file in Node and check every
4
+ * string against the glossary rules. The words of the Timeline bar itself (the stage names on a bar, a milestone) are
5
+ * slice 4B's `timeline-copy.js`; this file holds the words around it: the rows, the groups, the menu and the refusals.
6
+ */
7
+
8
+ const MON = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
9
+
10
+ /** "2026-10-20" -> "20 Oct". A date-only value is read as a calendar day, never shifted by the time zone. */
11
+ export function shortDate(ymd) {
12
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(String(ymd || ''));
13
+ return m ? Number(m[3]) + ' ' + MON[Number(m[2]) - 1] : '';
14
+ }
15
+
16
+ /** "2026-10-01" -> "Oct", or "Oct 2026" for the first month of the chart and for each January. */
17
+ export function monthLabel(ymd, withYear) {
18
+ const m = /^(\d{4})-(\d{2})/.exec(String(ymd || ''));
19
+ if (!m) return '';
20
+ const name = MON[Number(m[2]) - 1];
21
+ return withYear || m[2] === '01' ? name + ' ' + m[1] : name;
22
+ }
23
+
24
+ /** "5 Oct to 2 Dec": the span a bar covers, for the row's meta line and its label. */
25
+ export const spanText = (span) => (span ? (span.start === span.due ? shortDate(span.start) : shortDate(span.start) + ' to ' + shortDate(span.due)) : '');
26
+
27
+ export const COPY = {
28
+ view: 'Timeline',
29
+ chart: 'Timeline of initiatives, by month',
30
+ reading: 'Reading…',
31
+ readFailed: (why) => `Could not read the timeline: ${why}`,
32
+ retry: 'Try again',
33
+ none: 'No initiative is in a work lane yet.',
34
+ noDates: 'No initiative has a dated item yet. Give an item a start or a due date in its Breakdown, and its bar shows here.',
35
+ today: 'Today',
36
+ horizon: { now: 'Now', next: 'Next', later: 'Later' },
37
+ undatedHead: 'Not dated',
38
+ undatedNote: 'These initiatives have no dated item. Order is the only thing they carry.',
39
+ noDatedItems: 'No dated items',
40
+ stageLine: (label, done, total) => `${label} · ${done} of ${total}`,
41
+ progress: (done, total) => (total ? `${done} of ${total}` : 'no breakdown'),
42
+ aria: {
43
+ chart: 'Timeline of initiatives. Scrolls sideways.',
44
+ group: (label) => `${label} initiatives`,
45
+ reorder: (title) => `Drag to reorder ${title}`,
46
+ more: (title) => `More actions for ${title}`,
47
+ show: (title) => `Show stages of ${title}`,
48
+ hide: (title) => `Hide stages of ${title}`,
49
+ bar: (title, span) => (span ? `${title}, ${spanText(span)}` : `${title}, no dated items`),
50
+ stageBar: (title, stage, span) => `${title}, ${stage}${span ? ', ' + spanText(span) : ''}`,
51
+ },
52
+ menu: { open: 'Open', top: 'To top', up: 'Up', down: 'Down' },
53
+ moveFailed: (title, why) => `Could not move ${title}: ${why}`,
54
+ alsoPlaced: (title, n, horizon) => `Moved ${title}. ${n} other ${n === 1 ? 'row' : 'rows'} in ${horizon} now ${n === 1 ? 'has' : 'have'} a saved place, so the order holds.`,
55
+ clipped: (from, to) => `The chart shows ${from} to ${to}. A date outside those months is cut off.`,
56
+ why: { noWs: 'no workspace is selected', noAnswer: 'the workspace did not answer' },
57
+ };
58
+
59
+ export const GLOSSARY = { guide: 'initiatives-timeline.md' };