create-pmos 0.134.0 → 0.136.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 +1 -1
- package/payload/KIT-VERSION +2 -2
- 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/payload/state/log.md +1 -1
- package/workspace/bin/notes-replay.js +235 -0
- package/workspace/c3-briefing-test.js +130 -0
- package/workspace/c3-foundation-test.js +159 -0
- package/workspace/c3-ib-items-test.js +105 -0
- package/workspace/c3-ib-more-test.js +120 -0
- package/workspace/c3-ib-triage-backlog-test.js +119 -0
- package/workspace/c3-ini-harness.js +66 -0
- package/workspace/c3-initiatives-test.js +140 -0
- package/workspace/c3-one-home-test.js +14 -1
- package/workspace/c3-reports-test.js +57 -18
- package/workspace/c3-settings-test.js +139 -0
- package/workspace/c3-work-test.js +42 -10
- package/workspace/fixtures/one-home-baseline.json +1 -9
- package/workspace/guide/briefing-cards.md +15 -3
- package/workspace/guide/briefing.md +12 -8
- package/workspace/guide/calendar-popup.md +2 -2
- package/workspace/guide/console-calendar.md +39 -10
- package/workspace/guide/index.md +1 -0
- package/workspace/guide/initiative-boards.md +65 -0
- package/workspace/guide/jira.md +3 -1
- package/workspace/guide/layout.md +2 -0
- package/workspace/guide/my-work.md +5 -3
- package/workspace/guide/notes.md +16 -1
- package/workspace/guide/reports-dashboards.md +29 -5
- package/workspace/guide/settings.md +68 -0
- package/workspace/guide/welcome.md +10 -10
- package/workspace/lib/calendar-cli.js +3 -2
- package/workspace/lib/calendar-layers.js +21 -10
- package/workspace/lib/calendar-tidy.js +230 -0
- package/workspace/lib/engine/boards.js +542 -0
- package/workspace/lib/engine/breakdown-ops.js +180 -0
- package/workspace/lib/engine/calendar-import.js +84 -0
- package/workspace/lib/engine/calendar-model.js +185 -0
- package/workspace/lib/engine/card-state.js +92 -0
- package/workspace/lib/engine/derived/derive.js +92 -0
- package/workspace/lib/engine/derived/plan.js +3 -0
- package/workspace/lib/engine/derived/trust.js +3 -0
- package/workspace/lib/engine/doc-health.js +142 -0
- package/workspace/lib/engine/doc-sheet.js +75 -0
- package/workspace/lib/engine/intake.js +78 -0
- package/workspace/lib/engine/outbox.js +86 -0
- package/workspace/lib/engine/plan-forecast.js +342 -0
- package/workspace/lib/engine/promises.js +29 -0
- package/workspace/lib/engine/records/index.js +114 -0
- package/workspace/lib/engine/releases.js +96 -0
- package/workspace/lib/engine/replies.js +99 -0
- package/workspace/lib/engine/reply-contract/reply-contract.js +372 -0
- package/workspace/lib/engine/report-families.js +175 -0
- package/workspace/lib/engine/roadmap-ops.js +150 -0
- package/workspace/lib/engine/sessions-list.js +27 -0
- package/workspace/lib/engine/signal-rules.js +95 -0
- package/workspace/lib/engine/signals/cards.js +57 -0
- package/workspace/lib/engine/signals/detectors.js +370 -0
- package/workspace/lib/engine/signals/facts-cli.js +8 -0
- package/workspace/lib/engine/signals/facts.js +197 -0
- package/workspace/lib/engine/signals/index.js +33 -0
- package/workspace/lib/engine/signals/kinds.js +110 -0
- package/workspace/lib/engine/signals/layout-paths.js +44 -0
- package/workspace/lib/engine/signals/options.js +24 -0
- package/workspace/lib/engine/signals/score.js +72 -0
- package/workspace/lib/engine/signals/select.js +47 -0
- package/workspace/lib/engine/step-planner.js +65 -0
- package/workspace/lib/engine/trust/claim-rules.json +93 -0
- package/workspace/lib/engine/trust/import-calendar.js +21 -0
- package/workspace/lib/engine/trust/import-guard.js +36 -0
- package/workspace/lib/engine/trust/ledger.js +53 -0
- package/workspace/lib/engine/trust/outbox.js +45 -0
- package/workspace/lib/engine/trust/plan.js +5 -0
- package/workspace/lib/engine/trust/trust.js +21 -0
- package/workspace/lib/engine/truth-table.js +57 -0
- package/workspace/lib/engine/workspace-lib.js +24 -0
- package/workspace/lib/factory-join.js +1 -1
- package/workspace/lib/facts-async.js +4 -4
- package/workspace/lib/headless.js +95 -0
- package/workspace/lib/import-overlay.js +2 -1
- package/workspace/lib/jira-status.js +30 -3
- package/workspace/lib/notes-capture.js +9 -1
- package/workspace/lib/notes-final.js +38 -13
- package/workspace/lib/notes-replay.js +125 -0
- package/workspace/lib/notes-screen.js +180 -0
- package/workspace/lib/notes-whisper.js +10 -3
- package/workspace/lib/outbox-store.js +10 -6
- package/workspace/lib/pmos-verbs.js +3 -1
- package/workspace/lib/proactive-cli.js +7 -0
- package/workspace/lib/proactive.js +15 -2
- package/workspace/lib/records-dir.js +29 -0
- package/workspace/lib/repo-script.js +36 -0
- package/workspace/lib/report-dashboards.js +5 -2
- package/workspace/lib/report-frame.js +122 -0
- package/workspace/lib/report-schedules.js +113 -0
- package/workspace/lib/route-modules.js +9 -2
- package/workspace/lib/routes-boards.js +734 -0
- package/workspace/lib/routes-brief-page.js +13 -4
- package/workspace/lib/routes-briefing.js +22 -11
- package/workspace/lib/routes-c3-init.js +9 -8
- package/workspace/lib/routes-c3-life.js +2 -1
- package/workspace/lib/routes-c3-reports.js +99 -15
- package/workspace/lib/routes-c3-strategy.js +7 -5
- package/workspace/lib/routes-c3-timeline.js +3 -2
- package/workspace/lib/routes-calendar-import.js +3 -2
- package/workspace/lib/routes-calendar-views.js +9 -4
- package/workspace/lib/routes-doc-health.js +2 -1
- package/workspace/lib/routes-doc-sheet.js +2 -1
- package/workspace/lib/routes-forecast.js +2 -1
- package/workspace/lib/routes-hooks.js +3 -2
- package/workspace/lib/routes-initiatives.js +2 -1
- package/workspace/lib/routes-intake.js +2 -1
- package/workspace/lib/routes-notes.js +55 -9
- package/workspace/lib/routes-outbox.js +23 -3
- package/workspace/lib/routes-pm-items.js +19 -6
- package/workspace/lib/routes-records.js +10 -7
- package/workspace/lib/routes-releases.js +2 -1
- package/workspace/lib/routes-report-facts.js +4 -3
- package/workspace/lib/routes-report-families.js +2 -1
- package/workspace/lib/routes-roadmap-ops.js +17 -14
- package/workspace/lib/routes-runs.js +6 -5
- package/workspace/lib/routes-settings.js +51 -0
- package/workspace/lib/routes-signals.js +3 -2
- package/workspace/lib/routes-stage-tools.js +220 -0
- package/workspace/lib/run-answers.js +2 -1
- package/workspace/lib/settings-store.js +226 -0
- package/workspace/lib/stage-tools.js +208 -0
- package/workspace/lib/vendor/scripts/signals/layout-paths.js +2 -1
- package/workspace/lib/vendor/scripts/workspace-lib.js +24 -0
- package/workspace/lib/work-evidence.js +73 -0
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/briefing-deck.js +63 -17
- package/workspace/public/pm/briefing-model.js +36 -7
- package/workspace/public/pm/c3-ambient.js +100 -0
- package/workspace/public/pm/c3-brief-needs.js +26 -6
- package/workspace/public/pm/c3-brief-pulse.js +12 -4
- package/workspace/public/pm/c3-brief-today.js +56 -21
- package/workspace/public/pm/c3-brief.js +2 -1
- package/workspace/public/pm/c3-calendar.js +161 -42
- package/workspace/public/pm/c3-calpop.js +5 -5
- package/workspace/public/pm/c3-demo-boards.js +649 -0
- package/workspace/public/pm/c3-demo-brief-page.js +1 -1
- package/workspace/public/pm/c3-demo-cal4.js +3 -2
- package/workspace/public/pm/c3-demo-cal5.js +52 -0
- package/workspace/public/pm/c3-demo-data.js +17 -27
- package/workspace/public/pm/c3-demo-rep3.js +46 -5
- package/workspace/public/pm/c3-demo.js +2 -1
- package/workspace/public/pm/c3-dock.js +1 -1
- package/workspace/public/pm/c3-ib-docs.js +80 -0
- package/workspace/public/pm/c3-ib-initiatives.js +134 -0
- package/workspace/public/pm/c3-ib-items.js +201 -0
- package/workspace/public/pm/c3-ib-releases.js +51 -0
- package/workspace/public/pm/c3-ib-sprints.js +55 -0
- package/workspace/public/pm/c3-ib-triage.js +178 -0
- package/workspace/public/pm/c3-ii-tabs.js +240 -0
- package/workspace/public/pm/c3-ini-records.js +197 -0
- package/workspace/public/pm/c3-ini-timeline.js +278 -0
- package/workspace/public/pm/c3-ini-ui.js +229 -0
- package/workspace/public/pm/c3-ini-work.js +139 -0
- package/workspace/public/pm/c3-initiatives.css +218 -0
- package/workspace/public/pm/c3-initiatives.js +741 -0
- package/workspace/public/pm/c3-plan.js +2 -2
- package/workspace/public/pm/c3-reports.css +47 -47
- package/workspace/public/pm/c3-reports.js +223 -185
- package/workspace/public/pm/c3-settings.css +74 -0
- package/workspace/public/pm/c3-settings.js +703 -0
- package/workspace/public/pm/c3-shell.js +102 -36
- package/workspace/public/pm/c3-terminal-icons.js +2 -2
- package/workspace/public/pm/c3-terminal.js +2 -2
- package/workspace/public/pm/calendar-views.js +1 -1
- package/workspace/public/pm/components.css +319 -213
- package/workspace/public/pm/console3.css +99 -23
- package/workspace/public/pm/dest-notes.js +26 -4
- package/workspace/public/pm/notes-screen-capture.js +165 -0
- package/workspace/public/pm/notes-screen-view.js +98 -0
- package/workspace/public/pm/panel-trees.js +5 -2
- package/workspace/public/pm/pm-work-view.js +233 -146
- package/workspace/public/pm/shell-bell.js +3 -2
- package/workspace/public/pm/shell-recording.js +29 -8
- package/workspace/public/pm/tokens.css +2 -2
- package/workspace/public/pm/view-notes.js +46 -9
- package/workspace/public/pm/welcome.js +197 -89
- package/workspace/public/welcome.html +6 -4
- package/workspace/server.js +105 -6
- package/workspace/skills/day-check.skill +1 -1
- package/workspace/skills/jira-sync.skill +6 -4
- package/workspace/skills/morning-brief.skill +1 -1
- package/workspace/test-files.json +12 -3
- package/workspace/test-lists/c3-ib-items.json +9 -0
- package/workspace/test-lists/c3-ib-more.json +9 -0
- package/workspace/test-lists/c3-ib-triage-backlog.json +9 -0
- package/workspace/test-lists/c3-initiative-boards.json +6 -0
- package/workspace/test-lists/calendar-tidy-up.json +6 -0
- package/workspace/test-lists/console3-briefing.json +9 -0
- package/workspace/test-lists/console3-foundation.json +9 -0
- package/workspace/test-lists/console3-reports.json +3 -3
- package/workspace/test-lists/meeting-notes.json +10 -4
- package/workspace/test-lists/workspace-headless-jobs.json +5 -0
- package/workspace/test-lists/workspace-package-script-closure.json +6 -0
- package/workspace/lib/vendor/workspace/lib/actor.js +0 -91
- package/workspace/lib/vendor/workspace/lib/board-cache.js +0 -156
- package/workspace/lib/vendor/workspace/lib/console-state.js +0 -295
- package/workspace/lib/vendor/workspace/lib/factory-join.js +0 -158
- package/workspace/lib/vendor/workspace/lib/git-info.js +0 -306
- package/workspace/lib/vendor/workspace/lib/plan-items.js +0 -922
- package/workspace/lib/vendor/workspace/lib/plan-tree.js +0 -419
- package/workspace/lib/vendor/workspace/lib/review-gate.js +0 -39
- package/workspace/lib/vendor/workspace/lib/sink.js +0 -321
- 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
|
-
|
|
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
|
}
|