@mjasnikovs/pi-task 0.17.2 → 0.17.4

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.
@@ -7,8 +7,8 @@ const DEFAULTS = {
7
7
  compressReasoning: true,
8
8
  autoCommit: true,
9
9
  orientation: true,
10
- enforceGuidelines: false,
11
- verifyWork: false
10
+ enforceGuidelines: true,
11
+ verifyWork: true
12
12
  };
13
13
  const CONFIG_PATH = path.join(os.homedir(), '.config', 'pi-task', 'config.json');
14
14
  const _g = globalThis;
@@ -1,6 +1,51 @@
1
- import { SettingsList } from '@earendil-works/pi-tui';
1
+ import { SettingsList, visibleWidth } from '@earendil-works/pi-tui';
2
2
  import { registerBridgeCommand } from '../remote/bridge.js';
3
3
  import { getConfig, saveConfig } from './config.js';
4
+ const CONFIG_TITLE = 'pi-task settings';
5
+ /**
6
+ * Frames a child component (the settings list) in a rounded border with a title
7
+ * woven into the top edge. Without this the overlay's content sits flush against
8
+ * the chat scrollback and reads as just more console text; the border gives it a
9
+ * distinct panel. Layout mirrors {@link renderQuestionBox}'s box chrome: render
10
+ * the child at the inner width, pad each line so the right edge lines up, then
11
+ * frame. Input and invalidation are forwarded straight through to the child.
12
+ */
13
+ class BorderedBox {
14
+ child;
15
+ title;
16
+ border;
17
+ titleColor;
18
+ constructor(child, title, border, titleColor) {
19
+ this.child = child;
20
+ this.title = title;
21
+ this.border = border;
22
+ this.titleColor = titleColor;
23
+ }
24
+ render(width) {
25
+ const innerWidth = Math.max(1, width - 4); // "│ " + content + " │"
26
+ const dash = (n) => '─'.repeat(Math.max(0, n));
27
+ // Top border with the title woven in: "╭─ pi-task settings ─…─╮".
28
+ const tag = ` ${this.title} `;
29
+ const lead = 1; // one dash before the title
30
+ const rest = width - 2 - lead - visibleWidth(tag);
31
+ const top = rest >= 0 ?
32
+ this.border(`╭${dash(lead)}`) + this.titleColor(tag) + this.border(`${dash(rest)}╮`)
33
+ : this.border(`╭${dash(width - 2)}╮`);
34
+ const body = this.child.render(innerWidth).map(line => {
35
+ const pad = innerWidth - visibleWidth(line);
36
+ const padded = pad > 0 ? line + ' '.repeat(pad) : line;
37
+ return this.border('│ ') + padded + this.border(' │');
38
+ });
39
+ const bottom = this.border(`╰${dash(width - 2)}╯`);
40
+ return [top, ...body, bottom];
41
+ }
42
+ invalidate() {
43
+ this.child.invalidate();
44
+ }
45
+ handleInput(data) {
46
+ this.child.handleInput(data);
47
+ }
48
+ }
4
49
  const ITEMS = [
5
50
  { id: 'remote', label: 'remote', description: 'Remote UI server (QR code, phone access)' },
6
51
  {
@@ -58,8 +103,8 @@ async function handleTaskConfig(_args, ctx) {
58
103
  cfg[id] = newValue === 'on';
59
104
  saveConfig(cfg).catch(() => { });
60
105
  }, () => done(undefined));
61
- return list;
62
- }, { overlay: true, overlayOptions: { width: 54 } });
106
+ return new BorderedBox(list, CONFIG_TITLE, s => theme.fg('borderMuted', s), s => theme.fg('accent', theme.bold(s)));
107
+ }, { overlay: true, overlayOptions: { width: 58 } });
63
108
  }
64
109
  export function registerConfig(pi) {
65
110
  registerBridgeCommand(pi, 'task-config', {
@@ -222,6 +222,14 @@ LIVE-DATA RULE:
222
222
  - "### freshness-check skipped" → tag UNKNOWN and say current state needs verification.
223
223
  - No npm block + question is about latest/current version → tag UNKNOWN (training data goes stale).
224
224
 
225
+ TRIAGE — run these checks IN ORDER first. The REVERSIBILITY TEST below applies ONLY to a question that survives all checks as a genuine preference.
226
+
227
+ 1. ALREADY-DECIDED CHECK — scan the refined task and research for a value, shape, response body, schema, route, or requirement that ALREADY determines the answer. If one does, this is a fact, not a preference. Emit "ANSWER: <value taken from that source>". If your instinct or a "nicer" alternative contradicts that source, the SOURCE WINS — never override a stated contract with a preferred default. (E.g. a stated response shape { items, total, page, pageSize } already answers a pagination question — page/offset — you may NOT answer "cursor".)
228
+
229
+ 2. FUNCTIONAL-REQUIREMENT CHECK — if the question is whether to include or defer a package, config file, or setup that something THIS task configures needs in order to FUNCTION (a build plugin's engine or required peer dependency, an entry file the build reads, a runtime module an import resolves to), then a "minimize / keep it minimal / defer to the step that uses it" preference does NOT override that functional requirement. A tool you wire up this step must have its required pieces present this step or the build/step is broken. Emit "ANSWER: <include it now, because configuring X requires it>". Do not defer something the step's own configuration depends on.
230
+
231
+ 3. PREFERENCE — only if neither check fires (a genuine choice the sources do not determine), apply the REVERSIBILITY TEST.
232
+
225
233
  REVERSIBILITY TEST:
226
234
  ANSWER: cheap to undo (output style, policy, report format, obvious scope, standard convention).
227
235
  UNKNOWN: costly to reverse (file mutations, tool/dependency choice, approach/algorithm, format that shapes downstream artifacts).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mjasnikovs/pi-task",
3
- "version": "0.17.2",
3
+ "version": "0.17.4",
4
4
  "description": "Deterministic spec-orchestration for local models, with a bundled real-time remote web view and web/docs/fetch/worker subagent tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",