create-pmos 0.134.0 → 0.135.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 (209) 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/state/discoveries.md +1 -1
  6. package/workspace/bin/notes-replay.js +235 -0
  7. package/workspace/c3-briefing-test.js +130 -0
  8. package/workspace/c3-foundation-test.js +159 -0
  9. package/workspace/c3-ib-items-test.js +105 -0
  10. package/workspace/c3-ib-more-test.js +120 -0
  11. package/workspace/c3-ib-triage-backlog-test.js +119 -0
  12. package/workspace/c3-ini-harness.js +66 -0
  13. package/workspace/c3-initiatives-test.js +140 -0
  14. package/workspace/c3-one-home-test.js +14 -1
  15. package/workspace/c3-reports-test.js +57 -18
  16. package/workspace/c3-settings-test.js +139 -0
  17. package/workspace/c3-work-test.js +42 -10
  18. package/workspace/fixtures/one-home-baseline.json +1 -9
  19. package/workspace/guide/briefing-cards.md +15 -3
  20. package/workspace/guide/briefing.md +12 -8
  21. package/workspace/guide/calendar-popup.md +2 -2
  22. package/workspace/guide/console-calendar.md +39 -10
  23. package/workspace/guide/index.md +1 -0
  24. package/workspace/guide/initiative-boards.md +65 -0
  25. package/workspace/guide/jira.md +3 -1
  26. package/workspace/guide/layout.md +2 -0
  27. package/workspace/guide/my-work.md +5 -3
  28. package/workspace/guide/notes.md +16 -1
  29. package/workspace/guide/reports-dashboards.md +29 -5
  30. package/workspace/guide/settings.md +68 -0
  31. package/workspace/guide/welcome.md +10 -10
  32. package/workspace/lib/calendar-cli.js +3 -2
  33. package/workspace/lib/calendar-layers.js +21 -10
  34. package/workspace/lib/calendar-tidy.js +230 -0
  35. package/workspace/lib/engine/boards.js +542 -0
  36. package/workspace/lib/engine/breakdown-ops.js +180 -0
  37. package/workspace/lib/engine/calendar-import.js +84 -0
  38. package/workspace/lib/engine/calendar-model.js +185 -0
  39. package/workspace/lib/engine/card-state.js +92 -0
  40. package/workspace/lib/engine/derived/derive.js +92 -0
  41. package/workspace/lib/engine/derived/plan.js +3 -0
  42. package/workspace/lib/engine/derived/trust.js +3 -0
  43. package/workspace/lib/engine/doc-health.js +142 -0
  44. package/workspace/lib/engine/doc-sheet.js +75 -0
  45. package/workspace/lib/engine/intake.js +78 -0
  46. package/workspace/lib/engine/outbox.js +86 -0
  47. package/workspace/lib/engine/plan-forecast.js +342 -0
  48. package/workspace/lib/engine/promises.js +29 -0
  49. package/workspace/lib/engine/records/index.js +114 -0
  50. package/workspace/lib/engine/releases.js +96 -0
  51. package/workspace/lib/engine/replies.js +99 -0
  52. package/workspace/lib/engine/reply-contract/reply-contract.js +372 -0
  53. package/workspace/lib/engine/report-families.js +175 -0
  54. package/workspace/lib/engine/roadmap-ops.js +150 -0
  55. package/workspace/lib/engine/sessions-list.js +27 -0
  56. package/workspace/lib/engine/signal-rules.js +95 -0
  57. package/workspace/lib/engine/signals/cards.js +57 -0
  58. package/workspace/lib/engine/signals/detectors.js +370 -0
  59. package/workspace/lib/engine/signals/facts-cli.js +8 -0
  60. package/workspace/lib/engine/signals/facts.js +197 -0
  61. package/workspace/lib/engine/signals/index.js +33 -0
  62. package/workspace/lib/engine/signals/kinds.js +110 -0
  63. package/workspace/lib/engine/signals/layout-paths.js +44 -0
  64. package/workspace/lib/engine/signals/options.js +24 -0
  65. package/workspace/lib/engine/signals/score.js +72 -0
  66. package/workspace/lib/engine/signals/select.js +47 -0
  67. package/workspace/lib/engine/step-planner.js +65 -0
  68. package/workspace/lib/engine/trust/claim-rules.json +93 -0
  69. package/workspace/lib/engine/trust/import-calendar.js +21 -0
  70. package/workspace/lib/engine/trust/import-guard.js +36 -0
  71. package/workspace/lib/engine/trust/ledger.js +53 -0
  72. package/workspace/lib/engine/trust/outbox.js +45 -0
  73. package/workspace/lib/engine/trust/plan.js +5 -0
  74. package/workspace/lib/engine/trust/trust.js +21 -0
  75. package/workspace/lib/engine/truth-table.js +57 -0
  76. package/workspace/lib/engine/workspace-lib.js +24 -0
  77. package/workspace/lib/factory-join.js +1 -1
  78. package/workspace/lib/facts-async.js +4 -4
  79. package/workspace/lib/headless.js +95 -0
  80. package/workspace/lib/import-overlay.js +2 -1
  81. package/workspace/lib/jira-status.js +30 -3
  82. package/workspace/lib/notes-capture.js +9 -1
  83. package/workspace/lib/notes-final.js +38 -13
  84. package/workspace/lib/notes-replay.js +125 -0
  85. package/workspace/lib/notes-screen.js +180 -0
  86. package/workspace/lib/notes-whisper.js +10 -3
  87. package/workspace/lib/outbox-store.js +10 -6
  88. package/workspace/lib/pmos-verbs.js +3 -1
  89. package/workspace/lib/proactive-cli.js +7 -0
  90. package/workspace/lib/proactive.js +15 -2
  91. package/workspace/lib/repo-script.js +36 -0
  92. package/workspace/lib/report-dashboards.js +5 -2
  93. package/workspace/lib/report-frame.js +122 -0
  94. package/workspace/lib/report-schedules.js +113 -0
  95. package/workspace/lib/route-modules.js +9 -2
  96. package/workspace/lib/routes-boards.js +734 -0
  97. package/workspace/lib/routes-brief-page.js +13 -4
  98. package/workspace/lib/routes-briefing.js +22 -11
  99. package/workspace/lib/routes-c3-init.js +4 -3
  100. package/workspace/lib/routes-c3-life.js +2 -1
  101. package/workspace/lib/routes-c3-reports.js +96 -13
  102. package/workspace/lib/routes-c3-strategy.js +4 -3
  103. package/workspace/lib/routes-c3-timeline.js +3 -2
  104. package/workspace/lib/routes-calendar-import.js +3 -2
  105. package/workspace/lib/routes-calendar-views.js +9 -4
  106. package/workspace/lib/routes-doc-health.js +2 -1
  107. package/workspace/lib/routes-doc-sheet.js +2 -1
  108. package/workspace/lib/routes-forecast.js +2 -1
  109. package/workspace/lib/routes-hooks.js +3 -2
  110. package/workspace/lib/routes-initiatives.js +2 -1
  111. package/workspace/lib/routes-intake.js +2 -1
  112. package/workspace/lib/routes-notes.js +55 -9
  113. package/workspace/lib/routes-outbox.js +23 -3
  114. package/workspace/lib/routes-pm-items.js +19 -6
  115. package/workspace/lib/routes-records.js +3 -2
  116. package/workspace/lib/routes-releases.js +2 -1
  117. package/workspace/lib/routes-report-facts.js +4 -3
  118. package/workspace/lib/routes-report-families.js +2 -1
  119. package/workspace/lib/routes-roadmap-ops.js +5 -4
  120. package/workspace/lib/routes-runs.js +6 -5
  121. package/workspace/lib/routes-settings.js +51 -0
  122. package/workspace/lib/routes-signals.js +3 -2
  123. package/workspace/lib/routes-stage-tools.js +220 -0
  124. package/workspace/lib/run-answers.js +2 -1
  125. package/workspace/lib/settings-store.js +226 -0
  126. package/workspace/lib/stage-tools.js +208 -0
  127. package/workspace/lib/vendor/scripts/signals/layout-paths.js +2 -1
  128. package/workspace/lib/vendor/scripts/workspace-lib.js +24 -0
  129. package/workspace/lib/work-evidence.js +73 -0
  130. package/workspace/package-lock.json +2 -2
  131. package/workspace/package.json +1 -1
  132. package/workspace/public/pm/briefing-deck.js +63 -17
  133. package/workspace/public/pm/briefing-model.js +36 -7
  134. package/workspace/public/pm/c3-ambient.js +100 -0
  135. package/workspace/public/pm/c3-brief-needs.js +26 -6
  136. package/workspace/public/pm/c3-brief-pulse.js +12 -4
  137. package/workspace/public/pm/c3-brief-today.js +56 -21
  138. package/workspace/public/pm/c3-brief.js +2 -1
  139. package/workspace/public/pm/c3-calendar.js +161 -42
  140. package/workspace/public/pm/c3-calpop.js +5 -5
  141. package/workspace/public/pm/c3-demo-boards.js +649 -0
  142. package/workspace/public/pm/c3-demo-brief-page.js +1 -1
  143. package/workspace/public/pm/c3-demo-cal4.js +3 -2
  144. package/workspace/public/pm/c3-demo-cal5.js +52 -0
  145. package/workspace/public/pm/c3-demo-data.js +17 -27
  146. package/workspace/public/pm/c3-demo-rep3.js +46 -5
  147. package/workspace/public/pm/c3-demo.js +2 -1
  148. package/workspace/public/pm/c3-dock.js +1 -1
  149. package/workspace/public/pm/c3-ib-docs.js +80 -0
  150. package/workspace/public/pm/c3-ib-initiatives.js +134 -0
  151. package/workspace/public/pm/c3-ib-items.js +201 -0
  152. package/workspace/public/pm/c3-ib-releases.js +51 -0
  153. package/workspace/public/pm/c3-ib-sprints.js +55 -0
  154. package/workspace/public/pm/c3-ib-triage.js +178 -0
  155. package/workspace/public/pm/c3-ii-tabs.js +240 -0
  156. package/workspace/public/pm/c3-ini-records.js +197 -0
  157. package/workspace/public/pm/c3-ini-timeline.js +278 -0
  158. package/workspace/public/pm/c3-ini-ui.js +229 -0
  159. package/workspace/public/pm/c3-ini-work.js +139 -0
  160. package/workspace/public/pm/c3-initiatives.css +218 -0
  161. package/workspace/public/pm/c3-initiatives.js +741 -0
  162. package/workspace/public/pm/c3-plan.js +2 -2
  163. package/workspace/public/pm/c3-reports.css +47 -47
  164. package/workspace/public/pm/c3-reports.js +223 -185
  165. package/workspace/public/pm/c3-settings.css +74 -0
  166. package/workspace/public/pm/c3-settings.js +703 -0
  167. package/workspace/public/pm/c3-shell.js +102 -36
  168. package/workspace/public/pm/c3-terminal-icons.js +2 -2
  169. package/workspace/public/pm/c3-terminal.js +2 -2
  170. package/workspace/public/pm/calendar-views.js +1 -1
  171. package/workspace/public/pm/components.css +319 -213
  172. package/workspace/public/pm/console3.css +99 -23
  173. package/workspace/public/pm/dest-notes.js +26 -4
  174. package/workspace/public/pm/notes-screen-capture.js +165 -0
  175. package/workspace/public/pm/notes-screen-view.js +98 -0
  176. package/workspace/public/pm/panel-trees.js +5 -2
  177. package/workspace/public/pm/pm-work-view.js +233 -146
  178. package/workspace/public/pm/shell-bell.js +3 -2
  179. package/workspace/public/pm/shell-recording.js +29 -8
  180. package/workspace/public/pm/tokens.css +2 -2
  181. package/workspace/public/pm/view-notes.js +46 -9
  182. package/workspace/public/pm/welcome.js +197 -89
  183. package/workspace/public/welcome.html +6 -4
  184. package/workspace/server.js +105 -6
  185. package/workspace/skills/day-check.skill +1 -1
  186. package/workspace/skills/jira-sync.skill +6 -4
  187. package/workspace/skills/morning-brief.skill +1 -1
  188. package/workspace/test-files.json +12 -3
  189. package/workspace/test-lists/c3-ib-items.json +9 -0
  190. package/workspace/test-lists/c3-ib-more.json +9 -0
  191. package/workspace/test-lists/c3-ib-triage-backlog.json +9 -0
  192. package/workspace/test-lists/c3-initiative-boards.json +6 -0
  193. package/workspace/test-lists/calendar-tidy-up.json +6 -0
  194. package/workspace/test-lists/console3-briefing.json +9 -0
  195. package/workspace/test-lists/console3-foundation.json +9 -0
  196. package/workspace/test-lists/console3-reports.json +3 -3
  197. package/workspace/test-lists/meeting-notes.json +10 -4
  198. package/workspace/test-lists/workspace-headless-jobs.json +5 -0
  199. package/workspace/test-lists/workspace-package-script-closure.json +6 -0
  200. package/workspace/lib/vendor/workspace/lib/actor.js +0 -91
  201. package/workspace/lib/vendor/workspace/lib/board-cache.js +0 -156
  202. package/workspace/lib/vendor/workspace/lib/console-state.js +0 -295
  203. package/workspace/lib/vendor/workspace/lib/factory-join.js +0 -158
  204. package/workspace/lib/vendor/workspace/lib/git-info.js +0 -306
  205. package/workspace/lib/vendor/workspace/lib/plan-items.js +0 -922
  206. package/workspace/lib/vendor/workspace/lib/plan-tree.js +0 -419
  207. package/workspace/lib/vendor/workspace/lib/review-gate.js +0 -39
  208. package/workspace/lib/vendor/workspace/lib/sink.js +0 -321
  209. package/workspace/lib/vendor/workspace/lib/state-root.js +0 -587
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+ /* report-schedules.js — a schedule per Reports dashboard: a ready draft in the outbox on each run, and a notice on the bell
3
+ * (initiative console3-dashboard-schedules, PRD R1 to R4). NOTHING IS SENT: a run only appends one outbox draft.
4
+ *
5
+ * PLANS weekly (Mondays 08:00) and monthly (the 1st at 08:00), host-local, as lib/schedule-logic.js reads them
6
+ * readSchedules(runtimeDir) → { [key]: { key, ws, plan, audience, lastRun, last_status, last_error, last_draft, created_at } }
7
+ * viewOf(schedules, now) → the same, each with label and next_run (ISO), for GET /api/report-dashboards
8
+ * saveSchedule(runtimeDir, body, now) { key, plan: none|weekly|monthly, audience, ws } → { ok, schedules } | { ok:false, error }
9
+ * dueOf(schedules, now) → the schedules with a slot in (lastRun, now]
10
+ * markRun(runtimeDir, key, fields) merges the run's outcome into the schedule
11
+ * makeDraft(runtimeDir, sched, frame, now) → the outbox entry: ONE 'queued' line, made_by 'schedule'
12
+ * noticesOf(entries, now) → the bell's notices: scheduled drafts of the last 7 days still in the outbox
13
+ *
14
+ * The store is <runtimeDir>/report-dashboards/schedules.json, written with a temp file and a rename, beside layouts.json. Saving a
15
+ * schedule sets lastRun to now, so a slot that is already past never runs on save. schedule-logic.isDue fires once for the newest
16
+ * slot in (lastRun, now], so slots missed while the server was down are not caught up one by one. */
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const crypto = require('crypto');
20
+ const logic = require('./schedule-logic.js');
21
+ const rd = require('./report-dashboards.js');
22
+ const { repoScript } = require('./repo-script.js');
23
+ const outbox = require(repoScript('outbox.js'));
24
+ const store = require('./outbox-store.js');
25
+
26
+ const PLANS = Object.freeze({
27
+ weekly: Object.freeze({ cadence: 'weekly', day: 'Mon', time: '08:00', label: 'Weekly, Mondays 08:00' }),
28
+ monthly: Object.freeze({ cadence: 'monthly', dayOfMonth: 1, time: '08:00', label: 'Monthly, 1st at 08:00' }),
29
+ });
30
+ const AUDIENCES = ['Leadership', 'Team'];
31
+ const NOTICE_MS = 7 * 864e5;
32
+
33
+ const dirOf = (runtimeDir) => path.join(runtimeDir, 'report-dashboards');
34
+ const fileOf = (runtimeDir) => path.join(dirOf(runtimeDir), 'schedules.json');
35
+ const timing = (s) => ({ ...PLANS[s.plan], enabled: true, lastRun: s.lastRun || null });
36
+
37
+ /** A missing or damaged file reads as no schedules; an entry that is not valid is dropped. */
38
+ function readSchedules(runtimeDir) {
39
+ let raw;
40
+ try { raw = JSON.parse(fs.readFileSync(fileOf(runtimeDir), 'utf8')); } catch { return {}; }
41
+ const src = raw && typeof raw === 'object' && raw.schedules && typeof raw.schedules === 'object' ? raw.schedules : {};
42
+ const out = {};
43
+ for (const [k, v] of Object.entries(src)) {
44
+ if (!rd.validKey(k) || !v || !PLANS[v.plan] || !AUDIENCES.includes(v.audience)) continue;
45
+ out[k] = { ...v, key: k };
46
+ }
47
+ return out;
48
+ }
49
+
50
+ function writeAll(runtimeDir, schedules) {
51
+ const dir = dirOf(runtimeDir);
52
+ fs.mkdirSync(dir, { recursive: true });
53
+ const tmp = path.join(dir, 'schedules.json.' + process.pid + '.' + crypto.randomBytes(4).toString('hex') + '.tmp');
54
+ try {
55
+ fs.writeFileSync(tmp, JSON.stringify({ schedules }, null, 2) + '\n');
56
+ fs.renameSync(tmp, fileOf(runtimeDir));
57
+ } catch (e) {
58
+ try { fs.unlinkSync(tmp); } catch { /* nothing to remove */ }
59
+ return { ok: false, error: 'the schedule could not be saved: ' + String((e && e.message) || e) };
60
+ }
61
+ return { ok: true, schedules };
62
+ }
63
+
64
+ function viewOf(schedules, now = new Date()) {
65
+ const out = {};
66
+ for (const [k, s] of Object.entries(schedules || {})) out[k] = { ...s, label: PLANS[s.plan].label, next_run: logic.nextRun(timing(s), now) };
67
+ return out;
68
+ }
69
+
70
+ function saveSchedule(runtimeDir, body, now = new Date()) {
71
+ if (!runtimeDir || typeof runtimeDir !== 'string') return { ok: false, error: 'no runtime directory' };
72
+ const b = body || {};
73
+ if (!rd.validKey(b.key)) return { ok: false, error: 'key must be portfolio, board:<id> or initiative:<id>' };
74
+ if (b.plan !== 'none' && !PLANS[b.plan]) return { ok: false, error: 'plan must be none, weekly or monthly' };
75
+ if (b.plan !== 'none' && !AUDIENCES.includes(b.audience)) return { ok: false, error: 'audience must be Leadership or Team' };
76
+ if (b.ws != null && (typeof b.ws !== 'string' || b.ws.length > 200)) return { ok: false, error: 'ws must be a workspace id' };
77
+ const all = readSchedules(runtimeDir);
78
+ if (b.plan === 'none') delete all[b.key];
79
+ else {
80
+ const cur = all[b.key];
81
+ const same = cur && cur.plan === b.plan;
82
+ all[b.key] = { key: b.key, ws: b.ws || null, plan: b.plan, audience: b.audience, created_at: (cur && cur.created_at) || now.toISOString(),
83
+ lastRun: same ? cur.lastRun : now.toISOString(), last_status: same ? cur.last_status || null : null, last_error: same ? cur.last_error || null : null, last_draft: same ? cur.last_draft || null : null };
84
+ }
85
+ return writeAll(runtimeDir, all);
86
+ }
87
+
88
+ const dueOf = (schedules, now = new Date()) => Object.values(schedules || {}).filter((s) => logic.isDue(timing(s), now));
89
+
90
+ function markRun(runtimeDir, key, fields) {
91
+ const all = readSchedules(runtimeDir);
92
+ if (!all[key]) return { ok: false, error: 'no schedule for ' + key };
93
+ all[key] = { ...all[key], ...fields, key };
94
+ return writeAll(runtimeDir, all);
95
+ }
96
+
97
+ /** One draft for the schedule, from the frame lib/report-frame.js built. The hash covers what the outbox hashes; made_by and schedule_key ride beside it. */
98
+ function makeDraft(runtimeDir, sched, F, body, now = new Date()) {
99
+ const e = outbox.draftOutbox({ channel: 'customer-note', recipient: F.audience, subject: F.title + ' for ' + F.audience, body, origin: 'pm' });
100
+ const entry = { id: 'out-' + crypto.randomBytes(6).toString('hex'), ...e, made_by: 'schedule', schedule_key: sched.key };
101
+ store.appendEvent(runtimeDir, { event: 'queued', ...entry }, now);
102
+ return entry;
103
+ }
104
+
105
+ function noticesOf(entries, now = new Date()) {
106
+ const t = now.getTime();
107
+ return (entries || []).filter((e) => e && e.made_by === 'schedule' && e.state !== 'sent' && t - Date.parse(e.created_at || 0) <= NOTICE_MS)
108
+ .sort((a, b) => String(b.created_at).localeCompare(String(a.created_at)))
109
+ .map((e) => ({ key: 'dash-draft:' + e.id, tag: 'Just in', icon: 'mail', headline: (e.subject || 'A dashboard') + ': a scheduled draft is ready. Nothing was sent.',
110
+ when: '', unread: true, go: { tab: 'rep', view: 'drafts' } }));
111
+ }
112
+
113
+ module.exports = { PLANS, AUDIENCES, readSchedules, viewOf, saveSchedule, dueOf, markRun, makeDraft, noticesOf, fileOf };
@@ -16,7 +16,8 @@
16
16
  * };
17
17
  * `ctx` is what server.js hands over, plus `readJson`:
18
18
  * { json(res, obj, code), readBody(req), readJson(req) → { ok, body } | { ok: false },
19
- * getWs(id), invalidateNeedsAgg(id), boardCache, consoleState, stateDirFor(w), sessionList() }
19
+ * getWs(id), invalidateNeedsAgg(id), boardCache, consoleState, stateDirFor(w), sessionList(), runtimeDir,
20
+ * workspaceList(), selfRoot (the embedded PMOS checkout, or null), … }
20
21
  * A module needs nothing else from server.js; it requires the lib/ modules it uses itself (spelled with `.js` when the
21
22
  * module is a ledger writer, so scripts/check-separation.js lists the caller).
22
23
  *
@@ -61,8 +62,11 @@ const MODULES = Object.freeze([
61
62
  'routes-c3-strategy', // console3 Calendar Quarter and Year panes: outcomes, north star, signals, synergy, bets (read-only)
62
63
  'routes-c3-reports', // console3 Reports dashboards: library, per-scope data, page-press layouts (layouts are the only write)
63
64
  'routes-onboarding', // onboarding-scan-and-map slice 2: first run (scan read-only, structure, import into the overlay, undo, first Briefing)
65
+ 'routes-boards', // c3-initiative-boards: Portfolio, Board, Backlog, Triage asks, workflows and moves (boards.jsonl)
66
+ 'routes-settings', // console3 Settings: the settings store for settings with no home of their own (GET; page-press POST)
64
67
  'routes-hooks', // planning-flows run 7: CLI hook endpoints (session token, per-run JSONL)
65
68
  'routes-sources', // workspace-data-freshness: how old each source is, Refresh now, the change detector switch
69
+ 'routes-stage-tools', // stage-tools-records: the records the PM edits per stage, what PMOS holds per stage, the sprint burndown
66
70
  ]);
67
71
  const PM_DIR = path.join(__dirname, '..', 'public', 'pm');
68
72
  const MODULE_NAME = /^[a-z0-9][a-z0-9-]*\.js$/;
@@ -79,7 +83,10 @@ function load() {
79
83
  let mod;
80
84
  try { mod = require(full); }
81
85
  catch (e) {
82
- if (e && e.code === 'MODULE_NOT_FOUND' && String(e.message).includes(full)) continue; // not built yet
86
+ // Not built yet only when the module ITSELF is missing. Node lists the requiring file in the message too ("Require
87
+ // stack: - <full>"), so a module whose own require fails used to match here and vanish as "not built": in a package
88
+ // that left 21 route modules unrouted with no broken entry (incident workspace-package-script-closure).
89
+ if (e && e.code === 'MODULE_NOT_FOUND' && String(e.message).split('\n')[0].includes(full)) continue;
83
90
  broken[name] = `${name}.js failed to load: ${String((e && e.message) || e).slice(0, 200)}`;
84
91
  continue;
85
92
  }