pi-pier 0.3.0 → 0.4.1

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 (103) hide show
  1. package/README.md +16 -12
  2. package/package.json +3 -3
  3. package/schemas/role-manifest.schema.json +7 -1
  4. package/skills/pi-herdr-workflow/SKILL.md +4 -5
  5. package/src/ansi-text.ts +62 -11
  6. package/src/ask-dialog.ts +308 -0
  7. package/src/ask-user.ts +113 -112
  8. package/src/bootstrap.ts +10 -13
  9. package/src/compact-coordinator.ts +279 -261
  10. package/src/compact-economics-core.ts +77 -145
  11. package/src/config-catalog-core.ts +77 -197
  12. package/src/config-command.ts +271 -64
  13. package/src/cordis-services.ts +64 -0
  14. package/src/dashboard-command.ts +77 -33
  15. package/src/delegation-core.ts +115 -0
  16. package/src/efficiency-config-core.ts +286 -486
  17. package/src/efficiency-store.ts +16 -29
  18. package/src/gc-core.ts +10 -36
  19. package/src/guards.ts +6 -0
  20. package/src/herdr-client.ts +202 -233
  21. package/src/history-store.ts +38 -23
  22. package/src/index-gates.ts +118 -0
  23. package/src/index-locks.ts +2 -7
  24. package/src/index-master.ts +31 -29
  25. package/src/index-notices.ts +28 -15
  26. package/src/index-pipe.ts +31 -12
  27. package/src/index-roles.ts +306 -0
  28. package/src/index-runtime.ts +16 -6
  29. package/src/index-worker.ts +8 -18
  30. package/src/index.ts +561 -570
  31. package/src/jev-client.ts +12 -17
  32. package/src/jev-core.ts +138 -90
  33. package/src/ledger.ts +13 -21
  34. package/src/lock-core.ts +28 -56
  35. package/src/manifest-compose.ts +35 -20
  36. package/src/observation-core.ts +52 -100
  37. package/src/pane-title.ts +19 -38
  38. package/src/panel-open.ts +47 -0
  39. package/src/pi-surface.ts +34 -22
  40. package/src/pier-options.ts +53 -50
  41. package/src/pipe-channel.ts +44 -59
  42. package/src/platform-paths.ts +19 -52
  43. package/src/{core → plugins}/grid-shape.ts +8 -10
  44. package/src/{core → plugins}/heat-plan.ts +20 -22
  45. package/src/plugins/observation.ts +475 -0
  46. package/src/plugins/subagent.ts +766 -0
  47. package/src/{core → plugins}/terminal.ts +198 -139
  48. package/src/{core → plugins}/todo.ts +73 -134
  49. package/src/progress-core.ts +16 -53
  50. package/src/reconcile-core.ts +24 -33
  51. package/src/reducer-core.ts +26 -64
  52. package/src/reducer-invoker.ts +266 -239
  53. package/src/renderers.ts +108 -84
  54. package/src/role-loader.ts +33 -28
  55. package/src/role-manifest.ts +25 -31
  56. package/src/role-state.ts +119 -0
  57. package/src/roles/worker-default.json +3 -3
  58. package/src/routing-telemetry.ts +136 -0
  59. package/src/runtime-policy.ts +25 -40
  60. package/src/session-tail.ts +65 -41
  61. package/src/settle-wake-core.ts +61 -22
  62. package/src/slim-frame.ts +25 -122
  63. package/src/stale-core.ts +17 -24
  64. package/src/storage-layout.ts +14 -43
  65. package/src/subagent-core.ts +423 -120
  66. package/src/subagent-gc.ts +109 -67
  67. package/src/subagent-poller.ts +383 -24
  68. package/src/subagent-session.ts +516 -0
  69. package/src/subagent-spawn.ts +577 -52
  70. package/src/swallow.ts +7 -17
  71. package/src/terminal-core.ts +187 -134
  72. package/src/todo-core.ts +57 -109
  73. package/src/todo-read-hook.ts +46 -39
  74. package/src/todo-reminder-core.ts +26 -51
  75. package/src/todo-window.ts +11 -12
  76. package/src/todos-service.ts +15 -35
  77. package/src/tool-error.ts +6 -13
  78. package/src/tool-gate.ts +38 -21
  79. package/src/tree-view.ts +162 -0
  80. package/src/vocab.ts +52 -25
  81. package/src/worker-marker.ts +76 -0
  82. package/src/ask-multi.ts +0 -260
  83. package/src/config-guide.ts +0 -361
  84. package/src/core/observation.ts +0 -555
  85. package/src/core/subagent.ts +0 -633
  86. package/src/efficiency-config-io.ts +0 -53
  87. package/src/focus-poller.ts +0 -244
  88. package/src/git-adapter.ts +0 -113
  89. package/src/notice-buffer.ts +0 -23
  90. package/src/subagent-execute.ts +0 -328
  91. package/src/subagent-git-io.ts +0 -80
  92. package/src/subagent-launch.ts +0 -114
  93. package/src/subagent-list-action.ts +0 -69
  94. package/src/subagent-output-action.ts +0 -104
  95. package/src/subagent-output-adapter.ts +0 -27
  96. package/src/subagent-output-core.ts +0 -263
  97. package/src/subagent-poll-loop.ts +0 -305
  98. package/src/subagent-port.ts +0 -27
  99. package/src/subagent-ready.ts +0 -89
  100. package/src/subagent-registry.ts +0 -70
  101. package/src/subagent-resolution.ts +0 -41
  102. package/src/subagent-scope.ts +0 -41
  103. package/src/subagent-session-io.ts +0 -230
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Delegation identity (RFC docs/rfc-delegation-identity.md Phase 1): a worker pane knows who
3
+ * delegated it, for what task, and shows that on every surface it already touches — system prompt
4
+ * section, session custom entry (first-frame card), herdr sidebar tokens, and the pane title.
5
+ * Pure builders only; the composition root owns the side effects.
6
+ */
7
+
8
+ /** Contract env handed to the worker process by the master (PI_HERDR_ prefix per naming rule). */
9
+ export const DELEGATION_ENV = 'PI_HERDR_DELEGATION';
10
+ /** Worker-session custom entry written once at first boot; replayed on resume. */
11
+ export const DELEGATION_CUSTOM_TYPE = 'pi-herdr.delegation';
12
+ /** herdr sidebar tokens (pane.report_metadata): parent pane + delegated task. */
13
+ export const DELEGATION_PARENT_TOKEN = 'pi-parent';
14
+ export const DELEGATION_TASK_TOKEN = 'pi-task';
15
+ /** herdr truncates title/token values at 80 chars; clip locally to keep glyphs whole. */
16
+ const TOKEN_MAX = 80;
17
+
18
+ export interface DelegationContext {
19
+ /** Master pane that spawned this worker; '' when the master pane is unknown (tests, RPC). */
20
+ readonly parentPaneId: string;
21
+ /** Master pi session id (cross-locate the parent transcript via /resume). */
22
+ readonly parentSessionId: string;
23
+ /** SubEntry.taskId — stable across revives. */
24
+ readonly taskId: string;
25
+ /** Task short label (SubEntry.description). */
26
+ readonly description: string;
27
+ /** Role manifest name active at spawn. */
28
+ readonly role: string;
29
+ /** Phase 2: the master's pipe name — report_progress dials it directly (D49 reply-address
30
+ * semantics, precomputed because the worker cannot derive the master's session cwd). */
31
+ readonly parentPipe?: string;
32
+ }
33
+
34
+ function str(v: unknown): string | null {
35
+ return typeof v === 'string' ? v : null;
36
+ }
37
+
38
+ /** Validate a parsed delegation record (env JSON, marker JSON or custom-entry data); null when malformed. */
39
+ export function delegationFromRecord(parsed: unknown): DelegationContext | null {
40
+ if (!parsed || typeof parsed !== 'object') return null;
41
+ const rec = parsed as Record<string, unknown>; // shape-checked field by field below
42
+ const parentPipe = str(rec.parentPipe);
43
+ const taskId = str(rec.taskId);
44
+ const description = str(rec.description);
45
+ if (!taskId || !description) return null;
46
+ return {
47
+ parentPaneId: str(rec.parentPaneId) ?? '',
48
+ parentSessionId: str(rec.parentSessionId) ?? '',
49
+ taskId,
50
+ description,
51
+ role: str(rec.role) ?? 'worker-default',
52
+ ...(parentPipe ? { parentPipe } : {}),
53
+ };
54
+ }
55
+
56
+ /** Parse the spawn env; null when absent or structurally invalid (taskId/description mandatory). */
57
+ export function parseDelegationContext(raw: string | undefined | null): DelegationContext | null {
58
+ if (!raw || typeof raw !== 'string') return null;
59
+ try {
60
+ return delegationFromRecord(JSON.parse(raw));
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ /** env map for spawnPaneInTaskTab/createTab; JSON like the role manifest next to it. */
67
+ export function delegationEnv(ctx: DelegationContext): Record<string, string> {
68
+ return { [DELEGATION_ENV]: JSON.stringify(ctx) };
69
+ }
70
+
71
+ /** Fold `pi-herdr.delegation` branch entries (last one wins) — the /resume replay source. */
72
+ export function foldDelegation(
73
+ entries: ReadonlyArray<{ type?: string; customType?: string; data?: unknown }>,
74
+ ): DelegationContext | null {
75
+ let found: DelegationContext | null = null;
76
+ for (const entry of entries) {
77
+ if (entry.type !== 'custom' || entry.customType !== DELEGATION_CUSTOM_TYPE) continue;
78
+ const next = delegationFromRecord(entry.data);
79
+ if (next) found = next;
80
+ }
81
+ return found;
82
+ }
83
+
84
+ /**
85
+ * System-prompt section text: identity + delivery contract in one stable wording, so the master
86
+ * model does not have to restate it in every spawn prompt (pi-subagent-manager idea A+F).
87
+ */
88
+ export function buildDelegationSection(ctx: DelegationContext, ownPaneId: string): string {
89
+ const parent = ctx.parentPaneId || 'unknown pane';
90
+ const session = ctx.parentSessionId || 'unknown session';
91
+ const self = ownPaneId ? ` You are pane ${ownPaneId} (agentId "${ownPaneId}") — cite it when asking questions or reporting errors.`
92
+ : '';
93
+ return [
94
+ `You are a delegated subagent of the master pane ${parent} (session ${session}); you were not started by a human.`,
95
+ `Task: ${ctx.description}. Role: ${ctx.role}.${self}`,
96
+ 'Contract: when finished, state your final answer plainly — the master collects it from this pane\'s settlement; do not ask who requested the work. If you cannot finish, say exactly what blocks you instead of stopping silently.',
97
+ ].join('\n');
98
+ }
99
+
100
+ /** Sidebar token patch; empty (no request) when there is no parent pane to attribute. */
101
+ export function delegationSidebarTokens(ctx: DelegationContext): Record<string, string> {
102
+ if (!ctx.parentPaneId) return {};
103
+ return {
104
+ [DELEGATION_PARENT_TOKEN]: ctx.parentPaneId.slice(0, TOKEN_MAX),
105
+ [DELEGATION_TASK_TOKEN]: ctx.description.slice(0, TOKEN_MAX),
106
+ };
107
+ }
108
+
109
+ /** Worker pane title marker: `↳ <todo title>`, or `↳ <task>` alone before the first todo_write. */
110
+ export function applyWorkerTag(title: string | null, delegatedTask: string | null): string | null {
111
+ if (!delegatedTask) return title;
112
+ const base = title ?? delegatedTask;
113
+ return `↳ ${base.slice(0, TOKEN_MAX - 2)}`;
114
+ }
115
+