@poa-box/agent 0.1.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.
Files changed (139) hide show
  1. package/.env.agent.template +20 -0
  2. package/README.md +46 -0
  3. package/brain/Config/agent-config.json +14 -0
  4. package/brain/Config/brain-allowlist.json +20 -0
  5. package/brain/Identity/goals.template.md +23 -0
  6. package/brain/Identity/how-i-think.md +406 -0
  7. package/brain/Identity/who-i-am.template.md +34 -0
  8. package/brain/Knowledge/BOOTSTRAP.md +66 -0
  9. package/brain/Knowledge/audit-corpus-index.json +406 -0
  10. package/brain/Knowledge/discussions.json +245 -0
  11. package/brain/Knowledge/pop.brain.brainstorms.generated.md +48 -0
  12. package/brain/Knowledge/pop.brain.brainstorms.genesis.bin +0 -0
  13. package/brain/Knowledge/pop.brain.heuristics.snapshot.bin +0 -0
  14. package/brain/Knowledge/pop.brain.projects.generated.md +16 -0
  15. package/brain/Knowledge/pop.brain.projects.genesis.bin +0 -0
  16. package/brain/Knowledge/pop.brain.retros.generated.md +91 -0
  17. package/brain/Knowledge/pop.brain.retros.genesis.bin +0 -0
  18. package/brain/Knowledge/pop.brain.shared.generated.md +3811 -0
  19. package/brain/Knowledge/pop.brain.shared.genesis.bin +0 -0
  20. package/brain/Knowledge/projects.md +181 -0
  21. package/brain/Knowledge/risk-framework.md +90 -0
  22. package/brain/Knowledge/shared.md +416 -0
  23. package/brain/Knowledge/sprint-priorities.md +439 -0
  24. package/brain/Memory/.gitkeep +0 -0
  25. package/dist/commands/agent/daily-digest.d.ts +24 -0
  26. package/dist/commands/agent/daily-digest.js +336 -0
  27. package/dist/commands/agent/delegate.d.ts +12 -0
  28. package/dist/commands/agent/delegate.js +91 -0
  29. package/dist/commands/agent/deploy-to-org.d.ts +20 -0
  30. package/dist/commands/agent/deploy-to-org.js +154 -0
  31. package/dist/commands/agent/index.d.ts +2 -0
  32. package/dist/commands/agent/index.js +27 -0
  33. package/dist/commands/agent/init.d.ts +19 -0
  34. package/dist/commands/agent/init.js +303 -0
  35. package/dist/commands/agent/onboard.d.ts +22 -0
  36. package/dist/commands/agent/onboard.js +192 -0
  37. package/dist/commands/agent/paymaster-status.d.ts +14 -0
  38. package/dist/commands/agent/paymaster-status.js +130 -0
  39. package/dist/commands/agent/register.d.ts +21 -0
  40. package/dist/commands/agent/register.js +116 -0
  41. package/dist/commands/agent/setup-sponsorship.d.ts +22 -0
  42. package/dist/commands/agent/setup-sponsorship.js +154 -0
  43. package/dist/commands/agent/status.d.ts +12 -0
  44. package/dist/commands/agent/status.js +171 -0
  45. package/dist/commands/agent/triage.d.ts +12 -0
  46. package/dist/commands/agent/triage.js +503 -0
  47. package/dist/commands/brain/advance-stage.d.ts +42 -0
  48. package/dist/commands/brain/advance-stage.js +206 -0
  49. package/dist/commands/brain/allowlist.d.ts +30 -0
  50. package/dist/commands/brain/allowlist.js +274 -0
  51. package/dist/commands/brain/append-lesson.d.ts +55 -0
  52. package/dist/commands/brain/append-lesson.js +245 -0
  53. package/dist/commands/brain/brainstorm.d.ts +154 -0
  54. package/dist/commands/brain/brainstorm.js +573 -0
  55. package/dist/commands/brain/daemon.d.ts +31 -0
  56. package/dist/commands/brain/daemon.js +348 -0
  57. package/dist/commands/brain/doctor.d.ts +27 -0
  58. package/dist/commands/brain/doctor.js +497 -0
  59. package/dist/commands/brain/edit-lesson.d.ts +51 -0
  60. package/dist/commands/brain/edit-lesson.js +248 -0
  61. package/dist/commands/brain/import-snapshot.d.ts +68 -0
  62. package/dist/commands/brain/import-snapshot.js +177 -0
  63. package/dist/commands/brain/index.d.ts +2 -0
  64. package/dist/commands/brain/index.js +67 -0
  65. package/dist/commands/brain/list.d.ts +21 -0
  66. package/dist/commands/brain/list.js +83 -0
  67. package/dist/commands/brain/migrate-projects.d.ts +44 -0
  68. package/dist/commands/brain/migrate-projects.js +209 -0
  69. package/dist/commands/brain/migrate.d.ts +74 -0
  70. package/dist/commands/brain/migrate.js +306 -0
  71. package/dist/commands/brain/new-project.d.ts +53 -0
  72. package/dist/commands/brain/new-project.js +226 -0
  73. package/dist/commands/brain/read.d.ts +24 -0
  74. package/dist/commands/brain/read.js +81 -0
  75. package/dist/commands/brain/remove-lesson.d.ts +47 -0
  76. package/dist/commands/brain/remove-lesson.js +206 -0
  77. package/dist/commands/brain/remove-project.d.ts +36 -0
  78. package/dist/commands/brain/remove-project.js +177 -0
  79. package/dist/commands/brain/retro-file-tasks.d.ts +84 -0
  80. package/dist/commands/brain/retro-file-tasks.js +372 -0
  81. package/dist/commands/brain/retro-list.d.ts +28 -0
  82. package/dist/commands/brain/retro-list.js +125 -0
  83. package/dist/commands/brain/retro-mark-change.d.ts +58 -0
  84. package/dist/commands/brain/retro-mark-change.js +176 -0
  85. package/dist/commands/brain/retro-remove.d.ts +36 -0
  86. package/dist/commands/brain/retro-remove.js +142 -0
  87. package/dist/commands/brain/retro-respond.d.ts +56 -0
  88. package/dist/commands/brain/retro-respond.js +250 -0
  89. package/dist/commands/brain/retro-show.d.ts +23 -0
  90. package/dist/commands/brain/retro-show.js +100 -0
  91. package/dist/commands/brain/retro-start.d.ts +55 -0
  92. package/dist/commands/brain/retro-start.js +311 -0
  93. package/dist/commands/brain/search.d.ts +48 -0
  94. package/dist/commands/brain/search.js +190 -0
  95. package/dist/commands/brain/snapshot.d.ts +32 -0
  96. package/dist/commands/brain/snapshot.js +243 -0
  97. package/dist/commands/brain/status.d.ts +15 -0
  98. package/dist/commands/brain/status.js +166 -0
  99. package/dist/commands/brain/subscribe.d.ts +28 -0
  100. package/dist/commands/brain/subscribe.js +90 -0
  101. package/dist/commands/brain/tag.d.ts +46 -0
  102. package/dist/commands/brain/tag.js +192 -0
  103. package/dist/index.d.ts +17 -0
  104. package/dist/index.js +22 -0
  105. package/dist/lib/brain-daemon.d.ts +126 -0
  106. package/dist/lib/brain-daemon.js +811 -0
  107. package/dist/lib/brain-membership.d.ts +58 -0
  108. package/dist/lib/brain-membership.js +115 -0
  109. package/dist/lib/brain-migrate-projects.d.ts +43 -0
  110. package/dist/lib/brain-migrate-projects.js +247 -0
  111. package/dist/lib/brain-migrate.d.ts +77 -0
  112. package/dist/lib/brain-migrate.js +328 -0
  113. package/dist/lib/brain-ops.d.ts +271 -0
  114. package/dist/lib/brain-ops.js +571 -0
  115. package/dist/lib/brain-paths.d.ts +15 -0
  116. package/dist/lib/brain-paths.js +33 -0
  117. package/dist/lib/brain-projections.d.ts +216 -0
  118. package/dist/lib/brain-projections.js +829 -0
  119. package/dist/lib/brain-schemas.d.ts +36 -0
  120. package/dist/lib/brain-schemas.js +316 -0
  121. package/dist/lib/brain-signing.d.ts +103 -0
  122. package/dist/lib/brain-signing.js +256 -0
  123. package/dist/lib/brain.d.ts +198 -0
  124. package/dist/lib/brain.js +1057 -0
  125. package/dist/pop-agent.d.ts +1 -0
  126. package/dist/pop-agent.js +18 -0
  127. package/docs/agent.md +126 -0
  128. package/docs/agents/brain-anti-entropy.md +127 -0
  129. package/docs/agents/brain-cross-device-onboarding.md +210 -0
  130. package/docs/agents/brain-cross-machine-smoke.md +241 -0
  131. package/docs/agents/brain-layer-setup.md +725 -0
  132. package/docs/agents/offboarding-protocol.md +188 -0
  133. package/docs/agents/onboarding-protocol.md +243 -0
  134. package/docs/agents/running-an-agent.md +200 -0
  135. package/docs/brain.md +560 -0
  136. package/package.json +61 -0
  137. package/scripts/apply.sh +140 -0
  138. package/scripts/onboard.sh +205 -0
  139. package/scripts/setup-agent.ts +272 -0
@@ -0,0 +1,372 @@
1
+ "use strict";
2
+ /**
3
+ * pop brain retro file-tasks — convert agreed retro changes into on-chain tasks.
4
+ *
5
+ * Usage:
6
+ *
7
+ * pop brain retro file-tasks --retro retro-327-1776...
8
+ * pop brain retro file-tasks --retro retro-327-1776... --dry-run
9
+ * pop brain retro file-tasks --retro retro-327-1776... --project "CLI Infrastructure"
10
+ *
11
+ * Flow:
12
+ *
13
+ * 1. Load the retro from pop.brain.retros.
14
+ * 2. Find every proposed change whose status is 'agreed'. Changes at any
15
+ * other status are skipped — 'proposed' needs more discussion first,
16
+ * 'rejected' was explicitly rejected, 'modified' needs a second round,
17
+ * and 'filed' is already done (this is the idempotency guarantee:
18
+ * re-running the command is safe because filed changes are no-ops).
19
+ * 3. For each agreed change:
20
+ * a. Call `pop task create` with a structured description derived
21
+ * from the change summary + details + retro window.
22
+ * b. Capture the returned task id.
23
+ * c. Run `updateChangeStatus` to flip the change to 'filed' with
24
+ * filedTaskId set.
25
+ * 4. When every change is filed or rejected, the updateChangeStatus op
26
+ * auto-advances the retro status to 'shipped' with a closedAt
27
+ * timestamp.
28
+ *
29
+ * ## Idempotency
30
+ *
31
+ * This command is safe to run multiple times. A change with status='filed'
32
+ * is skipped. A change that was already converted won't be re-filed. The
33
+ * idempotency guarantee requires the `agreed → filed` transition to be
34
+ * the only way a change gets converted. Operators who want to re-file a
35
+ * change after filing it should run `pop brain retro respond --vote
36
+ * change-X=agree` again and then call file-tasks — but the previous
37
+ * filed task id is never overwritten, so the old task sticks around
38
+ * unless manually cancelled. That's a deliberate safety design: no
39
+ * accidental re-filing of the same work.
40
+ *
41
+ * ## Dry-run
42
+ *
43
+ * `--dry-run` prints the plan (which changes would be filed, what task
44
+ * description would be produced) without actually creating any tasks or
45
+ * mutating the retro. Use this to preview before committing.
46
+ *
47
+ * ## Project selection
48
+ *
49
+ * Defaults to "CLI Infrastructure" — the historical catch-all for brain
50
+ * layer + CLI work. Override with --project if the retro's proposed
51
+ * changes belong to a different project (e.g. "DeFi Research",
52
+ * "Agent Protocol").
53
+ */
54
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
55
+ if (k2 === undefined) k2 = k;
56
+ var desc = Object.getOwnPropertyDescriptor(m, k);
57
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
58
+ desc = { enumerable: true, get: function() { return m[k]; } };
59
+ }
60
+ Object.defineProperty(o, k2, desc);
61
+ }) : (function(o, m, k, k2) {
62
+ if (k2 === undefined) k2 = k;
63
+ o[k2] = m[k];
64
+ }));
65
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
66
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
67
+ }) : function(o, v) {
68
+ o["default"] = v;
69
+ });
70
+ var __importStar = (this && this.__importStar) || (function () {
71
+ var ownKeys = function(o) {
72
+ ownKeys = Object.getOwnPropertyNames || function (o) {
73
+ var ar = [];
74
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
75
+ return ar;
76
+ };
77
+ return ownKeys(o);
78
+ };
79
+ return function (mod) {
80
+ if (mod && mod.__esModule) return mod;
81
+ var result = {};
82
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
83
+ __setModuleDefault(result, mod);
84
+ return result;
85
+ };
86
+ })();
87
+ Object.defineProperty(exports, "__esModule", { value: true });
88
+ exports.retroFileTasksHandler = void 0;
89
+ const child_process_1 = require("child_process");
90
+ const brain_1 = require("../../lib/brain");
91
+ const brain_ops_1 = require("../../lib/brain-ops");
92
+ const output = __importStar(require("@poa-box/cli/lib/output"));
93
+ /**
94
+ * Build a structured task description for a filed retro change. The
95
+ * description follows the /task-create skill template: context,
96
+ * deliverable, acceptance, constraints, context links.
97
+ */
98
+ function buildTaskDescription(retro, change) {
99
+ const windowLabel = retro.window
100
+ ? `HB#${retro.window.from ?? '?'}..HB#${retro.window.to ?? '?'}`
101
+ : '(no window)';
102
+ const retroLabel = `retro ${retro.id} (${windowLabel})`;
103
+ // Short name: take the summary, trim to 60 chars, no change-id prefix
104
+ // so the task search UI reads cleanly.
105
+ const name = change.summary.slice(0, 60);
106
+ const descLines = [];
107
+ descLines.push(`[CONTEXT] This task was filed automatically by pop brain retro file-tasks from ${retroLabel}, change ${change.id}. The change was agreed during retro discussion and is ready to ship.`);
108
+ descLines.push('');
109
+ descLines.push(`[SUMMARY]`);
110
+ descLines.push(change.summary);
111
+ if (change.details) {
112
+ descLines.push('');
113
+ descLines.push(`[DETAILS]`);
114
+ descLines.push(change.details);
115
+ }
116
+ descLines.push('');
117
+ descLines.push(`[RETRO CONTEXT]`);
118
+ if (retro.author)
119
+ descLines.push(`- Retro author: ${retro.author}`);
120
+ descLines.push(`- Retro window: ${windowLabel}`);
121
+ descLines.push(`- Retro id: ${retro.id}`);
122
+ descLines.push(`- Change id: ${change.id}`);
123
+ if (Array.isArray(retro.discussion) && retro.discussion.length > 0) {
124
+ descLines.push(`- Discussion entries: ${retro.discussion.length}`);
125
+ // Find vote tallies on this specific change.
126
+ const voteCounts = {};
127
+ for (const entry of retro.discussion) {
128
+ const vote = entry?.votePerChange?.[change.id];
129
+ if (typeof vote === 'string') {
130
+ voteCounts[vote] = (voteCounts[vote] ?? 0) + 1;
131
+ }
132
+ }
133
+ if (Object.keys(voteCounts).length > 0) {
134
+ const tally = Object.entries(voteCounts).map(([v, n]) => `${n} ${v}`).join(', ');
135
+ descLines.push(`- Votes on this change: ${tally}`);
136
+ }
137
+ }
138
+ descLines.push('');
139
+ descLines.push(`[ACCEPTANCE]`);
140
+ descLines.push('- Implementation addresses the summary/details above');
141
+ descLines.push('- Any tests or verification appropriate to the change type');
142
+ descLines.push(`- Update the retro via pop brain retro respond with a shipped-note comment`);
143
+ descLines.push('');
144
+ descLines.push(`[CONSTRAINTS]`);
145
+ descLines.push('- Reuse existing POP CLI + brain infra — do not introduce new persistence layers');
146
+ descLines.push('- Pinned stack (helia@5.5.1, libp2p@2.10, gossipsub@14) unchanged');
147
+ return { name, description: descLines.join('\n') };
148
+ }
149
+ exports.retroFileTasksHandler = {
150
+ builder: (yargs) => yargs
151
+ .option('doc', {
152
+ describe: 'Brain document ID (default: pop.brain.retros)',
153
+ type: 'string',
154
+ default: 'pop.brain.retros',
155
+ })
156
+ .option('retro', {
157
+ describe: 'The retro.id whose agreed changes should be filed as tasks',
158
+ type: 'string',
159
+ demandOption: true,
160
+ })
161
+ .option('project', {
162
+ describe: 'Target project for the new tasks (default: "CLI Infrastructure")',
163
+ type: 'string',
164
+ default: 'CLI Infrastructure',
165
+ })
166
+ .option('payout', {
167
+ describe: 'PT payout per filed task (default: 10)',
168
+ type: 'number',
169
+ default: 10,
170
+ })
171
+ .option('difficulty', {
172
+ describe: 'Difficulty label for filed tasks',
173
+ type: 'string',
174
+ choices: ['easy', 'medium', 'hard'],
175
+ default: 'medium',
176
+ })
177
+ .option('est-hours', {
178
+ describe: 'Estimated hours per filed task',
179
+ type: 'number',
180
+ default: 2,
181
+ })
182
+ .option('dry-run', {
183
+ describe: 'Preview what would be filed without creating tasks or mutating the retro',
184
+ type: 'boolean',
185
+ default: false,
186
+ })
187
+ .option('yes', {
188
+ alias: 'y',
189
+ describe: 'Skip confirmation prompts on the underlying pop task create calls',
190
+ type: 'boolean',
191
+ default: true,
192
+ }),
193
+ handler: async (argv) => {
194
+ try {
195
+ // Load the retro via openBrainDoc (same read path as retro-show).
196
+ const { doc } = await (0, brain_1.openBrainDoc)(argv.doc);
197
+ const retros = Array.isArray(doc?.retros) ? doc.retros : [];
198
+ const retro = retros.find(r => r?.id === argv.retro);
199
+ if (!retro) {
200
+ const candidates = retros.map(r => r?.id).filter((id) => typeof id === 'string').slice(0, 8);
201
+ output.error(`Retro "${argv.retro}" not found in ${argv.doc}. ` +
202
+ `Available ids (first 8): ${candidates.join(', ') || '(none)'}`);
203
+ process.exitCode = 1;
204
+ return;
205
+ }
206
+ if (retro.removed) {
207
+ output.error(`Retro "${argv.retro}" is tombstoned — cannot file tasks against a removed retro.`);
208
+ process.exitCode = 1;
209
+ return;
210
+ }
211
+ // Partition changes by status.
212
+ const changes = Array.isArray(retro.proposedChanges) ? retro.proposedChanges : [];
213
+ const agreed = changes.filter(c => c?.status === 'agreed');
214
+ const alreadyFiled = changes.filter(c => c?.status === 'filed');
215
+ const rejected = changes.filter(c => c?.status === 'rejected');
216
+ const stillProposed = changes.filter(c => c?.status === 'proposed' || c?.status === 'modified');
217
+ if (agreed.length === 0) {
218
+ if (output.isJsonMode()) {
219
+ output.json({
220
+ status: 'noop',
221
+ docId: argv.doc,
222
+ retroId: argv.retro,
223
+ reason: 'no changes at status=agreed',
224
+ counts: {
225
+ total: changes.length,
226
+ agreed: 0,
227
+ alreadyFiled: alreadyFiled.length,
228
+ rejected: rejected.length,
229
+ stillProposed: stillProposed.length,
230
+ },
231
+ });
232
+ }
233
+ else {
234
+ console.log('');
235
+ console.log(` No changes at status='agreed' in retro "${argv.retro}". Nothing to file.`);
236
+ console.log('');
237
+ console.log(` Current status breakdown:`);
238
+ console.log(` total: ${changes.length}`);
239
+ console.log(` agreed: 0 (ready to file)`);
240
+ console.log(` already filed: ${alreadyFiled.length}`);
241
+ console.log(` rejected: ${rejected.length}`);
242
+ console.log(` still in discussion: ${stillProposed.length}`);
243
+ console.log('');
244
+ if (stillProposed.length > 0) {
245
+ console.log(` Changes still under discussion:`);
246
+ for (const c of stillProposed)
247
+ console.log(` - ${c.id}: ${c.summary}`);
248
+ console.log('');
249
+ console.log(` Other agents need to agree via "pop brain retro respond --to ${argv.retro} --vote ${stillProposed[0]?.id}=agree" before they can be filed.`);
250
+ }
251
+ console.log('');
252
+ }
253
+ return;
254
+ }
255
+ // Dry-run: print the plan and exit.
256
+ if (argv.dryRun) {
257
+ console.log('');
258
+ console.log(` [DRY RUN] Would file ${agreed.length} task${agreed.length === 1 ? '' : 's'} for retro "${argv.retro}"`);
259
+ console.log('');
260
+ for (const change of agreed) {
261
+ const { name, description } = buildTaskDescription(retro, change);
262
+ console.log(` === ${change.id} → new task ===`);
263
+ console.log(` name: ${name}`);
264
+ console.log(` project: ${argv.project}`);
265
+ console.log(` payout: ${argv.payout} PT`);
266
+ console.log(` difficulty: ${argv.difficulty}`);
267
+ console.log(` est hours: ${argv.estHours}`);
268
+ console.log(` description: ${description.split('\n').slice(0, 3).join(' ').slice(0, 160)}...`);
269
+ console.log('');
270
+ }
271
+ console.log(` Already filed: ${alreadyFiled.length} · rejected: ${rejected.length} · still proposed: ${stillProposed.length}`);
272
+ console.log('');
273
+ console.log(` Run without --dry-run to actually file the tasks.`);
274
+ console.log('');
275
+ return;
276
+ }
277
+ // Real run: for each agreed change, spawn `pop task create` and
278
+ // capture the resulting task id. Shelling out keeps this command
279
+ // decoupled from the task create plumbing (which has its own
280
+ // sponsored-tx + fee-limit logic we don't want to duplicate).
281
+ const cliPath = process.argv[1]; // dist/index.js, same entrypoint
282
+ const filed = [];
283
+ for (const change of agreed) {
284
+ const { name, description } = buildTaskDescription(retro, change);
285
+ const createArgs = [
286
+ cliPath, 'task', 'create',
287
+ '--force',
288
+ '--project', argv.project,
289
+ '--name', name,
290
+ '--description', description,
291
+ '--payout', String(argv.payout),
292
+ '--difficulty', argv.difficulty,
293
+ '--est-hours', String(argv.estHours),
294
+ '--json',
295
+ '-y',
296
+ ];
297
+ const res = (0, child_process_1.spawnSync)(process.execPath, createArgs, {
298
+ encoding: 'utf8',
299
+ env: process.env,
300
+ stdio: ['ignore', 'pipe', 'pipe'],
301
+ });
302
+ if (res.status !== 0) {
303
+ output.error(`pop task create failed for change ${change.id}: ${res.stderr || res.stdout}`);
304
+ process.exitCode = 1;
305
+ return;
306
+ }
307
+ let parsed;
308
+ try {
309
+ parsed = JSON.parse(res.stdout);
310
+ }
311
+ catch (err) {
312
+ output.error(`pop task create returned unparseable JSON for change ${change.id}: ${res.stdout}`);
313
+ process.exitCode = 1;
314
+ return;
315
+ }
316
+ const taskId = parsed.taskId;
317
+ const txHash = parsed.txHash;
318
+ if (!taskId) {
319
+ output.error(`pop task create for change ${change.id} returned no taskId: ${JSON.stringify(parsed)}`);
320
+ process.exitCode = 1;
321
+ return;
322
+ }
323
+ // Flip the retro change's status to 'filed' with filedTaskId.
324
+ await (0, brain_ops_1.routedDispatch)({
325
+ type: 'updateChangeStatus',
326
+ docId: argv.doc,
327
+ retroId: argv.retro,
328
+ changeId: change.id,
329
+ newStatus: 'filed',
330
+ filedTaskId: String(taskId),
331
+ });
332
+ filed.push({ changeId: change.id, taskId: String(taskId), txHash });
333
+ }
334
+ if (output.isJsonMode()) {
335
+ output.json({
336
+ status: 'ok',
337
+ docId: argv.doc,
338
+ retroId: argv.retro,
339
+ filed,
340
+ filedCount: filed.length,
341
+ skippedAlreadyFiled: alreadyFiled.length,
342
+ skippedRejected: rejected.length,
343
+ skippedStillProposed: stillProposed.length,
344
+ });
345
+ }
346
+ else {
347
+ console.log('');
348
+ console.log(` Filed ${filed.length} task${filed.length === 1 ? '' : 's'} from retro "${argv.retro}"`);
349
+ console.log('');
350
+ for (const f of filed) {
351
+ console.log(` ✓ ${f.changeId} → task #${f.taskId}`);
352
+ console.log(` tx: ${f.txHash}`);
353
+ }
354
+ console.log('');
355
+ if (alreadyFiled.length > 0)
356
+ console.log(` (${alreadyFiled.length} previously filed — skipped)`);
357
+ if (rejected.length > 0)
358
+ console.log(` (${rejected.length} rejected — skipped)`);
359
+ if (stillProposed.length > 0)
360
+ console.log(` (${stillProposed.length} still under discussion — skipped)`);
361
+ console.log('');
362
+ }
363
+ }
364
+ catch (err) {
365
+ output.error(err.message);
366
+ process.exitCode = 1;
367
+ }
368
+ finally {
369
+ await (0, brain_1.stopBrainNode)();
370
+ }
371
+ },
372
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * pop brain retro list — list retros in pop.brain.retros.
3
+ *
4
+ * Filters:
5
+ * --status open|discussed|shipped only show retros at this status
6
+ * --doc <doc-id> default: pop.brain.retros
7
+ *
8
+ * JSON mode emits a machine-readable array; human mode prints a table.
9
+ *
10
+ * Always reads in-process (no daemon routing) because this is a
11
+ * pure-read path and concurrent reads against the helia blockstore
12
+ * work fine alongside a running daemon (HB#323 verification).
13
+ */
14
+ import type { Argv, ArgumentsCamelCase } from 'yargs';
15
+ import type { RetroStatus } from '../../lib/brain-projections';
16
+ interface RetroListArgs {
17
+ doc: string;
18
+ status?: RetroStatus;
19
+ }
20
+ export declare const retroListHandler: {
21
+ builder: (yargs: Argv) => Argv<{
22
+ doc: string;
23
+ } & {
24
+ status: RetroStatus | undefined;
25
+ }>;
26
+ handler: (argv: ArgumentsCamelCase<RetroListArgs>) => Promise<void>;
27
+ };
28
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /**
3
+ * pop brain retro list — list retros in pop.brain.retros.
4
+ *
5
+ * Filters:
6
+ * --status open|discussed|shipped only show retros at this status
7
+ * --doc <doc-id> default: pop.brain.retros
8
+ *
9
+ * JSON mode emits a machine-readable array; human mode prints a table.
10
+ *
11
+ * Always reads in-process (no daemon routing) because this is a
12
+ * pure-read path and concurrent reads against the helia blockstore
13
+ * work fine alongside a running daemon (HB#323 verification).
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.retroListHandler = void 0;
50
+ const brain_1 = require("../../lib/brain");
51
+ const output = __importStar(require("@poa-box/cli/lib/output"));
52
+ const VALID_STATUSES = ['open', 'discussed', 'shipped'];
53
+ exports.retroListHandler = {
54
+ builder: (yargs) => yargs
55
+ .option('doc', {
56
+ describe: 'Brain document ID (default: pop.brain.retros)',
57
+ type: 'string',
58
+ default: 'pop.brain.retros',
59
+ })
60
+ .option('status', {
61
+ describe: 'Filter by retro status',
62
+ type: 'string',
63
+ choices: VALID_STATUSES,
64
+ }),
65
+ handler: async (argv) => {
66
+ try {
67
+ const { doc } = await (0, brain_1.openBrainDoc)(argv.doc);
68
+ const retros = Array.isArray(doc?.retros) ? doc.retros : [];
69
+ const live = retros.filter(r => r?.removed !== true);
70
+ const filtered = argv.status
71
+ ? live.filter(r => r?.status === argv.status)
72
+ : live;
73
+ if (output.isJsonMode()) {
74
+ output.json({
75
+ docId: argv.doc,
76
+ statusFilter: argv.status ?? null,
77
+ count: filtered.length,
78
+ retros: filtered.map(r => ({
79
+ id: r.id,
80
+ author: r.author,
81
+ hb: r.hb,
82
+ window: r.window,
83
+ status: r.status ?? 'open',
84
+ changeCount: Array.isArray(r.proposedChanges) ? r.proposedChanges.length : 0,
85
+ discussionCount: Array.isArray(r.discussion) ? r.discussion.length : 0,
86
+ createdAt: r.createdAt,
87
+ closedAt: r.closedAt,
88
+ })),
89
+ });
90
+ return;
91
+ }
92
+ if (filtered.length === 0) {
93
+ console.log(argv.status
94
+ ? `No retros in ${argv.doc} with status='${argv.status}'.`
95
+ : `No retros in ${argv.doc} yet. Start one with: pop brain retro start --window-from N --window-to M --changes-file <path>`);
96
+ return;
97
+ }
98
+ console.log('');
99
+ console.log(` Retros in ${argv.doc}${argv.status ? ` (status=${argv.status})` : ''}`);
100
+ console.log('');
101
+ console.log(' ID Author Window Status Changes');
102
+ console.log(' ' + '─'.repeat(80));
103
+ for (const r of filtered) {
104
+ const id = (r.id ?? '(no id)').padEnd(32).slice(0, 32);
105
+ const author = (r.author ?? '(unknown)').slice(0, 12).padEnd(14);
106
+ const windowLabel = r.window
107
+ ? `#${r.window.from ?? '?'}..#${r.window.to ?? '?'}`.padEnd(12)
108
+ : '(no window)'.padEnd(12);
109
+ const status = (r.status ?? 'open').padEnd(10);
110
+ const changeCount = Array.isArray(r.proposedChanges) ? r.proposedChanges.length : 0;
111
+ console.log(` ${id}${author}${windowLabel}${status} ${changeCount}`);
112
+ }
113
+ console.log('');
114
+ console.log(` ${filtered.length} retro${filtered.length === 1 ? '' : 's'}. Run "pop brain retro show <id>" for full detail.`);
115
+ console.log('');
116
+ }
117
+ catch (err) {
118
+ output.error(err.message);
119
+ process.exitCode = 1;
120
+ }
121
+ finally {
122
+ await (0, brain_1.stopBrainNode)();
123
+ }
124
+ },
125
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * pop brain retro mark-change — manually set a proposed change's status.
3
+ *
4
+ * The retro workflow separates VOTES (discussion-level signals) from
5
+ * CHANGE STATUS (decision). Other agents respond via `pop brain retro
6
+ * respond --vote change-1=agree`, which records a vote entry in the
7
+ * discussion array — NOT a status change on the proposed change.
8
+ *
9
+ * When the retro author (or a designated file-tasks runner) decides a
10
+ * change has enough agreement, they explicitly flip its status to
11
+ * 'agreed' with this command. Then `pop brain retro file-tasks` picks
12
+ * up the change and converts it into a real on-chain task.
13
+ *
14
+ * MVP design: quorum interpretation is human-judged per the task spec
15
+ * (#344 "out of scope: cross-agent voting quorum logic"). This command
16
+ * is the escape hatch that lets operators make the call explicitly.
17
+ *
18
+ * Usage:
19
+ *
20
+ * pop brain retro mark-change retro-327-... change-1 --status agreed
21
+ * pop brain retro mark-change retro-327-... change-2 --status rejected
22
+ * pop brain retro mark-change retro-327-... change-3 --status modified
23
+ *
24
+ * Status values: proposed, agreed, modified, rejected, filed.
25
+ * Setting status to 'filed' manually is unusual — prefer `file-tasks`,
26
+ * which records the filedTaskId for you. Allowed here for emergency
27
+ * manual reconciliation.
28
+ */
29
+ import type { Argv, ArgumentsCamelCase } from 'yargs';
30
+ import type { RetroChangeStatus } from '../../lib/brain-projections';
31
+ interface MarkChangeArgs {
32
+ doc: string;
33
+ retroId: string;
34
+ changeId: string;
35
+ status: RetroChangeStatus;
36
+ filedTaskId?: string;
37
+ 'idempotency-key'?: string;
38
+ 'no-idempotency'?: boolean;
39
+ }
40
+ export declare const retroMarkChangeHandler: {
41
+ builder: (yargs: Argv) => Argv<import("yargs").Defined<{
42
+ "retro-id": string | undefined;
43
+ } & {
44
+ "change-id": string | undefined;
45
+ } & {
46
+ doc: string;
47
+ } & {
48
+ status: RetroChangeStatus;
49
+ } & {
50
+ "filed-task-id": string | undefined;
51
+ } & {
52
+ "idempotency-key": string | undefined;
53
+ } & {
54
+ "no-idempotency": boolean;
55
+ }, "retro-id" | "change-id">>;
56
+ handler: (argv: ArgumentsCamelCase<MarkChangeArgs>) => Promise<void>;
57
+ };
58
+ export {};