@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.
- package/.env.agent.template +20 -0
- package/README.md +46 -0
- package/brain/Config/agent-config.json +14 -0
- package/brain/Config/brain-allowlist.json +20 -0
- package/brain/Identity/goals.template.md +23 -0
- package/brain/Identity/how-i-think.md +406 -0
- package/brain/Identity/who-i-am.template.md +34 -0
- package/brain/Knowledge/BOOTSTRAP.md +66 -0
- package/brain/Knowledge/audit-corpus-index.json +406 -0
- package/brain/Knowledge/discussions.json +245 -0
- package/brain/Knowledge/pop.brain.brainstorms.generated.md +48 -0
- package/brain/Knowledge/pop.brain.brainstorms.genesis.bin +0 -0
- package/brain/Knowledge/pop.brain.heuristics.snapshot.bin +0 -0
- package/brain/Knowledge/pop.brain.projects.generated.md +16 -0
- package/brain/Knowledge/pop.brain.projects.genesis.bin +0 -0
- package/brain/Knowledge/pop.brain.retros.generated.md +91 -0
- package/brain/Knowledge/pop.brain.retros.genesis.bin +0 -0
- package/brain/Knowledge/pop.brain.shared.generated.md +3811 -0
- package/brain/Knowledge/pop.brain.shared.genesis.bin +0 -0
- package/brain/Knowledge/projects.md +181 -0
- package/brain/Knowledge/risk-framework.md +90 -0
- package/brain/Knowledge/shared.md +416 -0
- package/brain/Knowledge/sprint-priorities.md +439 -0
- package/brain/Memory/.gitkeep +0 -0
- package/dist/commands/agent/daily-digest.d.ts +24 -0
- package/dist/commands/agent/daily-digest.js +336 -0
- package/dist/commands/agent/delegate.d.ts +12 -0
- package/dist/commands/agent/delegate.js +91 -0
- package/dist/commands/agent/deploy-to-org.d.ts +20 -0
- package/dist/commands/agent/deploy-to-org.js +154 -0
- package/dist/commands/agent/index.d.ts +2 -0
- package/dist/commands/agent/index.js +27 -0
- package/dist/commands/agent/init.d.ts +19 -0
- package/dist/commands/agent/init.js +303 -0
- package/dist/commands/agent/onboard.d.ts +22 -0
- package/dist/commands/agent/onboard.js +192 -0
- package/dist/commands/agent/paymaster-status.d.ts +14 -0
- package/dist/commands/agent/paymaster-status.js +130 -0
- package/dist/commands/agent/register.d.ts +21 -0
- package/dist/commands/agent/register.js +116 -0
- package/dist/commands/agent/setup-sponsorship.d.ts +22 -0
- package/dist/commands/agent/setup-sponsorship.js +154 -0
- package/dist/commands/agent/status.d.ts +12 -0
- package/dist/commands/agent/status.js +171 -0
- package/dist/commands/agent/triage.d.ts +12 -0
- package/dist/commands/agent/triage.js +503 -0
- package/dist/commands/brain/advance-stage.d.ts +42 -0
- package/dist/commands/brain/advance-stage.js +206 -0
- package/dist/commands/brain/allowlist.d.ts +30 -0
- package/dist/commands/brain/allowlist.js +274 -0
- package/dist/commands/brain/append-lesson.d.ts +55 -0
- package/dist/commands/brain/append-lesson.js +245 -0
- package/dist/commands/brain/brainstorm.d.ts +154 -0
- package/dist/commands/brain/brainstorm.js +573 -0
- package/dist/commands/brain/daemon.d.ts +31 -0
- package/dist/commands/brain/daemon.js +348 -0
- package/dist/commands/brain/doctor.d.ts +27 -0
- package/dist/commands/brain/doctor.js +497 -0
- package/dist/commands/brain/edit-lesson.d.ts +51 -0
- package/dist/commands/brain/edit-lesson.js +248 -0
- package/dist/commands/brain/import-snapshot.d.ts +68 -0
- package/dist/commands/brain/import-snapshot.js +177 -0
- package/dist/commands/brain/index.d.ts +2 -0
- package/dist/commands/brain/index.js +67 -0
- package/dist/commands/brain/list.d.ts +21 -0
- package/dist/commands/brain/list.js +83 -0
- package/dist/commands/brain/migrate-projects.d.ts +44 -0
- package/dist/commands/brain/migrate-projects.js +209 -0
- package/dist/commands/brain/migrate.d.ts +74 -0
- package/dist/commands/brain/migrate.js +306 -0
- package/dist/commands/brain/new-project.d.ts +53 -0
- package/dist/commands/brain/new-project.js +226 -0
- package/dist/commands/brain/read.d.ts +24 -0
- package/dist/commands/brain/read.js +81 -0
- package/dist/commands/brain/remove-lesson.d.ts +47 -0
- package/dist/commands/brain/remove-lesson.js +206 -0
- package/dist/commands/brain/remove-project.d.ts +36 -0
- package/dist/commands/brain/remove-project.js +177 -0
- package/dist/commands/brain/retro-file-tasks.d.ts +84 -0
- package/dist/commands/brain/retro-file-tasks.js +372 -0
- package/dist/commands/brain/retro-list.d.ts +28 -0
- package/dist/commands/brain/retro-list.js +125 -0
- package/dist/commands/brain/retro-mark-change.d.ts +58 -0
- package/dist/commands/brain/retro-mark-change.js +176 -0
- package/dist/commands/brain/retro-remove.d.ts +36 -0
- package/dist/commands/brain/retro-remove.js +142 -0
- package/dist/commands/brain/retro-respond.d.ts +56 -0
- package/dist/commands/brain/retro-respond.js +250 -0
- package/dist/commands/brain/retro-show.d.ts +23 -0
- package/dist/commands/brain/retro-show.js +100 -0
- package/dist/commands/brain/retro-start.d.ts +55 -0
- package/dist/commands/brain/retro-start.js +311 -0
- package/dist/commands/brain/search.d.ts +48 -0
- package/dist/commands/brain/search.js +190 -0
- package/dist/commands/brain/snapshot.d.ts +32 -0
- package/dist/commands/brain/snapshot.js +243 -0
- package/dist/commands/brain/status.d.ts +15 -0
- package/dist/commands/brain/status.js +166 -0
- package/dist/commands/brain/subscribe.d.ts +28 -0
- package/dist/commands/brain/subscribe.js +90 -0
- package/dist/commands/brain/tag.d.ts +46 -0
- package/dist/commands/brain/tag.js +192 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +22 -0
- package/dist/lib/brain-daemon.d.ts +126 -0
- package/dist/lib/brain-daemon.js +811 -0
- package/dist/lib/brain-membership.d.ts +58 -0
- package/dist/lib/brain-membership.js +115 -0
- package/dist/lib/brain-migrate-projects.d.ts +43 -0
- package/dist/lib/brain-migrate-projects.js +247 -0
- package/dist/lib/brain-migrate.d.ts +77 -0
- package/dist/lib/brain-migrate.js +328 -0
- package/dist/lib/brain-ops.d.ts +271 -0
- package/dist/lib/brain-ops.js +571 -0
- package/dist/lib/brain-paths.d.ts +15 -0
- package/dist/lib/brain-paths.js +33 -0
- package/dist/lib/brain-projections.d.ts +216 -0
- package/dist/lib/brain-projections.js +829 -0
- package/dist/lib/brain-schemas.d.ts +36 -0
- package/dist/lib/brain-schemas.js +316 -0
- package/dist/lib/brain-signing.d.ts +103 -0
- package/dist/lib/brain-signing.js +256 -0
- package/dist/lib/brain.d.ts +198 -0
- package/dist/lib/brain.js +1057 -0
- package/dist/pop-agent.d.ts +1 -0
- package/dist/pop-agent.js +18 -0
- package/docs/agent.md +126 -0
- package/docs/agents/brain-anti-entropy.md +127 -0
- package/docs/agents/brain-cross-device-onboarding.md +210 -0
- package/docs/agents/brain-cross-machine-smoke.md +241 -0
- package/docs/agents/brain-layer-setup.md +725 -0
- package/docs/agents/offboarding-protocol.md +188 -0
- package/docs/agents/onboarding-protocol.md +243 -0
- package/docs/agents/running-an-agent.md +200 -0
- package/docs/brain.md +560 -0
- package/package.json +61 -0
- package/scripts/apply.sh +140 -0
- package/scripts/onboard.sh +205 -0
- 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 {};
|