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.
- package/package.json +1 -1
- package/payload/KIT-VERSION +1 -1
- 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/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/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 +4 -3
- package/workspace/lib/routes-c3-life.js +2 -1
- package/workspace/lib/routes-c3-reports.js +96 -13
- package/workspace/lib/routes-c3-strategy.js +4 -3
- 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 +3 -2
- 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 +5 -4
- 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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* file draws only the frame and composes the real views into it, each through its own mount function:
|
|
4
4
|
* Briefing one column, the brief: the deck (mountBriefing), Today (c3-brief-today.js), Needs you (c3-brief-needs.js), Portfolio pulse (c3-brief-pulse.js)
|
|
5
5
|
* right the dock (c3-dock.js): the repository, branch and session tree, the selected session's detail, "Open the session" to /
|
|
6
|
-
*
|
|
6
|
+
* Initiatives and Reports also carry the mockup's "Plan: Decide what gates the day" lens row and deck (c3-plan.js planNode).
|
|
7
7
|
* Calendar mountCalendarViews Work mountPmWork
|
|
8
8
|
* Initiatives a switch among mountLifecycle, mountForecast and mountReleases Reports mountReportFamilies, mountOutbox
|
|
9
9
|
* The bell, the ticker, the banner and the recording group are the shell-*.js modules. The old app (/) is not touched.
|
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
* The workspace id is ?ws= (default: the first of GET /api/workspaces). The views read some routes without a ws, so a GET to /api/
|
|
12
12
|
* that names none gets the page's ws added (see withWs). No dialog is used. Presses are the views' own. */
|
|
13
13
|
import { el } from './dom.js';
|
|
14
|
-
import { row } from './primitives.js';
|
|
14
|
+
import { row, button } from './primitives.js';
|
|
15
15
|
import { pmGet } from './http.js';
|
|
16
16
|
import { ensureC3Css, c3ic, c3Phone, mountPmWork } from './pm-work-view.js';
|
|
17
17
|
import { mountBriefing, showCard, flipBack } from './briefing-deck.js';
|
|
18
18
|
import { mountCalendarViews } from './calendar-views.js';
|
|
19
19
|
import { todaySection } from './c3-brief-today.js';
|
|
20
|
-
import { needsSection } from './c3-brief-needs.js';
|
|
20
|
+
import { needsSection, needsCount } from './c3-brief-needs.js';
|
|
21
21
|
import { pulse } from './c3-brief-pulse.js';
|
|
22
|
-
import { loadBriefPage } from './c3-brief-data.js';
|
|
22
|
+
import { loadBriefPage, onBriefPage } from './c3-brief-data.js';
|
|
23
23
|
import { mountLifecycle } from './lifecycle-lens.js';
|
|
24
24
|
import { mountForecast } from './timeline-forecast-view.js';
|
|
25
25
|
import { mountReleases } from './releases-view.js';
|
|
26
26
|
import { mountReportFamilies } from './report-families-view.js';
|
|
27
|
-
import { mountReports } from './c3-reports.js';
|
|
27
|
+
import { mountReports, showReportsView } from './c3-reports.js';
|
|
28
28
|
import { mountOutbox } from './outbox-panel.js';
|
|
29
29
|
import { createDock } from './c3-dock.js';
|
|
30
30
|
import { reviewSection, handledRow, trustCard, footLine, rowApi, BX, toast, setNeedsTitle, hooks as briefHooks } from './c3-brief.js';
|
|
31
31
|
import { stopCard } from './c3-misc-panels.js';
|
|
32
32
|
import { openSheet } from './c3-sheet.js';
|
|
33
33
|
import { mountCalPopupTrigger } from './c3-calpop.js';
|
|
34
|
-
import { planNode,
|
|
34
|
+
import { planNode, dueCard, crossLinks, newInitLine, portfolioCard } from './c3-plan.js';
|
|
35
35
|
import { initiativesViewCtx } from './registry.js';
|
|
36
36
|
import { mount as mountRoadmap } from './c3-roadmap.js';
|
|
37
37
|
import { mount as mountBreakdown } from './c3-breakdown.js';
|
|
@@ -40,13 +40,16 @@ import { mount as mountTickets, badge as ticketsBadge } from './c3-tickets.js';
|
|
|
40
40
|
import { mount as mountDocs, badge as docsBadge } from './c3-docs.js';
|
|
41
41
|
import { mount as mountSignals, badge as signalsBadge } from './c3-signals.js';
|
|
42
42
|
import { mountDaypart } from './c3-daypart.js';
|
|
43
|
+
import { mountAmbient } from './c3-ambient.js';
|
|
43
44
|
import { mountTicker } from './shell-ticker.js';
|
|
44
45
|
import { mountBell, openBellList } from './shell-bell.js';
|
|
45
46
|
import { onBriefing, loadBriefing } from './shell-ticker.js';
|
|
46
47
|
import { registry, filterPalette, rowStep } from './briefing-model.js';
|
|
47
48
|
import { freshnessLine } from './freshness-line.js';
|
|
49
|
+
import { mountInitiatives } from './c3-initiatives.js';
|
|
50
|
+
import { mountSettings, gearIcon, applyLook } from './c3-settings.js';
|
|
48
51
|
|
|
49
|
-
/* In demo mode each tab's deck asks for its own cards (the mockup draws a different deck per tab); real mode sends no scope. */
|
|
52
|
+
/* In demo mode each tab's deck asks for its own cards (the mockup draws a different deck per tab); real mode sends no scope. Reports always sends its own (repTab). */
|
|
50
53
|
const sc = (name) => (DEMO ? name : undefined);
|
|
51
54
|
const TABS = [['brief', 'Briefing', 'sun'], ['cal', 'Calendar', 'cal'], ['work', 'Work', 'todo'], ['init', 'Initiatives', 'init'], ['rep', 'Reports', 'report']];
|
|
52
55
|
/* The mockup's eight Initiatives views, in its order: Lifecycle, Roadmap, Breakdown, Timeline (= Forecast), Tickets, Releases, Documents, Signals. */
|
|
@@ -74,12 +77,17 @@ function withWs() {
|
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
/* t is light, dark or system (Settings, Appearance); system follows the computer and changes with it. */
|
|
81
|
+
const darkQuery = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;
|
|
77
82
|
function setTheme(t) {
|
|
78
|
-
S.
|
|
83
|
+
S.themePref = t === 'dark' || t === 'system' ? t : 'light';
|
|
84
|
+
S.theme = S.themePref === 'system' ? (darkQuery && darkQuery.matches ? 'dark' : 'light') : S.themePref;
|
|
79
85
|
document.documentElement.setAttribute('data-pm-page-theme', S.theme);
|
|
80
86
|
S.root.setAttribute('data-pm-theme', S.theme);
|
|
81
|
-
store.set(THEME_KEY, S.
|
|
87
|
+
store.set(THEME_KEY, S.themePref);
|
|
88
|
+
if (S.settings && S.settingsCtx) { S.settingsCtx.theme = S.theme; S.settingsCtx.themePref = S.themePref; }
|
|
82
89
|
}
|
|
90
|
+
if (darkQuery && darkQuery.addEventListener) darkQuery.addEventListener('change', () => { if (S.themePref === 'system' && S.root) setTheme('system'); });
|
|
83
91
|
|
|
84
92
|
/* ── header: the mockup's .top (title, date line) and .tools (terminal, recording, bell, search, more) ── */
|
|
85
93
|
const dateLine = () => {
|
|
@@ -94,9 +102,9 @@ function header() {
|
|
|
94
102
|
S.ttl = el('h1', { 'data-c3pg': 'title' });
|
|
95
103
|
S.sub = el('div', { class: 'sub', 'data-c3pg': 'date' }, dateLine());
|
|
96
104
|
S.termBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'term-count' }, '0');
|
|
97
|
-
/* the AGENT button (the
|
|
98
|
-
S.termBtn =
|
|
99
|
-
|
|
105
|
+
/* the AGENT button (the bolt glyph, as the mockup's Sessions pill): the Terminal page, the full agent surfaces, with the needs-you badge. The dock's own button is the TERMINAL glyph (c3-terminal-icons.js); Ctrl J and the More menu fold the dock. */
|
|
106
|
+
S.termBtn = button({ variant: 'ghost', label: [ic('bolt', 'sm'), 'Sessions', S.termBdg], onClick: () => { import('./c3-terminal.js').then((m) => m.openTerminalPage()); },
|
|
107
|
+
attrs: { class: 'psess', title: 'Agent surfaces: sessions, results to accept, questions for you', 'aria-label': 'Agent surfaces: sessions, results to accept, questions for you', 'aria-haspopup': 'dialog', 'data-c3pg': 'agent-button' } }); // the mockup's header button (agent-surfaces.html #act)
|
|
100
108
|
S.tools = el('div', { class: 'tools', 'data-c3pg': 'tools' });
|
|
101
109
|
if (S.demoMod) S.tools.append(S.demoMod.demoPill());
|
|
102
110
|
S.tools.append(S.termBtn);
|
|
@@ -104,6 +112,9 @@ function header() {
|
|
|
104
112
|
S.tools.append(S.bellHost);
|
|
105
113
|
S.tools.append(ibtn('Search (Ctrl K)', 'search', { 'data-c3pg': 'search', 'aria-haspopup': 'dialog', onclick: () => openPalette() }));
|
|
106
114
|
mountCalPopupTrigger(S.tools); // the calendar button (before Search) and the key C (c3-calpop.js)
|
|
115
|
+
/* Settings is a page of its own, not a tab: the gear opens it, as do the More menu, the palette and ?tab=settings (c3-settings.js). */
|
|
116
|
+
S.gearBtn = ibtn('Settings', 'info', { 'data-c3pg': 'settings', onclick: () => showTab('settings', true) }); S.gearBtn.replaceChildren(gearIcon());
|
|
117
|
+
S.tools.append(S.gearBtn);
|
|
107
118
|
S.moreBtn = ibtn('More', 'more', { 'aria-haspopup': 'menu', 'aria-expanded': 'false', 'data-c3pg': 'more', onclick: toggleMore });
|
|
108
119
|
S.tools.append(el('span', { class: 'c3pg-menuwrap' }, S.moreBtn));
|
|
109
120
|
/* workspace-data-freshness R9: how old the sources are, quiet when they are up to date (freshness-line.js) */
|
|
@@ -123,6 +134,7 @@ function toggleMore() {
|
|
|
123
134
|
item('spark', 'Agent playbooks', () => openPlaybooks(), false, { 'data-a': 'pbopen' }),
|
|
124
135
|
item('phone', 'Phone preview', () => togglePreview(), !!S.preview, { 'data-a': 'phone' }),
|
|
125
136
|
item(S.theme === 'dark' ? 'sun' : 'moon', S.theme === 'dark' ? 'Light theme' : 'Dark theme', () => setTheme(S.theme === 'dark' ? 'light' : 'dark')),
|
|
137
|
+
((b) => { b.firstChild.replaceWith(gearIcon('sm')); return b; })(item('info', 'Settings', () => showTab('settings', true), false, { 'data-a': 'settings' })),
|
|
126
138
|
item('term', S.dockOpen ? 'Fold the dock' : 'Open the dock', () => { S.dockOpen = !S.dockOpen; syncDock(); }, false, { 'data-a': 'dockt' }, 'Ctrl J'),
|
|
127
139
|
el('a', { class: 'c3pg-mi', role: 'menuitem', href: '/' }, c3ic('term', 'sm'), el('span', null, 'Open the main app')));
|
|
128
140
|
S.root.append(S.menu); // on the page root with position:fixed, so no ancestor's overflow, transform or stacking order can hide it
|
|
@@ -226,9 +238,13 @@ function openPlaybooks() {
|
|
|
226
238
|
function tabBar() {
|
|
227
239
|
S.tabBtns = {};
|
|
228
240
|
const nav = el('nav', { class: 'c3tabs', role: 'tablist', 'aria-label': 'Places' });
|
|
229
|
-
S.workBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'work-count' }, '0');
|
|
241
|
+
S.workBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'work-count', title: 'Inbox to decide' }, '0');
|
|
242
|
+
S.briefBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'brief-count', title: 'Needs you' }, '0');
|
|
243
|
+
S.initBdg = el('span', { class: 'bdg', hidden: true, 'data-c3pg': 'init-count', title: 'New asks to triage' }, '0');
|
|
244
|
+
const BDG = { brief: S.briefBdg, work: S.workBdg, init: S.initBdg };
|
|
230
245
|
for (const [id, label, icon] of TABS) {
|
|
231
246
|
const b = el('button', { type: 'button', role: 'tab', id: 'c3tab-' + id, 'aria-controls': 'c3pane-' + id, 'data-c3-tab': id, onclick: () => showTab(id, true) }, c3ic(icon), label, id === 'work' ? S.workBdg : null);
|
|
247
|
+
if (BDG[id] && id !== 'work') b.append(BDG[id]);
|
|
232
248
|
S.tabBtns[id] = b;
|
|
233
249
|
nav.append(b);
|
|
234
250
|
}
|
|
@@ -243,41 +259,47 @@ function tabBar() {
|
|
|
243
259
|
return nav;
|
|
244
260
|
}
|
|
245
261
|
function moveInd() {
|
|
262
|
+
if (S.ind) S.ind.hidden = !S.tabBtns[S.tab];
|
|
246
263
|
const b = S.tabBtns[S.tab]; if (!b || !S.ind) return;
|
|
247
264
|
S.ind.style.width = b.offsetWidth + 'px'; S.ind.style.transform = 'translateX(' + b.offsetLeft + 'px)';
|
|
248
265
|
}
|
|
249
266
|
|
|
250
|
-
/* ── the Briefing tab:
|
|
251
|
-
*
|
|
252
|
-
*
|
|
267
|
+
/* ── the Briefing tab: two columns, decisions and reads ──
|
|
268
|
+
* Left: the stance bar with the day-part switch and the headline deck (briefing-deck.js), then Needs you (c3-brief-needs.js).
|
|
269
|
+
* Right: Today (c3-brief-today.js) and Portfolio pulse (c3-brief-pulse.js). Review lives in Work's Review lens; Handled, What I could stop and
|
|
270
|
+
* Data you can lean on live in Reports > Drafts (console3-briefing-parity, PM decision 1). The ribbon and the embedded calendar are not here:
|
|
271
|
+
* the calendar is the Calendar tab. */
|
|
253
272
|
function briefTab(pane) {
|
|
254
|
-
const
|
|
273
|
+
const left = el('div', { class: 'bcol l' });
|
|
274
|
+
const right = el('div', { class: 'bcol r' });
|
|
255
275
|
const deckHost = el('div', { 'data-c3pg': 'deck-host' });
|
|
256
|
-
const
|
|
257
|
-
S.deckHost = deckHost;
|
|
276
|
+
const ftHost = el('div');
|
|
277
|
+
S.deckHost = deckHost; S.needsBox = null;
|
|
258
278
|
let sig = '';
|
|
259
|
-
onBriefing((b) => { //
|
|
260
|
-
const g = JSON.stringify(
|
|
279
|
+
onBriefing((b) => { // the briefing's own foot line, when it carries one (the demo's). Built again only when it changed.
|
|
280
|
+
const g = JSON.stringify(b && b.foot);
|
|
261
281
|
if (g === sig) return; sig = g;
|
|
262
|
-
|
|
263
|
-
stHost.replaceChildren(...[stopCard(b && b.stop)].filter(Boolean)); trHost.replaceChildren(...(b && b.trust ? [trustCard(b.trust)] : [])); ftHost.replaceChildren(...(b && b.foot ? [footLine(b.foot)] : []));
|
|
282
|
+
ftHost.replaceChildren(...(b && b.foot ? [footLine(b.foot)] : []));
|
|
264
283
|
if (S.why) whyMark();
|
|
265
284
|
});
|
|
266
285
|
S.needsBox = needsSection(S);
|
|
267
|
-
|
|
268
|
-
|
|
286
|
+
left.append(deckHost, S.needsBox);
|
|
287
|
+
right.append(todaySection(), pulse(S));
|
|
288
|
+
pane.append(el('div', { class: 'brief' }, el('div', { class: 'bcols' }, left, right), ftHost));
|
|
269
289
|
mountBriefing(deckHost, { noTicker: true, onLens: lensChanged });
|
|
270
290
|
loadBriefPage();
|
|
271
291
|
}
|
|
272
292
|
|
|
273
|
-
/* The day-part switch: Reflect
|
|
293
|
+
/* The day-part switch: Reflect names Needs you "Carries over" (the mockup's vBrief, line 1470). */
|
|
274
294
|
function lensChanged(l) {
|
|
275
|
-
|
|
295
|
+
setNeedsTitle(S.needsBox, l === 'Reflect');
|
|
276
296
|
}
|
|
277
297
|
|
|
278
298
|
/* ── global: where a notification goes, the person sheet, the palette and the keys ── */
|
|
279
299
|
/* A bell entry or the banner goes to its target (console3.html nopen, line 2530): the card to turn over, the row to open, or the sheet to show. */
|
|
280
300
|
function goTarget(t) {
|
|
301
|
+
/* a dashboard schedule's notice (routes-briefing.js notices): Reports, then its Drafts tab */
|
|
302
|
+
if (t && t.tab && BUILD[t.tab]) { showTab(t.tab, true); if (t.tab === 'rep' && t.view) showReportsView(t.view); return; }
|
|
281
303
|
showTab('brief', true);
|
|
282
304
|
if (!t) return;
|
|
283
305
|
if (t.card !== undefined && t.card !== null) { showCard(S.deckHost, t.card); return; }
|
|
@@ -313,7 +335,8 @@ function openPerson(k) {
|
|
|
313
335
|
/* the palette (console3.html palette, line 1944): one input, up to nine results across places, people, documents and sessions */
|
|
314
336
|
function paletteItems() {
|
|
315
337
|
const items = [{ label: 'Agent playbooks', kind: 'place', icon: 'spark', run: () => openPlaybooks() },
|
|
316
|
-
...TABS.map(([id, label, icon]) => ({ label, kind: 'place', icon, run: () => showTab(id, true) }))
|
|
338
|
+
...TABS.map(([id, label, icon]) => ({ label, kind: 'place', icon, run: () => showTab(id, true) })),
|
|
339
|
+
{ label: 'Settings', kind: 'place', icon: 'shield', run: () => showTab('settings', true) }];
|
|
317
340
|
for (const k of Object.keys(registry('people') || {})) { const p = registry('people')[k]; items.push({ label: p.n + ' · ' + p.role, kind: 'person', icon: 'user', run: () => openPerson(k) }); }
|
|
318
341
|
for (const d of registry('docs') || []) items.push({ label: d.n, kind: 'document', icon: d.icon || 'doc', run: () => { showTab('init', true); const b = S.initSeg && S.initSeg.querySelector('[data-c3-init="documents"]'); if (b) b.click(); } });
|
|
319
342
|
for (const x of S.palSessions || []) items.push({ label: (x.branch || x.tree || '') ? ((x.branch || String(x.tree).split('/').pop()) + ' · ' + x.name) : x.name, kind: 'session', icon: 'branch', run: () => openSession(x) });
|
|
@@ -474,12 +497,24 @@ function showInit(id) {
|
|
|
474
497
|
}
|
|
475
498
|
}
|
|
476
499
|
}
|
|
477
|
-
|
|
500
|
+
/* Reports: the headline deck on top (the Plan deck of the Reports scope), the tabs, and on Drafts what the Briefing no longer carries
|
|
501
|
+
* (Handled, What I could stop, Data you can lean on) above "Reports to send" (the old families, their claims check and the outbox). */
|
|
502
|
+
/* The Reports deck always names its scope, so real mode gets the engine's report signals and never the Briefing's cards (console3-deck-flow-fixes). */
|
|
503
|
+
function repTab(pane) { mountReports(pane, { ws: S.ws, pmGet, deck: (h) => h.append(planNode('rep')), more: draftsMore, drafts: draftsTab }); }
|
|
504
|
+
function draftsMore(host) {
|
|
505
|
+
let sig = '';
|
|
506
|
+
onBriefing((b) => { // the same cards and the same condition as the Briefing had: only what the briefing carries (the demo's); redrawn only when it changed, so an open row stays open
|
|
507
|
+
const g = JSON.stringify([b && b.handled, b && b.stop, b && b.trust]);
|
|
508
|
+
if (g === sig) return; sig = g;
|
|
509
|
+
host.replaceChildren(...[b && b.handled ? handledRow(b.handled) : null, stopCard(b && b.stop), b && b.trust ? trustCard(b.trust) : null].filter(Boolean));
|
|
510
|
+
});
|
|
511
|
+
loadBriefing();
|
|
512
|
+
}
|
|
478
513
|
function draftsTab(pane) {
|
|
479
514
|
const fam = el('div', { 'data-c3pg': 'families-host' }); const out = el('div', { class: 'brief', 'data-c3pg': 'outbox-host', style: 'margin-top:var(--sp-4)' });
|
|
480
515
|
pane.append(fam, out);
|
|
481
516
|
pmGet('/api/report-families/facts?ws=' + encodeURIComponent(S.ws)).then((j) => {
|
|
482
|
-
mountReportFamilies(fam, { reportFacts: j && j.ok ? j.facts : {}, plan:
|
|
517
|
+
mountReportFamilies(fam, { reportFacts: j && j.ok ? j.facts : {}, plan: null, portfolio: portfolioCard() });
|
|
483
518
|
mountOutbox(out, {});
|
|
484
519
|
/* The mockup's Reports draw the outbox's drafts under Communications only (the Messages queue); the other families have no outbox. */
|
|
485
520
|
const sync = () => { out.hidden = !fam.querySelector('[data-family="communications"][aria-pressed="true"]'); };
|
|
@@ -487,25 +522,50 @@ function draftsTab(pane) {
|
|
|
487
522
|
});
|
|
488
523
|
}
|
|
489
524
|
|
|
490
|
-
const BUILD = { brief: briefTab, cal: (p) => mountCalendarViews(p, { view: 'week', page: true, scope: sc('cal') }), work: (p) => {
|
|
525
|
+
const BUILD = { brief: briefTab, cal: (p) => mountCalendarViews(p, { view: 'week', page: true, scope: sc('cal'), deck: planNode('cal', { bare: true }) }), work: (p) => { mountPmWork(p, { go: (t) => showTab(t, true) }); }, init: (p) => mountInitiatives(p, { ws: S.ws, workspaces: S.workspaces, demo: DEMO, showTab }), rep: repTab };
|
|
491
526
|
|
|
492
527
|
function showTab(id, push) {
|
|
493
|
-
if (!BUILD[id]) id = 'brief';
|
|
528
|
+
if (!BUILD[id] && id !== 'settings') id = 'brief';
|
|
494
529
|
S.tab = id;
|
|
495
530
|
for (const [t, label, icon] of TABS) {
|
|
496
531
|
const on = t === id;
|
|
497
|
-
S.tabBtns[t].setAttribute('aria-selected', String(on)); S.tabBtns[t].tabIndex = on ? 0 : -1;
|
|
532
|
+
S.tabBtns[t].setAttribute('aria-selected', String(on)); S.tabBtns[t].tabIndex = on ? 0 : (id === 'settings' && t === 'brief' ? 0 : -1);
|
|
498
533
|
S.panes[t].hidden = !on;
|
|
499
534
|
if (on) { S.ttl.replaceChildren(c3ic(icon, 'lg'), label); document.title = label + ' · PMOS console'; }
|
|
500
535
|
}
|
|
501
|
-
|
|
536
|
+
S.panes.settings.hidden = id !== 'settings';
|
|
537
|
+
if (S.gearBtn) S.gearBtn.setAttribute('aria-pressed', String(id === 'settings'));
|
|
538
|
+
if (id === 'settings') {
|
|
539
|
+
S.ttl.replaceChildren(gearIcon('lg'), 'Settings'); document.title = 'Settings · PMOS console';
|
|
540
|
+
if (!S.settings) { S.settingsCtx = { ws: S.ws, workspaces: S.workspaces, theme: S.theme, themePref: S.themePref, setTheme, goTab: (t) => showTab(t, true), section: q.get('section') || '', root: S.root }; S.settings = mountSettings(S.panes.settings, S.settingsCtx); }
|
|
541
|
+
else S.settings.refresh();
|
|
542
|
+
} else if (!S.mounted[id]) { S.mounted[id] = true; BUILD[id](S.panes[id]); }
|
|
502
543
|
S.root.dataset.tab = id;
|
|
503
544
|
S.dockOpen = S.wide && id === 'brief'; syncDock();
|
|
504
545
|
S.pageView.classList.remove('view'); void S.pageView.offsetWidth; S.pageView.classList.add('view');
|
|
505
546
|
moveInd();
|
|
547
|
+
if (push) S.userNav = true;
|
|
506
548
|
if (push) { try { const u = new URL(location.href); u.searchParams.set('tab', id); history.replaceState(null, '', u); } catch { /* no history */ } }
|
|
507
549
|
}
|
|
508
550
|
|
|
551
|
+
const setBdg = (b, n) => { b.textContent = String(n); b.hidden = !n; };
|
|
552
|
+
S.setNeedsBdg = (n) => { S.needsLive = true; setBdg(S.briefBdg, n); };
|
|
553
|
+
|
|
554
|
+
/* Tab badges. Briefing: the Needs you count (the section's own count once it is drawn; before that, the same rules over the briefing and the brief page).
|
|
555
|
+
* Initiatives: the new asks to triage, that is the captures an agent triaged and the PM has not added yet (GET /api/needs, kind triage); the demo has four. */
|
|
556
|
+
function briefCount() {
|
|
557
|
+
let b = null; let page = null;
|
|
558
|
+
const upd = () => { if (!S.needsLive) setBdg(S.briefBdg, needsCount(b, page)); };
|
|
559
|
+
onBriefing((x) => { b = x; upd(); }); onBriefPage((x) => { page = x; upd(); });
|
|
560
|
+
loadBriefing(); if (S.tab !== 'brief') loadBriefPage();
|
|
561
|
+
}
|
|
562
|
+
async function askCount() {
|
|
563
|
+
if (S.demo) { setBdg(S.initBdg, 4); return; }
|
|
564
|
+
const j = await pmGet('/api/needs?ws=' + encodeURIComponent(S.ws)).catch(() => null);
|
|
565
|
+
if (!j || !Array.isArray(j.needs)) return;
|
|
566
|
+
setBdg(S.initBdg, j.needs.filter((r) => r && r.kind === 'triage').length);
|
|
567
|
+
}
|
|
568
|
+
|
|
509
569
|
async function workCount() {
|
|
510
570
|
const j = await pmGet('/api/pm-items').catch(() => null);
|
|
511
571
|
if (!j || !j.ok || !j.lists) return;
|
|
@@ -533,10 +593,12 @@ async function boot() {
|
|
|
533
593
|
S.tickHost = el('div', { class: 'c3pg-tick', 'data-c3pg': 'ticker-host' });
|
|
534
594
|
S.pageView = el('div', { class: 'view' });
|
|
535
595
|
for (const [id] of TABS) { S.panes[id] = el('div', { class: 'c3pg-pane', role: 'tabpanel', id: 'c3pane-' + id, 'aria-labelledby': 'c3tab-' + id, hidden: true, 'data-c3-pane': id }); S.pageView.append(S.panes[id]); }
|
|
596
|
+
S.panes.settings = el('div', { class: 'c3pg-pane', role: 'region', 'aria-label': 'Settings', hidden: true, 'data-c3-pane': 'settings' }); S.pageView.append(S.panes.settings);
|
|
536
597
|
const main = el('div', { class: 'c3main' }, header(), S.tickHost, tabBar(), S.pageView);
|
|
537
598
|
S.grid = el('div', { class: 'c3grid' }, main, ...dock());
|
|
538
599
|
root.replaceChildren(S.grid);
|
|
539
600
|
mountDaypart(root, root.querySelector('.c3top'));
|
|
601
|
+
mountAmbient(root); // the ambient motion canvas, once, behind the grid
|
|
540
602
|
|
|
541
603
|
S.dock.setWorkspaces(S.workspaces, S.ws);
|
|
542
604
|
mountBell(S.bellHost, { go: (_, t) => goTarget(t) });
|
|
@@ -548,9 +610,13 @@ async function boot() {
|
|
|
548
610
|
S.narrow = matchMedia('(max-width:980px)');
|
|
549
611
|
S.narrow.addEventListener('change', () => { S.wide = !S.narrow.matches; S.dockOpen = S.wide && S.tab === 'brief'; syncDock(); });
|
|
550
612
|
S.wide = !S.narrow.matches;
|
|
551
|
-
|
|
613
|
+
/* The saved settings set the start page (look.start) when the address names no tab, and turn the time-of-day tint and strip off or on. */
|
|
614
|
+
let start = q.get('tab');
|
|
615
|
+
const saved = DEMO ? null : await pmGet('/api/settings' + (S.ws ? '?ws=' + encodeURIComponent(S.ws) : '')).catch(() => null); // demo mode's workspace is not registered
|
|
616
|
+
if (saved && saved.ok) { applyLook(root, saved.settings); if (!start) { const s = (saved.settings || []).find((x) => x.key === 'look.start'); if (s && BUILD[s.value]) start = s.value; } }
|
|
617
|
+
if (!S.userNav) showTab(start || 'brief', false); // a press during the read above (the gear, a tab) wins over the start page
|
|
552
618
|
new ResizeObserver(moveInd).observe(S.tabNav);
|
|
553
|
-
workCount(); S.dock.start();
|
|
619
|
+
workCount(); briefCount(); askCount(); S.dock.start();
|
|
554
620
|
setInterval(() => { S.sub.textContent = dateLine(); }, 30000);
|
|
555
621
|
}
|
|
556
622
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* pm/c3-terminal-icons.js — the icon language of the agent surfaces, and the few glyphs the console3 sprite does not hold.
|
|
2
2
|
*
|
|
3
3
|
* Two glyphs, never swapped (the mockups draw them apart: agent-surfaces.html and terminal-layout.html):
|
|
4
|
-
* AGENT `
|
|
4
|
+
* AGENT `bolt` (the mockup's i-bolt) the agent surfaces: sessions that need you, results to accept. Header button (with the needs-you badge) and the
|
|
5
5
|
* dock's "Agent surfaces" button. It also means "the agent acts" everywhere else on the page (swipe right, suggested move).
|
|
6
6
|
* TERMINAL `term` (`>_`) a real session's terminal: the dock rail button, a session's "Open the session" link, a session row's mark.
|
|
7
7
|
* AGENT = "the interface that reads sessions for you". TERMINAL = "the raw CLI session". A button shows one or the other, with its own tooltip.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* another module already added is not added again. */
|
|
11
11
|
import { c3ic } from './pm-work-view.js';
|
|
12
12
|
|
|
13
|
-
export const ICON = { agent: '
|
|
13
|
+
export const ICON = { agent: 'bolt', terminal: 'term' }; // the mockup's header Sessions pill draws the bolt glyph; the rail draws the terminal glyph
|
|
14
14
|
export const TIPS = {
|
|
15
15
|
agentHeader: (n) => (n ? 'Agent surfaces: ' + n + (n === 1 ? ' session needs you' : ' sessions need you') : 'Agent surfaces: sessions, results to accept, questions for you'),
|
|
16
16
|
agentDock: 'Agent surfaces: the full page of sessions that need you',
|
|
@@ -13,7 +13,7 @@ import { source, isDemo } from './c3-terminal-data.js';
|
|
|
13
13
|
import { mountSessions, disposeSessions } from './sessions-panel.js';
|
|
14
14
|
import { mountEdge, disposeEdge } from './c3-terminal-edge.js';
|
|
15
15
|
|
|
16
|
-
const TABS = [['sessions', 'Sessions', '
|
|
16
|
+
const TABS = [['sessions', 'Sessions', 'bolt'], ['edge', 'Edge cases', 'alert']];
|
|
17
17
|
const NEXT = [['', 'replies normally'], ['noresult', 'ends with no result'], ['rejected', 'is unreadable'], ['quiet', 'goes quiet'], ['unlabelled', 'has an unlabelled claim'], ['prose', 'answers in plain text'], ['attention', 'needs a sign-in'], ['crashed', 'crashes']];
|
|
18
18
|
let sheet = null;
|
|
19
19
|
|
|
@@ -45,7 +45,7 @@ export async function openTerminalPage(o = {}) {
|
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
const body = [el('div', { class: 'c3 c3e c3t c3t-page', 'data-c3t': 'page' }, el('div', { class: 'chips2', style: 'justify-content:space-between' }, seg, demoBar), note, host)];
|
|
48
|
-
const s = openSheet({ title: 'Agent surfaces', icon: '
|
|
48
|
+
const s = openSheet({ title: 'Agent surfaces', icon: 'bolt', dw: true, body, onClose: () => { disposeSessions(host); disposeEdge(host); sheet = null; } });
|
|
49
49
|
sheet = s;
|
|
50
50
|
await draw();
|
|
51
51
|
return s;
|
|
@@ -31,7 +31,7 @@ const IX = () => (typeof window !== 'undefined' && window.__c3calix) || null;
|
|
|
31
31
|
const baseId = (e) => String((e && e.id) || '').split('@')[0];
|
|
32
32
|
const gotoTab = (id) => { const b = document.querySelector('[data-c3-tab="' + id + '"]'); if (b) b.click(); };
|
|
33
33
|
const isC3 = (r) => !!(r && r.ctx && (r.ctx.ribbon || r.ctx.plan || r.ctx.page));
|
|
34
|
-
const isCalTab = (x) => !!(x && x.ctx && (x.ctx.plan || x.ctx.page)); // the Calendar tab's own instance (the older mount passes plan, the page passes page)
|
|
34
|
+
const isCalTab = (x) => !!(x && x.ctx && (x.ctx.plan || (x.ctx.page && !x.ctx.overlay))); // the Calendar tab's own instance (the older mount passes plan, the page passes page)
|
|
35
35
|
|
|
36
36
|
const NS = 'http://www.w3.org/2000/svg';
|
|
37
37
|
const VIEWS = [['day', 'Day'], ['week', 'Week'], ['month', 'Month'], ['quarter', 'Quarter'], ['year', 'Year']];
|