create-pmos 0.52.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.
- package/package.json +1 -1
- package/payload/KIT-VERSION +2 -2
- package/payload/mods/pmos-cockpit/README.md +13 -0
- package/payload/mods/pmos-cockpit/hooks/lib/commands.mjs +2 -1
- package/payload/mods/pmos-cockpit/hooks/lib/grants.mjs +41 -11
- package/payload/mods/pmos-cockpit/hooks/lib/guard.mjs +228 -8
- package/payload/mods/pmos-cockpit/hooks/register.tsx +11 -3
- package/payload/planning/evals/eval-calibration.md +1 -1
- package/payload/planning/okrs/health-budgets.md +1 -1
- package/payload/scripts/plan-items-stage.js +271 -0
- package/payload/scripts/pmos-log.sh +18 -7
- package/payload/scripts/workflow-state.js +28 -2
- package/payload/state/discoveries.md +1 -1
- package/payload/state/log.md +1 -1
- package/workspace/bin/pmos.js +15 -1
- package/workspace/cut-stub.js +40 -0
- package/workspace/first-paint-audit.js +145 -0
- package/workspace/fixtures/capture/requirements/capture-2026-10-04-1.md +10 -0
- package/workspace/fixtures/initiatives-api/list.json +176 -0
- package/workspace/fixtures/initiatives-api/post-403.json +5 -0
- package/workspace/fixtures/initiatives-api/post-ok.json +10 -0
- package/workspace/fixtures/initiatives-api/roadmap.json +208 -0
- package/workspace/fixtures/initiatives-api/sheet.json +112 -0
- package/workspace/fixtures/report-api/draft.json +177 -0
- package/workspace/fixtures/reports-page/draft-biweekly-2026-10-16.md +97 -0
- package/workspace/fixtures/today-api/provider-rows.json +204 -0
- package/workspace/fixtures/today-api/seam-probe-kinds.json +5 -0
- package/workspace/guide/board.md +81 -0
- package/workspace/guide/breakdown.md +154 -0
- package/workspace/guide/command-palette.md +75 -0
- package/workspace/guide/index.md +27 -17
- package/workspace/guide/initiatives-roadmap.md +130 -0
- package/workspace/guide/initiatives-screen.md +89 -0
- package/workspace/guide/initiatives-timeline.md +57 -0
- package/workspace/guide/integrated-work.md +94 -0
- package/workspace/guide/knowledge-graph.md +3 -68
- package/workspace/guide/layout.md +98 -32
- package/workspace/guide/live-notes.md +3 -3
- package/workspace/guide/pm-only-acts.md +89 -0
- package/workspace/guide/pm-only-lines.md +61 -0
- package/workspace/guide/reports-page.md +80 -0
- package/workspace/guide/reports.md +73 -0
- package/workspace/guide/timeline.md +70 -0
- package/workspace/guide/today.md +85 -0
- package/workspace/guide/validate-with-typesafe.md +1 -1
- package/workspace/lib/actor.js +91 -0
- package/workspace/lib/board-cache.js +32 -2
- package/workspace/lib/board-cli.js +108 -0
- package/workspace/lib/board-fold.js +232 -0
- package/workspace/lib/breakdown-export.js +80 -0
- package/workspace/lib/capture.js +98 -0
- package/workspace/lib/engine/plan-items-stage.js +271 -0
- package/workspace/lib/engine/workflow-state.js +28 -2
- package/workspace/lib/factory-join.js +158 -0
- package/workspace/lib/grant-mint.js +113 -0
- package/workspace/lib/health-rules-factory.js +92 -0
- package/workspace/lib/health-rules-plan.js +164 -0
- package/workspace/lib/health.js +79 -0
- package/workspace/lib/initiative-cli.js +222 -0
- package/workspace/lib/initiative-display.js +183 -0
- package/workspace/lib/initiative-needs.js +127 -0
- package/workspace/lib/initiative-rows.js +206 -0
- package/workspace/lib/initiative-writer.js +141 -0
- package/workspace/lib/issues.js +206 -0
- package/workspace/lib/item-cli.js +195 -0
- package/workspace/lib/item-spans.js +137 -0
- package/workspace/lib/measure-cli.js +100 -0
- package/workspace/lib/measurements.js +189 -0
- package/workspace/lib/mobile-nav.js +57 -53
- package/workspace/lib/needs-providers.js +120 -0
- package/workspace/lib/placements.js +440 -0
- package/workspace/lib/plan-items.js +922 -0
- package/workspace/lib/plan-ledgers.js +85 -0
- package/workspace/lib/plan-rules.js +72 -0
- package/workspace/lib/plan-tree.js +367 -0
- package/workspace/lib/pm-guard.js +174 -0
- package/workspace/lib/pm-lines-needs.js +331 -0
- package/workspace/lib/pmos-verbs.js +66 -0
- package/workspace/lib/proactive.js +7 -4
- package/workspace/lib/report-cli.js +152 -0
- package/workspace/lib/report-draft.js +579 -0
- package/workspace/lib/report-needs.js +213 -0
- package/workspace/lib/route-modules.js +128 -0
- package/workspace/lib/routes-board.js +91 -0
- package/workspace/lib/routes-capture.js +52 -0
- package/workspace/lib/routes-initiatives.js +371 -0
- package/workspace/lib/routes-reports.js +163 -0
- package/workspace/lib/routes-timeline.js +197 -0
- package/workspace/lib/routes-today.js +32 -0
- package/workspace/lib/today-cli.js +99 -0
- package/workspace/lib/today.js +333 -0
- package/workspace/lib/triage.js +163 -0
- package/workspace/lib/verify-work-cli.js +81 -0
- package/workspace/lib/work-check-needs.js +99 -0
- package/workspace/package-lock.json +1 -1
- package/workspace/package.json +4 -5
- package/workspace/public/index.html +29 -19
- package/workspace/public/pm/app.js +299 -30
- package/workspace/public/pm/bd-board.js +113 -0
- package/workspace/public/pm/bd-drag.js +59 -0
- package/workspace/public/pm/bd-model.js +152 -0
- package/workspace/public/pm/bd-timeline.js +233 -0
- package/workspace/public/pm/bd-tree.js +244 -0
- package/workspace/public/pm/board-copy.js +57 -0
- package/workspace/public/pm/breakdown-api.js +58 -0
- package/workspace/public/pm/breakdown-copy.js +138 -0
- package/workspace/public/pm/components.css +3054 -0
- package/workspace/public/pm/cycle-review.js +125 -0
- package/workspace/public/pm/data.js +40 -187
- package/workspace/public/pm/dest-board.js +438 -0
- package/workspace/public/pm/dest-initiatives.js +134 -0
- package/workspace/public/pm/dest-reports.js +270 -0
- package/workspace/public/pm/dest-settings.js +217 -0
- package/workspace/public/pm/dest-today.js +176 -0
- package/workspace/public/pm/dialogs.js +88 -0
- package/workspace/public/pm/display-word.js +56 -0
- package/workspace/public/pm/dock.js +105 -0
- package/workspace/public/pm/fixture.js +8 -227
- package/workspace/public/pm/frame-copy.js +94 -0
- package/workspace/public/pm/handoff-box.js +82 -0
- package/workspace/public/pm/http.js +88 -0
- package/workspace/public/pm/icons.js +53 -0
- package/workspace/public/pm/initiative-list.js +218 -0
- package/workspace/public/pm/initiative-sheet.js +261 -0
- package/workspace/public/pm/initiatives-api.js +59 -0
- package/workspace/public/pm/initiatives-copy.js +215 -0
- package/workspace/public/pm/initiatives-timeline-copy.js +59 -0
- package/workspace/public/pm/initiatives-timeline.js +410 -0
- package/workspace/public/pm/initiatives-ui.js +123 -0
- package/workspace/public/pm/item-sheet.js +251 -0
- package/workspace/public/pm/keep-card.js +204 -0
- package/workspace/public/pm/lifecycle.js +7 -1
- package/workspace/public/pm/mobile.css +49 -20
- package/workspace/public/pm/mobile.js +157 -29
- package/workspace/public/pm/modes-live.js +7 -883
- package/workspace/public/pm/modes.js +32 -1024
- package/workspace/public/pm/new-initiative-sheet.js +74 -0
- package/workspace/public/pm/next-step-ui.js +3 -2
- package/workspace/public/pm/palette-copy.js +51 -0
- package/workspace/public/pm/palette.js +312 -0
- package/workspace/public/pm/panel-breakdown.js +702 -0
- package/workspace/public/pm/panel-cockpit.js +63 -295
- package/workspace/public/pm/panel-detail.js +25 -172
- package/workspace/public/pm/panel-initiatives.js +1 -19
- package/workspace/public/pm/panel-repos.js +31 -81
- package/workspace/public/pm/panel-tabs.js +197 -110
- package/workspace/public/pm/panel-trees.js +5 -2
- package/workspace/public/pm/portfolio-report.js +61 -0
- package/workspace/public/pm/primitives.js +656 -0
- package/workspace/public/pm/print.css +33 -0
- package/workspace/public/pm/provider-cards.js +136 -0
- package/workspace/public/pm/registry.js +194 -0
- package/workspace/public/pm/release-card.js +110 -0
- package/workspace/public/pm/report-view.js +309 -0
- package/workspace/public/pm/reports-copy.js +114 -0
- package/workspace/public/pm/roadmap.js +271 -0
- package/workspace/public/pm/sig-watch.js +41 -0
- package/workspace/public/pm/state.js +8 -4
- package/workspace/public/pm/status-banner.js +13 -5
- package/workspace/public/pm/tab-doc.js +2 -4
- package/workspace/public/pm/tab-term.js +12 -2
- package/workspace/public/pm/tab-web.js +3 -2
- package/workspace/public/pm/timeline-copy.js +48 -0
- package/workspace/public/pm/today-cards.js +244 -0
- package/workspace/public/pm/today-copy.js +97 -0
- package/workspace/public/pm/tokens.css +16 -18
- package/workspace/public/pm/topbar.js +102 -0
- package/workspace/public/pm/triage-card.js +60 -0
- package/workspace/public/pm/undo-hold.js +103 -0
- package/workspace/public/pm/view-addrepo.js +2 -1
- package/workspace/public/pm/view-livenotes.js +3 -1
- package/workspace/public/pm/view-today.js +7 -162
- package/workspace/public/vendor/Sortable.min.js +2 -0
- package/workspace/public/vendor/lucide-sprite.js +79 -0
- package/workspace/replaced-tests.json +2864 -0
- package/workspace/run-tests.js +56 -5
- package/workspace/server.js +312 -36
- package/workspace/sheet-answer.js +61 -0
- package/workspace/skills/measure.skill +41 -0
- package/workspace/skills/report-biweekly.skill +23 -25
- package/workspace/skills/tracker-refresh.skill +50 -0
- package/workspace/test-files.json +19 -3
- package/workspace/test-lists/base.json +6 -0
- package/workspace/test-lists/run2-a.json +6 -0
- package/workspace/test-lists/run2-b.json +13 -0
- package/workspace/test-lists/run2-c.json +19 -0
- package/workspace/test-lists/run2-d.json +22 -0
- package/workspace/test-lists/run3-0.json +5 -0
- package/workspace/test-lists/run3-a.json +5 -0
- package/workspace/test-lists/run3-b.json +6 -0
- package/workspace/test-lists/run3-c.json +15 -0
- package/workspace/test-lists/run3-d.json +6 -0
- package/workspace/test-lists/run4-a.json +8 -0
- package/workspace/test-lists/run4-b.json +6 -0
- package/workspace/test-lists/run4-c.json +13 -0
- package/workspace/test-lists/run4-d.json +9 -0
- package/workspace/test-lists/run5-a.json +6 -0
- package/workspace/test-lists/run5-b.json +6 -0
- package/workspace/test-lists/run5-c.json +15 -0
- package/workspace/test-run.js +27 -1
- package/workspace/third-party/README.md +44 -0
- package/workspace/third-party/lucide-static-1.52.0.LICENSE +43 -0
- package/workspace/third-party/sortablejs-1.15.7.LICENSE +21 -0
- package/workspace/design-parity.js +0 -673
- package/workspace/public/pm/tab-task.js +0 -86
- package/workspace/public/pm/view-guide.js +0 -141
- package/workspace/public/pm/view-knowledge.js +0 -225
- package/workspace/public/pm/view-memory.js +0 -122
- package/workspace/public/pm/view-portfolio.js +0 -153
- package/workspace/public/pm/view-reports.js +0 -190
- package/workspace/public/pm/view-scheduled.js +0 -161
- package/workspace/public/pm/view-skills.js +0 -216
package/workspace/run-tests.js
CHANGED
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
*
|
|
25
25
|
* Output: a suite's own output is buffered and printed whole when it finishes, so lines from two
|
|
26
26
|
* suites never interleave. A passing suite prints its last lines; --verbose prints all of it.
|
|
27
|
+
*
|
|
28
|
+
* Fragments (pm-os-absorb Runs 2 to 5). Builders who work at the same time add their suites in a file
|
|
29
|
+
* of their own, test-lists/<name>.json, never in test-files.json: two slices that each append to the
|
|
30
|
+
* same JSON array always conflict. A fragment has the keys modules, panels, exclusive and seconds of
|
|
31
|
+
* test-files.json, plus `helpers` (a -test.js file that is a helper, not a suite, with the reason, as
|
|
32
|
+
* in ELSEWHERE). This file merges every fragment into the lists before it does anything else, so
|
|
33
|
+
* --check, --shard and every group see one list. A fragment that is not valid fails every command.
|
|
27
34
|
*/
|
|
28
35
|
const fs = require('fs');
|
|
29
36
|
const os = require('os');
|
|
@@ -31,7 +38,41 @@ const path = require('path');
|
|
|
31
38
|
const { spawn } = require('child_process');
|
|
32
39
|
|
|
33
40
|
const DIR = __dirname;
|
|
34
|
-
const
|
|
41
|
+
const FRAG_DIR = path.join(DIR, 'test-lists');
|
|
42
|
+
const FRAG_KEYS = ['_comment', 'modules', 'panels', 'exclusive', 'seconds', 'helpers'];
|
|
43
|
+
const fragProblems = [];
|
|
44
|
+
const fragHelpers = {};
|
|
45
|
+
/** test-files.json with every test-lists/*.json fragment merged in (see the header). Problems go to fragProblems. */
|
|
46
|
+
function loadFiles() {
|
|
47
|
+
const files = JSON.parse(fs.readFileSync(path.join(DIR, 'test-files.json'), 'utf8'));
|
|
48
|
+
let names = [];
|
|
49
|
+
try { names = fs.readdirSync(FRAG_DIR).filter((n) => n.endsWith('.json')).sort(); } catch { /* no fragments yet */ }
|
|
50
|
+
for (const n of names) {
|
|
51
|
+
const where = `test-lists/${n}`;
|
|
52
|
+
if (!/^[a-z0-9][a-z0-9-]*\.json$/.test(n)) fragProblems.push(`${where}: a fragment is named <lowercase-id>.json, for example run2-a.json`);
|
|
53
|
+
let frag;
|
|
54
|
+
try { frag = JSON.parse(fs.readFileSync(path.join(FRAG_DIR, n), 'utf8')); } catch (e) { fragProblems.push(`${where} is not valid JSON — ${e.message}`); continue; }
|
|
55
|
+
if (!frag || typeof frag !== 'object' || Array.isArray(frag)) { fragProblems.push(`${where} is not a JSON object`); continue; }
|
|
56
|
+
for (const k of Object.keys(frag)) if (!FRAG_KEYS.includes(k)) fragProblems.push(`${where}: unknown key "${k}" (the keys are ${FRAG_KEYS.slice(1).join(', ')})`);
|
|
57
|
+
for (const k of ['modules', 'panels', 'exclusive']) {
|
|
58
|
+
if (frag[k] === undefined) continue;
|
|
59
|
+
if (!Array.isArray(frag[k]) || !frag[k].every((f) => typeof f === 'string')) { fragProblems.push(`${where}: "${k}" is a list of file names`); continue; }
|
|
60
|
+
files[k] = [...(files[k] || []), ...frag[k]];
|
|
61
|
+
}
|
|
62
|
+
for (const [f, v] of Object.entries(frag.seconds || {})) {
|
|
63
|
+
if (typeof v !== 'number' || !(v > 0)) fragProblems.push(`${where}: seconds of ${f} is a positive number`);
|
|
64
|
+
else if (files.seconds && f in files.seconds) fragProblems.push(`${where}: seconds of ${f} is already recorded elsewhere`);
|
|
65
|
+
else files.seconds = { ...(files.seconds || {}), [f]: v };
|
|
66
|
+
}
|
|
67
|
+
for (const [f, why] of Object.entries(frag.helpers || {})) {
|
|
68
|
+
if (typeof why !== 'string' || !why.trim()) fragProblems.push(`${where}: helper ${f} needs a reason`);
|
|
69
|
+
else if (fragHelpers[f]) fragProblems.push(`${where}: helper ${f} is already named by ${fragHelpers[f].where}`);
|
|
70
|
+
else fragHelpers[f] = { why, where };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
const FILES = loadFiles();
|
|
35
76
|
const GROUPS = {
|
|
36
77
|
unit: [...FILES.unit, ...FILES.modules],
|
|
37
78
|
modules: FILES.modules,
|
|
@@ -43,7 +84,14 @@ const GROUPS = {
|
|
|
43
84
|
// Suites that run elsewhere on purpose, so --check does not count them as unwired.
|
|
44
85
|
const ELSEWHERE = {
|
|
45
86
|
'offline-tarball.test.js': 'npm run test:offline (needs a packed tarball)',
|
|
87
|
+
// A helper module, not a suite: the Breakdown suites require it (pm-os-absorb Run 1). Its name keeps it out of the
|
|
88
|
+
// tarball (BUNDLE_EXCLUDES has 'pm-*-test.js'), which is why it ends in -test.js.
|
|
89
|
+
'pm-breakdown-stub-test.js': 'not a suite — the helpers pm-breakdown-test.js, pm-breakdown-phone-test.js and first-paint-count.test.js require',
|
|
46
90
|
};
|
|
91
|
+
for (const [f, h] of Object.entries(fragHelpers)) {
|
|
92
|
+
if (ELSEWHERE[f]) fragProblems.push(`${h.where}: helper ${f} is already exempt in run-tests.js`);
|
|
93
|
+
else ELSEWHERE[f] = `${h.why} (${h.where})`;
|
|
94
|
+
}
|
|
47
95
|
const PER_FILE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
48
96
|
|
|
49
97
|
const args = process.argv.slice(2);
|
|
@@ -119,10 +167,11 @@ function changedSuites(list, ref) {
|
|
|
119
167
|
|
|
120
168
|
function check() {
|
|
121
169
|
const listed = new Set(GROUPS.all);
|
|
122
|
-
const problems = [];
|
|
170
|
+
const problems = [...fragProblems];
|
|
123
171
|
const dupes = GROUPS.all.filter((f, k) => GROUPS.all.indexOf(f) !== k);
|
|
124
|
-
for (const f of new Set(dupes)) problems.push(`${f} is listed more than once in test-files.json
|
|
125
|
-
for (const f of listed) if (!fs.existsSync(path.join(DIR, f))) problems.push(`${f} is listed in test-files.json but does not exist`);
|
|
172
|
+
for (const f of new Set(dupes)) problems.push(`${f} is listed more than once in test-files.json and test-lists/`);
|
|
173
|
+
for (const f of listed) if (!fs.existsSync(path.join(DIR, f))) problems.push(`${f} is listed in test-files.json or test-lists/ but does not exist`);
|
|
174
|
+
for (const f of Object.keys(ELSEWHERE)) if (listed.has(f)) problems.push(`${f} is exempt as a helper but is also listed as a suite`);
|
|
126
175
|
for (const f of FILES.exclusive || []) if (!listed.has(f)) problems.push(`${f} is marked exclusive but is in no test list`);
|
|
127
176
|
const onDisk = fs.readdirSync(DIR).filter((f) => f === 'test.js' || /(\.test\.(js|mjs)|-test\.js)$/.test(f));
|
|
128
177
|
for (const f of onDisk) if (!listed.has(f) && !ELSEWHERE[f]) problems.push(`${f} is a suite on disk that no test list runs. Add it to test-files.json.`);
|
|
@@ -131,7 +180,8 @@ function check() {
|
|
|
131
180
|
if (parts.length !== GROUPS[g].length || new Set(parts).size !== GROUPS[g].length) problems.push(`--shard does not partition "${g}" into ${n}`);
|
|
132
181
|
}
|
|
133
182
|
if (problems.length) { for (const p of problems) console.error(`✗ ${p}`); process.exitCode = 1; return; }
|
|
134
|
-
|
|
183
|
+
const frags = fs.existsSync(FRAG_DIR) ? fs.readdirSync(FRAG_DIR).filter((n) => n.endsWith('.json')).length : 0;
|
|
184
|
+
console.log(`✓ ${listed.size} suites listed, each once, each on disk; ${onDisk.filter((f) => !ELSEWHERE[f]).length} suites on disk, all listed; shards partition every group; ${frags} fragment(s) in test-lists/.`);
|
|
135
185
|
}
|
|
136
186
|
|
|
137
187
|
function runOne(file, verbose) {
|
|
@@ -159,6 +209,7 @@ function runOne(file, verbose) {
|
|
|
159
209
|
|
|
160
210
|
async function main() {
|
|
161
211
|
if (flag('check')) return check();
|
|
212
|
+
if (fragProblems.length) { for (const p of fragProblems) console.error(`✗ ${p}`); process.exitCode = 2; return; }
|
|
162
213
|
if (!group || !GROUPS[group]) {
|
|
163
214
|
console.error(`usage: node run-tests.js <${Object.keys(GROUPS).join('|')}> [--jobs=N] [--shard=I/N] [--list] [--verbose]\n node run-tests.js --check`);
|
|
164
215
|
process.exitCode = 2; return;
|