pi-pier 0.4.1 → 0.4.3

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.
Files changed (45) hide show
  1. package/README.md +1 -2
  2. package/package.json +1 -1
  3. package/schemas/efficiency-config.schema.json +25 -19
  4. package/schemas/role-manifest.schema.json +9 -9
  5. package/src/ask-dialog.ts +9 -2
  6. package/src/ask-user.ts +142 -74
  7. package/src/compact-coordinator.ts +204 -33
  8. package/src/compact-economics-core.ts +62 -29
  9. package/src/config-catalog-core.ts +1 -0
  10. package/src/delegation-core.ts +1 -1
  11. package/src/efficiency-config-core.ts +34 -20
  12. package/src/efficiency-store.ts +42 -5
  13. package/src/herdr-client.ts +15 -5
  14. package/src/index-notices.ts +1 -1
  15. package/src/index-pipe.ts +0 -8
  16. package/src/index.ts +71 -87
  17. package/src/jev-client.ts +32 -7
  18. package/src/jev-core.ts +70 -33
  19. package/src/manifest-compose.ts +4 -4
  20. package/src/observation-core.ts +13 -1
  21. package/src/pipe-channel.ts +0 -8
  22. package/src/plugins/heat-plan.ts +18 -3
  23. package/src/plugins/observation.ts +118 -46
  24. package/src/plugins/subagent.ts +53 -40
  25. package/src/plugins/terminal.ts +192 -47
  26. package/src/plugins/todo.ts +44 -22
  27. package/src/reducer-invoker.ts +28 -14
  28. package/src/renderers.ts +1 -13
  29. package/src/role-loader.ts +8 -8
  30. package/src/role-manifest.ts +22 -22
  31. package/src/roles/master.json +1 -1
  32. package/src/roles/worker-default.json +3 -3
  33. package/src/settle-wake-core.ts +8 -2
  34. package/src/subagent-core.ts +41 -3
  35. package/src/subagent-poller.ts +52 -18
  36. package/src/subagent-session.ts +67 -4
  37. package/src/subagent-spawn.ts +6 -5
  38. package/src/terminal-core.ts +111 -17
  39. package/src/todo-core.ts +47 -2
  40. package/src/todo-read-hook.ts +31 -17
  41. package/src/todo-reminder-core.ts +9 -5
  42. package/src/todo-window.ts +8 -4
  43. package/src/todos-service.ts +12 -0
  44. package/src/tree-view.ts +10 -10
  45. package/src/vocab.ts +7 -1
package/src/tree-view.ts CHANGED
@@ -66,7 +66,7 @@ export function workerLine(row: WorkerWidgetRow): string {
66
66
  const counts = countsOf(items);
67
67
  if (!cur) return `↳ ${ref} ${counts}`;
68
68
  if (cur.status === 'blocked') {
69
- const why = cur.blocker && cur.blocker !== cur.content ? `(${clip(cur.blocker, 24)})` : '';
69
+ const why = cur.blocker && cur.blocker !== cur.content ? ` (${clip(cur.blocker, 24)})` : '';
70
70
  return `↳ ${ref} ■ ${clip(cur.content, 40)}${why} ${counts}`;
71
71
  }
72
72
  return `↳ ${ref} ▶ ${clip(cur.content)} ${counts}`;
@@ -85,7 +85,7 @@ export function selfLine(items: readonly TodoItem[]): string | null {
85
85
  const cur = currentOf(items);
86
86
  if (!cur) return null;
87
87
  const counts = countsOf(items);
88
- if (cur.status === 'blocked') return `■ 等人: ${clip(cur.blocker || cur.content, 40)} ${counts}`;
88
+ if (cur.status === 'blocked') return `■ waiting on: ${clip(cur.blocker || cur.content, 40)} ${counts}`;
89
89
  return `▶ ${clip(cur.content)} ${counts}`;
90
90
  }
91
91
 
@@ -100,8 +100,8 @@ export function unifiedWidgetLines(
100
100
  // Human gate open: the question owns the fixed area (unchanged discipline from the old widget).
101
101
  if ((opts?.blockedDepth ?? 0) > 0) {
102
102
  return workers.length === 0 || items.length === 0
103
- ? [`${formatTodoSummary(items)} · /todos 全量`]
104
- : [`${formatTodoSummary(items)} · ↳×${workers.length} · /todos 全量`];
103
+ ? [`${formatTodoSummary(items)} · /todos for all`]
104
+ : [`${formatTodoSummary(items)} · ↳×${workers.length} · /todos for all`];
105
105
  }
106
106
  if (items.length === 0 && workers.length === 0) return [];
107
107
  // Archived plans keep their degraded two-line form; workers stay visible underneath.
@@ -114,7 +114,7 @@ export function unifiedWidgetLines(
114
114
  const budget = WIDGET_MAX_LINES - head.length - 1;
115
115
  const shown = rows.slice(0, Math.max(budget, 0));
116
116
  const hidden = rows.length - shown.length;
117
- return [...head, ...shown, ...(hidden > 0 ? [`…另 ${hidden} 个子代理 · /pier-tree`] : [])];
117
+ return [...head, ...shown, ...(hidden > 0 ? [`…+${hidden} more subagents · /pier-tree`] : [])];
118
118
  }
119
119
 
120
120
  /** Full delegation tree for /pier-tree: self todos in full + per-worker full lists + settled nodes. */
@@ -126,15 +126,15 @@ export function formatDelegationTree(opts: {
126
126
  }): string[] {
127
127
  const now = opts.now ?? Date.now();
128
128
  const lines: string[] = ['==================== PIER DELEGATION TREE ===================='];
129
- lines.push(`● master(本 pane)· ${opts.selfItems.length} 项`);
129
+ lines.push(`● master (this pane) · ${opts.selfItems.length} items`);
130
130
  lines.push(...renderTodoGroups(opts.selfItems).map((l) => ` ${l}`));
131
131
  if (opts.workers.length > 0 || (opts.settled?.length ?? 0) > 0) lines.push(' │');
132
132
  for (const w of opts.workers) {
133
133
  const ref = w.slug ?? w.paneId;
134
134
  const items = w.todos?.items;
135
135
  const headSuffix = items && items.length > 0
136
- ? `· ${items.length} 项`
137
- : w.todos?.summary ? `· ${clip(w.todos.summary, 40)}` : '· todo 未同步';
136
+ ? `· ${items.length} items`
137
+ : w.todos?.summary ? `· ${clip(w.todos.summary, 40)}` : '· todos not synced';
138
138
  lines.push(` ├─ ↳ ${ref} (${w.paneId} · running${w.kind && w.kind !== 'task' ? ` · ${w.kind}` : ''}) ${headSuffix}`);
139
139
  if (items && items.length > 0) {
140
140
  lines.push(...renderTodoGroups(toTodoItems(items)).map((l) => ` │ ${l}`));
@@ -143,10 +143,10 @@ export function formatDelegationTree(opts: {
143
143
  for (const s of opts.settled ?? []) {
144
144
  const ref = s.slug ?? s.paneId;
145
145
  const age = s.settledAt ? ` · settled ${formatAge(Math.max(now - s.settledAt, 0))} ago` : ' · settled';
146
- lines.push(` └─ ✓ ${ref} (${s.paneId}${age}) — 结果已注入结算通知`);
146
+ lines.push(` └─ ✓ ${ref} (${s.paneId}${age}) — result delivered in the settlement notice`);
147
147
  }
148
148
  lines.push('----------------------------------------------------------------');
149
- lines.push('提示: /todos 编辑自己的清单 · subagent list 交互子代理 · /dashboard ops 面板');
149
+ lines.push('Hint: /todos edit your own list · subagent list interact with subagents · /dashboard ops panel');
150
150
  return lines;
151
151
  }
152
152
 
package/src/vocab.ts CHANGED
@@ -98,13 +98,19 @@ const NULL_CLOSING_SENTENCE: Record<SettlementNullReason, string> = {
98
98
  silent: 'It left no closing message.',
99
99
  };
100
100
 
101
- /** Subagent settlement notice (aligned with DSH). */
101
+ /** Subagent settlement notice (aligned with DSH). `reportDeliveredAt`: the master already received
102
+ * this exact closing message through `subagent output`, so the notice points there instead. */
102
103
  export function formatSettlementNotice(
103
104
  agentId: string,
104
105
  closingMessage: string | null,
105
106
  nullReason: SettlementNullReason = 'silent',
107
+ reportDeliveredAt: number | null = null,
106
108
  ): string {
107
109
  const head = `Background subagent ${agentId} finished and will do no further work unless you send it more.`;
110
+ if (closingMessage && reportDeliveredAt !== null) {
111
+ const at = new Date(reportDeliveredAt).toTimeString().slice(0, 8);
112
+ return `${head} Its closing message is the report subagent(action:"output") already returned at ${at}; it is not repeated here.`;
113
+ }
108
114
  return closingMessage
109
115
  ? `${head} Its closing message: ${closingMessage}`
110
116
  : `${head} ${NULL_CLOSING_SENTENCE[nullReason]}`;