create-pmos 0.215.0 → 0.217.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/c3-sessions-panel-test.js +18 -0
- package/workspace/guide/console3-sessions.md +1 -1
- package/workspace/guide/my-work.md +1 -1
- package/workspace/package-lock.json +2 -2
- package/workspace/package.json +1 -1
- package/workspace/public/pm/c3-case.js +8 -2
- package/workspace/public/pm/console3.css +8 -2
- package/workspace/public/pm/pm-work-view.js +10 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pmos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.217.0",
|
|
4
4
|
"description": "Scaffold the PMOS portable kit — run the PMOS product-management workflow (initiative → lane-fit spec → contract → build → three gates, with work-type lanes for features, research, maintenance, incidents, and content) entirely inside your own repo, with all state as git-versioned files. Includes `workflow-sweep`, which audits the state every board derives from and separates real defects from work you simply have not done. `create-pmos workspace` also installs + launches the local Terminal Workspace GUI. No database, no network, no telemetry.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
package/payload/KIT-VERSION
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Eval calibration log"
|
|
4
4
|
description: "Append-only record of every PM override of an evaluator verdict."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T04:36:06Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Health budgets"
|
|
4
4
|
description: "Closed registry of health-budget anchors (D59), edited only by the PM."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T04:36:06Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "Discoveries and friction log"
|
|
4
4
|
description: "Append-only record of what runs discovered and where the process rubbed."
|
|
5
|
-
generated: {by: process:create-pmos, at: "2026-10-
|
|
5
|
+
generated: {by: process:create-pmos, at: "2026-10-14T04:36:06Z"}
|
|
6
6
|
status: stable
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -261,6 +261,24 @@ function startShell(name) {
|
|
|
261
261
|
}, cvSel, 10000));
|
|
262
262
|
ok('S2 the tool line lists each call with its target', await page.evaluate((s) => [...document.querySelectorAll(s + ' details[data-chat="tool"] li')].map((li) => li.querySelector('b').textContent + ' ' + ((li.querySelector('span') || {}).textContent || '')).join() === 'Bash git log', cvSel));
|
|
263
263
|
ok('S3 the status reads Your turn and the meta names the model', await page.evaluate(() => (document.querySelector('[data-cv="status"]') || {}).textContent === 'Your turn' && /claude-test/.test((document.querySelector('[data-cv="meta"]') || {}).textContent || '')));
|
|
264
|
+
// at Whole the list of sessions shows: each row's title sits above its subtitle, both at the row's left, and rows don't overlap
|
|
265
|
+
await page.click('[data-c3-size="whole"]');
|
|
266
|
+
await sleep(250);
|
|
267
|
+
const lay = await page.evaluate((s) => {
|
|
268
|
+
const rows = [...document.querySelectorAll('[data-c3-sess-list] [data-c3-sess-pick]')].map((b) => {
|
|
269
|
+
const r = b.getBoundingClientRect(), n = b.querySelector('.nm').getBoundingClientRect(), u = b.querySelector('.sub').getBoundingClientRect();
|
|
270
|
+
return { top: r.top, bottom: r.bottom, left: r.left, nl: n.left, nb: n.bottom, ul: u.left, ut: u.top, ub: u.bottom };
|
|
271
|
+
});
|
|
272
|
+
const f = document.querySelector(s + ' [data-cv="feed"]').getBoundingClientRect();
|
|
273
|
+
const m = document.querySelector(s + ' [data-chat="me"],' + s + ' [data-chat="bot"]');
|
|
274
|
+
const w = document.querySelector(s + ' [data-cv="feed"] > .wrap').getBoundingClientRect();
|
|
275
|
+
return { rows, gap: w.left - f.left, shown: !!m && m.getBoundingClientRect().height > 0 };
|
|
276
|
+
}, cvSel);
|
|
277
|
+
ok('S3b the list rows are laid out cleanly (title over subtitle, left aligned, no overlap)', lay.rows.length > 0 && lay.rows.every((r, i) =>
|
|
278
|
+
r.nb <= r.ut + 1 && r.ub <= r.bottom && Math.abs(r.nl - r.ul) < 1 && r.nl - r.left < 14 && (i === 0 || r.top >= lay.rows[i - 1].bottom - 1)), JSON.stringify(lay.rows));
|
|
279
|
+
ok('S3c at Whole the conversation starts at the left of its pane, next to the list', lay.shown && lay.gap < 16, String(lay.gap));
|
|
280
|
+
await page.click('[data-c3-size="half"]');
|
|
281
|
+
await sleep(150);
|
|
264
282
|
await page.fill('[data-cv="msg"]', 'echo c3-conv-$((5*5))');
|
|
265
283
|
await page.press('[data-cv="msg"]', 'Enter');
|
|
266
284
|
ok('S4 a sent message shows at once', await waitFor(page, () => [...document.querySelectorAll('[data-c3-conv] [data-chat="me"]')].some((n) => /c3-conv-/.test(n.textContent)), null, 3000));
|
|
@@ -71,7 +71,7 @@ A shell where Claude has not started says "No Claude in this shell yet". Press *
|
|
|
71
71
|
|
|
72
72
|
If PMOS cannot find the transcript of a Claude session, the view says so, and it does not show the transcript of a different session. Read the session in the terminal. PMOS looks for transcripts in `~/.claude`, in each `~/.claude-*` profile folder, and in the folder that `CLAUDE_CONFIG_DIR` names.
|
|
73
73
|
|
|
74
|
-
At **2/3** and **Whole**, the sheet also shows a list of your running sessions at the left. Press a session to open it.
|
|
74
|
+
At **2/3** and **Whole**, the sheet also shows a list of your running sessions at the left. Each row shows the session name and, below it, the agent and its state. Press a session to open it. The conversation starts next to the list.
|
|
75
75
|
|
|
76
76
|
### The scratchpad
|
|
77
77
|
|
|
@@ -121,7 +121,7 @@ The row chip then shows the agent's state:
|
|
|
121
121
|
|
|
122
122
|
The page reads the state again every 15 seconds while an agent is queued, working or posting.
|
|
123
123
|
|
|
124
|
-
When the draft is ready, the case file
|
|
124
|
+
When the draft is ready, the case file shows it as a document, with its headings, lists and tables. Select **Open the draft** to read all of it. Then choose one option:
|
|
125
125
|
|
|
126
126
|
- **Post it to** the ticket posts the exact text. Nothing goes out until you hold to confirm.
|
|
127
127
|
- **Send it back with a note** returns the draft to the agent. Type what to change and press Enter.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmos-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.217.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pmos-workspace",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.217.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|
package/workspace/package.json
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* normalizeCase(model) -> the canonical case (pure; accepts the mockup's field names and the descriptive ones)
|
|
5
5
|
* slideFor(caseModel, pickedId) -> { enabled, reason, label } for the slide under the case (pure)
|
|
6
6
|
* renderCase(model, opts) -> the `.case` element; opts: { picked, onPick(id, option), onConfirm({ option, hash, case }),
|
|
7
|
+
* noConf (no confidence figure: the recommended option says "Suggested", the others nothing),
|
|
8
|
+
* renderQuote(text) → nodes (the quote drawn as rich text, for example a markdown draft),
|
|
7
9
|
* outbox: boolean, onGo(go) }
|
|
8
10
|
*
|
|
9
11
|
* What the mockup's case file holds, top to bottom, and what this draws:
|
|
@@ -114,6 +116,7 @@ const fxList = (a) => el('div', { class: 'fx' }, ...a.map((f) => el('span', { cl
|
|
|
114
116
|
export function renderCase(model, opts = {}) {
|
|
115
117
|
const c = normalizeCase(model);
|
|
116
118
|
const outbox = !!opts.outbox;
|
|
119
|
+
const noConf = !!opts.noConf;
|
|
117
120
|
let picked = c.options.some((o) => o.id === opts.picked) ? opts.picked : c.recId;
|
|
118
121
|
const root = el('div', { class: 'case', 'data-case': c.id || null, style: '--tc:' + c.tc });
|
|
119
122
|
const optsHost = c.options.length ? el('div', { class: 'opts', role: 'radiogroup', 'aria-label': 'Options' }) : null;
|
|
@@ -125,11 +128,14 @@ export function renderCase(model, opts = {}) {
|
|
|
125
128
|
return el('button', { type: 'button', class: 'opt' + (o.rec ? ' rec' : ''), role: 'radio', 'aria-checked': String(on), 'aria-pressed': String(on), 'data-opt': o.id,
|
|
126
129
|
onclick: () => pick(o.id) },
|
|
127
130
|
el('span', { class: 'pk' }, c3ic('check', 'sm')),
|
|
128
|
-
|
|
131
|
+
// `noConf`: a real item has no confidence figure, so only the recommended option is marked, "Suggested", with no bar
|
|
132
|
+
noConf ? (o.rec ? el('span', { class: 'rk' }, c3ic('spark', 'sm'), 'Suggested') : null)
|
|
133
|
+
: el('span', { class: 'rk', title: 'Confidence from the sources listed above' }, o.rec ? [c3ic('spark', 'sm'), 'Recommended · ' + c.confidence + '%'] : null),
|
|
129
134
|
el('b', null, o.label),
|
|
130
135
|
fxList(o.effects),
|
|
131
136
|
o.rec ? el('div', { class: 'conf' }, el('i', { style: 'width:' + c.confidence + '%' })) : null);
|
|
132
137
|
}));
|
|
138
|
+
if (noConf) optsHost.querySelectorAll('.conf').forEach((n) => n.remove()); // no figure, no bar
|
|
133
139
|
};
|
|
134
140
|
let disposeHold = null;
|
|
135
141
|
const drawSlide = () => {
|
|
@@ -164,7 +170,7 @@ export function renderCase(model, opts = {}) {
|
|
|
164
170
|
if (opts.onPick) opts.onPick(id, c.options.find((o) => o.id === id));
|
|
165
171
|
}
|
|
166
172
|
|
|
167
|
-
if (c.quote) root.append(el('blockquote', { class: 'qd' }, c.quote));
|
|
173
|
+
if (c.quote) root.append(el('blockquote', { class: 'qd' + (opts.renderQuote ? ' qd-md' : '') }, opts.renderQuote ? opts.renderQuote(c.quote) : c.quote));
|
|
168
174
|
root.append(el('p', { class: 'sit' }, c.situation));
|
|
169
175
|
if (c.move) root.append(el('div', { class: 'c3ag' }, el('div', { class: 'dim mono', style: 'font-size:var(--fs-2)' }, c3ic('spark', 'sm'), ' Suggested move: ' + c.move)));
|
|
170
176
|
if (c.evidence.length) {
|
|
@@ -405,6 +405,10 @@
|
|
|
405
405
|
.c3 .cft .cm{display:inline-flex;gap:6px;align-items:center}
|
|
406
406
|
.c3 .cft .cm .conf{width:56px}
|
|
407
407
|
.c3 .qd{border-left:2px solid var(--ring);padding:2px 0 2px 10px;font-size:var(--fs-3);white-space:pre-wrap;margin:0}
|
|
408
|
+
.c3 .qd.qd-md{white-space:normal;max-height:28rem;overflow:auto}
|
|
409
|
+
.c3 .wk-agent-md{font-size:var(--fs-3);max-width:none}
|
|
410
|
+
.c3 .wk-agent-md h1{font-size:var(--fs-4)}
|
|
411
|
+
.c3 .wk-agent-md h2{font-size:var(--fs-4);margin:14px 0 4px}
|
|
408
412
|
.c3 .fun{display:grid;gap:4px}
|
|
409
413
|
.c3 .fun div{display:grid;grid-template-columns:62px 1fr 34px;gap:8px;align-items:center;font:var(--fs-2) var(--mono);color:var(--muted-foreground)}
|
|
410
414
|
.c3 .fun i{display:block;height:8px;border-radius:4px;background:var(--ring);transform-origin:left;animation:c3-grow .7s backwards}
|
|
@@ -1697,7 +1701,8 @@
|
|
|
1697
1701
|
.c3 .c3t-cv-panes .c3t-tw{flex:1 1 0;height:auto;min-height:0}
|
|
1698
1702
|
.c3 .c3t-cv-list{display:none;border-right:1px solid var(--border);overflow:auto;padding:0 var(--sp-2) 0 0;margin-right:var(--sp-3);gap:2px;align-content:start}
|
|
1699
1703
|
.c3 .c3t-cv-list .eyebrow{padding:var(--sp-2) 10px 4px;font:500 var(--fs-1) var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--muted-foreground)}
|
|
1700
|
-
.c3 .c3t-cv-list button{display:grid;gap:2px;text-align:left;border:0;background:none;padding:8px 10px;border-radius:8px;cursor:pointer;color:var(--foreground);font:inherit;font-size:var(--fs-3);width:100%;min-width:0}
|
|
1704
|
+
.c3 .c3t-cv-list button{display:grid;gap:2px;justify-content:stretch;justify-items:start;align-content:start;text-align:left;border:0;background:none;padding:8px 10px;border-radius:8px;cursor:pointer;color:var(--foreground);font:inherit;font-size:var(--fs-3);line-height:1.3;width:100%;min-width:0;height:auto;min-height:0}
|
|
1705
|
+
.c3 .c3t-cv-list button>span{max-width:100%}
|
|
1701
1706
|
.c3 .c3t-cv-list button .nm,.c3 .c3t-cv-list button .sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
1702
1707
|
.c3 .c3t-cv-list button .sub{font:var(--fs-1) var(--mono);color:var(--muted-foreground)}
|
|
1703
1708
|
.c3 .c3t-cv-list button[aria-current="true"]{background:color-mix(in oklab,var(--acc) 12%,transparent)}
|
|
@@ -1708,7 +1713,7 @@
|
|
|
1708
1713
|
.c3 .c3t-cv-meta .tg[data-tone="muted"]{--tc:var(--muted-foreground)}
|
|
1709
1714
|
.c3 .c3t-cv-meta .tg[data-tone="warning"]{--tc:var(--warning)}
|
|
1710
1715
|
.c3 .c3t-cv-feed{flex:1 1 0;min-height:0;overflow:auto;padding:var(--sp-3) 2px}
|
|
1711
|
-
.c3 .c3t-cv-feed>.wrap{max-width:
|
|
1716
|
+
.c3 .c3t-cv-feed>.wrap{max-width:820px;margin:0;display:flex;flex-direction:column;gap:var(--sp-2)}
|
|
1712
1717
|
.c3 .c3t-cv .m{padding:8px 14px;border-radius:8px;max-width:85%;overflow-wrap:anywhere;font-size:var(--fs-3);line-height:1.5}
|
|
1713
1718
|
.c3 .c3t-cv .m.me{align-self:flex-end;background:var(--acc);color:var(--on-accent);white-space:pre-wrap}
|
|
1714
1719
|
.c3 .c3t-cv .m.bot{align-self:flex-start;background:var(--muted)}
|
|
@@ -1951,6 +1956,7 @@
|
|
|
1951
1956
|
.c3 .wk-agent-sum{margin:0}
|
|
1952
1957
|
.c3 .wk-agent-body{--tc:var(--acc)}
|
|
1953
1958
|
.c3 .wk-agent-body .sit{white-space:pre-line}
|
|
1959
|
+
.c3 .wk-agent-doc .wk-agent-md{font-size:var(--fs-4);max-width:72ch}
|
|
1954
1960
|
.c3 .wk-agent-editbox{display:grid;gap:var(--sp-2)}
|
|
1955
1961
|
.c3 .wk-agent-edit{width:100%;box-sizing:border-box;font:inherit;font-size:var(--fs-2);line-height:1.5;padding:8px 10px;border:1px solid var(--border);background:var(--background);color:var(--foreground);border-radius:6px;resize:vertical}
|
|
1956
1962
|
.c3 .tag.wk-off{background:var(--accw);color:var(--acc)}
|
|
@@ -30,6 +30,7 @@ import { el } from './dom.js';
|
|
|
30
30
|
import { button } from './primitives.js';
|
|
31
31
|
import { pmGet, pmPost } from './http.js';
|
|
32
32
|
import { renderCase } from './c3-case.js';
|
|
33
|
+
import { parseMd, toDom } from './c3-md.js';
|
|
33
34
|
import { makeXp, attachExpand } from './c3-expand.js';
|
|
34
35
|
import { attachSwipe } from './c3-swipe.js';
|
|
35
36
|
import { toast } from './c3-toast.js';
|
|
@@ -822,6 +823,9 @@ function openAgentSession(id, item) {
|
|
|
822
823
|
try { window.dispatchEvent(new CustomEvent('pmos:open-session', { detail: { id, name: 'Job · ' + (item.key || item.title || '') } })); } catch { /* no event */ }
|
|
823
824
|
}
|
|
824
825
|
|
|
826
|
+
/* The agent's draft drawn the way a document is (c3-md.js, as the document sheet draws it): headings, lists, tables, bold. */
|
|
827
|
+
const draftMd = (text) => el('div', { class: 'ds-md wk-agent-md' }, toDom(parseMd(String(text || '')), document));
|
|
828
|
+
|
|
825
829
|
/* The agent's draft in a sheet. A draft that waits for the PM can be edited there (amendment 13): Save keeps the PM's text
|
|
826
830
|
* as the draft, so Post sends exactly that text. */
|
|
827
831
|
function openDraft(item, inst, editing) {
|
|
@@ -842,7 +846,7 @@ function openDraft(item, inst, editing) {
|
|
|
842
846
|
? el('div', { class: 'wk-agent-editbox' }, area, el('div', { class: 'chips2' },
|
|
843
847
|
button({ label: AG.saveDraft, variant: 'primary', size: 'sm', onClick: save, attrs: { 'data-pm-agent-save': item.id } }),
|
|
844
848
|
button({ label: AG.cancel, variant: 'outline', size: 'sm', onClick: () => openDraft(item, inst, false) })))
|
|
845
|
-
: el('div', { class: '
|
|
849
|
+
: el('div', { class: 'wk-agent-doc' }, draftMd(d.body || ''));
|
|
846
850
|
const body = el('div', { class: 'wk-agent-sheet' },
|
|
847
851
|
el('div', { class: 'chips' }, el('span', { class: 'tag' }, a.state === 'sent' ? 'posted' : d.edited_at ? 'draft · edited by you' : 'draft'), item.key ? el('span', { class: 'chip2' }, c3ic('org', 'sm'), (item.origin === 'jira' ? 'Jira ' : '') + item.key) : null),
|
|
848
852
|
d.summary ? el('p', { class: 'dim wk-agent-sum' }, d.summary) : null,
|
|
@@ -857,7 +861,8 @@ function openDraft(item, inst, editing) {
|
|
|
857
861
|
function caseFile(inst, item, lens) {
|
|
858
862
|
const { model, run } = itemCase(inst, item, lens);
|
|
859
863
|
const root = renderCase(model, {
|
|
860
|
-
picked: inst.picks.get(item.id), outbox: !!model.outbox,
|
|
864
|
+
picked: inst.picks.get(item.id), outbox: !!model.outbox, noConf: !item.mock_row,
|
|
865
|
+
renderQuote: item.agent && !item.mock_row ? draftMd : undefined,
|
|
861
866
|
onPick: (id) => { inst.picks.set(item.id, id); const n = root.querySelector('[data-pm-agent-note]'); if (n) { n.hidden = id !== 'back'; if (!n.hidden) n.querySelector('input').focus(); } },
|
|
862
867
|
onConfirm: ({ option }) => {
|
|
863
868
|
const fn = run[option.id];
|
|
@@ -865,10 +870,6 @@ function caseFile(inst, item, lens) {
|
|
|
865
870
|
},
|
|
866
871
|
});
|
|
867
872
|
root.setAttribute('data-pm-case', item.id);
|
|
868
|
-
if (!item.mock_row) { // real items carry no confidence figure: never show a made-up percentage
|
|
869
|
-
root.querySelectorAll('.opt .rk').forEach((n) => { if (n.childNodes.length) n.replaceChildren(c3ic('spark', 'sm'), 'Suggested'); else n.remove(); n.removeAttribute('title'); });
|
|
870
|
-
root.querySelectorAll('.opt .conf').forEach((n) => n.remove());
|
|
871
|
-
}
|
|
872
873
|
const extras = [];
|
|
873
874
|
const rs = inst.runs.get(item.id);
|
|
874
875
|
const agent = item.mock_row && item.agent_move && (item.ix || {}).move;
|
|
@@ -1226,10 +1227,9 @@ function jobCase(inst, j, close) {
|
|
|
1226
1227
|
{ id: 'mv', l: near ? 'Delete it and move its ' + its.length + ' item' + (its.length === 1 ? '' : 's') + ' to "' + nm(near) + '"' : 'Delete it', rec: 0, fx: [fx('trash', 'The job is gone', 'warn'), fx('target', its.length + ' items change job', 'warn')] },
|
|
1227
1228
|
{ id: 'nj', l: 'Delete it and leave its items without a job', rec: 0, fx: [fx('trash', 'The job is gone', 'warn'), fx('alert', 'The items have no job', '')] }] };
|
|
1228
1229
|
const run = { keep: () => { say({ text: 'Kept.', timeout: 2500 }); close(); }, mv: del(near && near.id), nj: del(null) };
|
|
1229
|
-
|
|
1230
|
+
// a job carries no confidence figure: never show a made-up percentage
|
|
1231
|
+
const root = renderCase(model, { noConf: true, onConfirm: ({ option }) => { if (run[option.id]) run[option.id](); } });
|
|
1230
1232
|
root.setAttribute('data-pm-case', j.id);
|
|
1231
|
-
root.querySelectorAll('.opt .rk').forEach((n) => { n.replaceChildren(c3ic('spark', 'sm'), 'Suggested'); n.removeAttribute('title'); }); // a job carries no confidence figure: never show a made-up percentage
|
|
1232
|
-
root.querySelectorAll('.opt .conf').forEach((n) => n.remove());
|
|
1233
1233
|
const sit = root.querySelector('.sit');
|
|
1234
1234
|
sit.after(el('div', { class: 'c3jf' }, j.mock_name ? jobEditField(inst, j, 'mock_name') : null, jobEditField(inst, j, 'when'), jobEditField(inst, j, 'want'), jobEditField(inst, j, 'so')), jobAll(inst, j));
|
|
1235
1235
|
return root;
|
|
@@ -1246,16 +1246,12 @@ function jobNewCase(inst, st, close) {
|
|
|
1246
1246
|
const model = { id: 'job:new', sit: 'The agent drafted this from your line. Change anything, then create it. It has no items yet.', conf: 70, cta: 'Slide to create',
|
|
1247
1247
|
chg: [['spark', 'Drafted by the agent', 'assumption', 'warn']],
|
|
1248
1248
|
opts: [{ id: 'mk', l: 'Create the job', rec: 1, fx: [fx('target', 'Items can now be filed under it', 'ok')] }, { id: 'no', l: 'Not now', rec: 0, fx: [] }] };
|
|
1249
|
-
const root = renderCase(model, { onConfirm: async ({ option }) => {
|
|
1249
|
+
const root = renderCase(model, { noConf: !demo, onConfirm: async ({ option }) => {
|
|
1250
1250
|
if (option.id === 'no') { say({ text: 'Dropped the draft.', timeout: 2500 }); close(); return; }
|
|
1251
1251
|
const line = 'when ' + val('when') + ', I want ' + val('want') + ', so ' + val('so');
|
|
1252
1252
|
const r = await press(inst, JOBS + '/add', nameIn ? { line, name: nameIn.value.trim() } : { line });
|
|
1253
1253
|
if (r) { say({ text: 'Job created. Add work to it by saying which job it serves.', timeout: 3000 }); close(); await load(inst); }
|
|
1254
1254
|
} });
|
|
1255
|
-
if (!demo) {
|
|
1256
|
-
root.querySelectorAll('.opt .rk').forEach((n) => { if (n.childNodes.length) n.replaceChildren(c3ic('spark', 'sm'), 'Suggested'); else n.remove(); n.removeAttribute('title'); });
|
|
1257
|
-
root.querySelectorAll('.opt .conf').forEach((n) => n.remove());
|
|
1258
|
-
}
|
|
1259
1255
|
root.querySelector('.sit').after(el('div', { class: 'c3jf' }, nameIn ? field('Job', nameIn) : null, ...['when', 'want', 'so'].map((k, i) => field(k === 'when' ? 'When' : k === 'want' ? 'I want' : 'So', inputs[i]))));
|
|
1260
1256
|
return root;
|
|
1261
1257
|
}
|