@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,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* pop brain retro show — render a single retro as markdown.
|
|
4
|
+
*
|
|
5
|
+
* Loads the retro doc, extracts the requested retro, and runs it
|
|
6
|
+
* through the projection layer. Same shape + schema as projectRetros
|
|
7
|
+
* produces for the full doc snapshot, but scoped to one entry.
|
|
8
|
+
*
|
|
9
|
+
* Pure read path — no daemon routing required.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.retroShowHandler = void 0;
|
|
46
|
+
const brain_1 = require("../../lib/brain");
|
|
47
|
+
const brain_projections_1 = require("../../lib/brain-projections");
|
|
48
|
+
const output = __importStar(require("@poa-box/cli/lib/output"));
|
|
49
|
+
exports.retroShowHandler = {
|
|
50
|
+
builder: (yargs) => yargs
|
|
51
|
+
.positional('retro-id', {
|
|
52
|
+
describe: 'The retro.id to show',
|
|
53
|
+
type: 'string',
|
|
54
|
+
})
|
|
55
|
+
.option('doc', {
|
|
56
|
+
describe: 'Brain document ID (default: pop.brain.retros)',
|
|
57
|
+
type: 'string',
|
|
58
|
+
default: 'pop.brain.retros',
|
|
59
|
+
})
|
|
60
|
+
.demandOption('retro-id'),
|
|
61
|
+
handler: async (argv) => {
|
|
62
|
+
try {
|
|
63
|
+
const { doc, headCid } = await (0, brain_1.openBrainDoc)(argv.doc);
|
|
64
|
+
const retros = Array.isArray(doc?.retros) ? doc.retros : [];
|
|
65
|
+
const target = retros.find(r => r?.id === argv.retroId);
|
|
66
|
+
if (!target) {
|
|
67
|
+
const candidates = retros
|
|
68
|
+
.map(r => r?.id)
|
|
69
|
+
.filter((id) => typeof id === 'string')
|
|
70
|
+
.slice(0, 8);
|
|
71
|
+
output.error(`Retro "${argv.retroId}" not found in ${argv.doc}. ` +
|
|
72
|
+
`Available ids (first 8): ${candidates.join(', ') || '(none)'}`);
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (output.isJsonMode()) {
|
|
77
|
+
output.json({
|
|
78
|
+
docId: argv.doc,
|
|
79
|
+
headCid,
|
|
80
|
+
retro: target,
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Render the ONE retro through the projection layer by wrapping
|
|
85
|
+
// it in a synthetic single-retro doc. This keeps the output
|
|
86
|
+
// format identical to what `pop brain snapshot` would produce,
|
|
87
|
+
// so reviewers see the same rendered structure whether they're
|
|
88
|
+
// looking at a live retro or a committed snapshot.
|
|
89
|
+
const markdown = (0, brain_projections_1.projectRetros)({ retros: [target] }, headCid);
|
|
90
|
+
console.log(markdown);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
output.error(err.message);
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
await (0, brain_1.stopBrainNode)();
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pop brain retro start — create a new retrospective entry in pop.brain.retros.
|
|
3
|
+
*
|
|
4
|
+
* Input:
|
|
5
|
+
* --window-from <HB#> lower bound of the HB window covered
|
|
6
|
+
* --window-to <HB#> upper bound of the HB window covered
|
|
7
|
+
* --observations-file <path> markdown file with "## What worked" and
|
|
8
|
+
* "## What didn't work" sections (both optional)
|
|
9
|
+
* --changes-file <path> JSON or markdown file listing proposed
|
|
10
|
+
* changes. JSON shape is an array of
|
|
11
|
+
* {id, summary, details?} objects;
|
|
12
|
+
* markdown shape is `- **change-1** — summary`
|
|
13
|
+
* lines (details on the next indented line).
|
|
14
|
+
* --id <retro-id> optional override (default: retro-<hb>-<unix>)
|
|
15
|
+
* --author <label> optional override (default: signing address)
|
|
16
|
+
* --doc <doc-id> default: pop.brain.retros
|
|
17
|
+
*
|
|
18
|
+
* The retro is written via routedDispatch so it lands in a running daemon
|
|
19
|
+
* when present and falls back to in-process applyBrainChange otherwise.
|
|
20
|
+
* Schema validation happens inside dispatchOp at write time — empty
|
|
21
|
+
* changes list, bad window, duplicate change ids all fail fast with a
|
|
22
|
+
* clear error.
|
|
23
|
+
*/
|
|
24
|
+
import type { Argv, ArgumentsCamelCase } from 'yargs';
|
|
25
|
+
interface RetroStartArgs {
|
|
26
|
+
doc: string;
|
|
27
|
+
windowFrom: number;
|
|
28
|
+
windowTo: number;
|
|
29
|
+
observationsFile?: string;
|
|
30
|
+
changesFile: string;
|
|
31
|
+
id?: string;
|
|
32
|
+
author?: string;
|
|
33
|
+
hb?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare const retroStartHandler: {
|
|
36
|
+
builder: (yargs: Argv) => Argv<{
|
|
37
|
+
doc: string;
|
|
38
|
+
} & {
|
|
39
|
+
"window-from": number;
|
|
40
|
+
} & {
|
|
41
|
+
"window-to": number;
|
|
42
|
+
} & {
|
|
43
|
+
"observations-file": string | undefined;
|
|
44
|
+
} & {
|
|
45
|
+
"changes-file": string;
|
|
46
|
+
} & {
|
|
47
|
+
id: string | undefined;
|
|
48
|
+
} & {
|
|
49
|
+
author: string | undefined;
|
|
50
|
+
} & {
|
|
51
|
+
hb: number | undefined;
|
|
52
|
+
}>;
|
|
53
|
+
handler: (argv: ArgumentsCamelCase<RetroStartArgs>) => Promise<void>;
|
|
54
|
+
};
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* pop brain retro start — create a new retrospective entry in pop.brain.retros.
|
|
4
|
+
*
|
|
5
|
+
* Input:
|
|
6
|
+
* --window-from <HB#> lower bound of the HB window covered
|
|
7
|
+
* --window-to <HB#> upper bound of the HB window covered
|
|
8
|
+
* --observations-file <path> markdown file with "## What worked" and
|
|
9
|
+
* "## What didn't work" sections (both optional)
|
|
10
|
+
* --changes-file <path> JSON or markdown file listing proposed
|
|
11
|
+
* changes. JSON shape is an array of
|
|
12
|
+
* {id, summary, details?} objects;
|
|
13
|
+
* markdown shape is `- **change-1** — summary`
|
|
14
|
+
* lines (details on the next indented line).
|
|
15
|
+
* --id <retro-id> optional override (default: retro-<hb>-<unix>)
|
|
16
|
+
* --author <label> optional override (default: signing address)
|
|
17
|
+
* --doc <doc-id> default: pop.brain.retros
|
|
18
|
+
*
|
|
19
|
+
* The retro is written via routedDispatch so it lands in a running daemon
|
|
20
|
+
* when present and falls back to in-process applyBrainChange otherwise.
|
|
21
|
+
* Schema validation happens inside dispatchOp at write time — empty
|
|
22
|
+
* changes list, bad window, duplicate change ids all fail fast with a
|
|
23
|
+
* clear error.
|
|
24
|
+
*/
|
|
25
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
28
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
29
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
30
|
+
}
|
|
31
|
+
Object.defineProperty(o, k2, desc);
|
|
32
|
+
}) : (function(o, m, k, k2) {
|
|
33
|
+
if (k2 === undefined) k2 = k;
|
|
34
|
+
o[k2] = m[k];
|
|
35
|
+
}));
|
|
36
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
37
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
38
|
+
}) : function(o, v) {
|
|
39
|
+
o["default"] = v;
|
|
40
|
+
});
|
|
41
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
42
|
+
var ownKeys = function(o) {
|
|
43
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
44
|
+
var ar = [];
|
|
45
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
46
|
+
return ar;
|
|
47
|
+
};
|
|
48
|
+
return ownKeys(o);
|
|
49
|
+
};
|
|
50
|
+
return function (mod) {
|
|
51
|
+
if (mod && mod.__esModule) return mod;
|
|
52
|
+
var result = {};
|
|
53
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
54
|
+
__setModuleDefault(result, mod);
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
})();
|
|
58
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
+
exports.retroStartHandler = void 0;
|
|
60
|
+
const fs_1 = require("fs");
|
|
61
|
+
const path_1 = require("path");
|
|
62
|
+
const ethers_1 = require("ethers");
|
|
63
|
+
const brain_1 = require("../../lib/brain");
|
|
64
|
+
const brain_ops_1 = require("../../lib/brain-ops");
|
|
65
|
+
const output = __importStar(require("@poa-box/cli/lib/output"));
|
|
66
|
+
/**
|
|
67
|
+
* Parse the observations file. Expects a markdown document with
|
|
68
|
+
* `## What worked` and `## What didn't work` sections. Both sections
|
|
69
|
+
* are optional; sections outside those two are ignored.
|
|
70
|
+
*/
|
|
71
|
+
function parseObservationsFile(content) {
|
|
72
|
+
const result = {};
|
|
73
|
+
// Split into sections on H2 headers. The regex keeps the header text
|
|
74
|
+
// as a capture so we can dispatch on it.
|
|
75
|
+
const sections = content.split(/^##\s+/m).slice(1);
|
|
76
|
+
for (const section of sections) {
|
|
77
|
+
const nl = section.indexOf('\n');
|
|
78
|
+
if (nl < 0)
|
|
79
|
+
continue;
|
|
80
|
+
const header = section.slice(0, nl).trim().toLowerCase();
|
|
81
|
+
const body = section.slice(nl + 1).trim();
|
|
82
|
+
if (!body)
|
|
83
|
+
continue;
|
|
84
|
+
if (/worked/i.test(header) && !/didn/i.test(header)) {
|
|
85
|
+
result.worked = body;
|
|
86
|
+
}
|
|
87
|
+
else if (/didn.?t\s*work|didntwork|not\s*work/i.test(header)) {
|
|
88
|
+
result.didntWork = body;
|
|
89
|
+
}
|
|
90
|
+
// Silently drop other sections — they might be "Next actions" or
|
|
91
|
+
// similar that don't belong in observations.
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Parse the proposed-changes file. Supports two shapes:
|
|
97
|
+
*
|
|
98
|
+
* 1. JSON: `[{"id": "change-1", "summary": "...", "details": "..."}, ...]`
|
|
99
|
+
* 2. Markdown: `- **change-1** — summary\n details (indented)\n- **change-2** — ...`
|
|
100
|
+
*
|
|
101
|
+
* JSON is tried first. If parse fails, fall back to markdown scanning.
|
|
102
|
+
*/
|
|
103
|
+
function parseChangesFile(content) {
|
|
104
|
+
// Try JSON first.
|
|
105
|
+
const trimmed = content.trim();
|
|
106
|
+
if (trimmed.startsWith('[') || trimmed.startsWith('{')) {
|
|
107
|
+
try {
|
|
108
|
+
const parsed = JSON.parse(trimmed);
|
|
109
|
+
const items = Array.isArray(parsed) ? parsed : parsed.changes ?? [];
|
|
110
|
+
return items.map((item) => {
|
|
111
|
+
if (!item.id || !item.summary) {
|
|
112
|
+
throw new Error(`change entry missing id or summary: ${JSON.stringify(item)}`);
|
|
113
|
+
}
|
|
114
|
+
const out = {
|
|
115
|
+
id: String(item.id),
|
|
116
|
+
summary: String(item.summary),
|
|
117
|
+
};
|
|
118
|
+
if (item.details)
|
|
119
|
+
out.details = String(item.details);
|
|
120
|
+
return out;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
throw new Error(`Failed to parse changes file as JSON: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Markdown: bullet lines that start with `- **<id>**`. Anything
|
|
128
|
+
// indented under a bullet belongs to that change's details.
|
|
129
|
+
const changes = [];
|
|
130
|
+
const lines = content.split('\n');
|
|
131
|
+
let current = null;
|
|
132
|
+
const detailLines = [];
|
|
133
|
+
const commit = () => {
|
|
134
|
+
if (!current)
|
|
135
|
+
return;
|
|
136
|
+
if (detailLines.length > 0) {
|
|
137
|
+
current.details = detailLines.join('\n').trim();
|
|
138
|
+
}
|
|
139
|
+
changes.push(current);
|
|
140
|
+
current = null;
|
|
141
|
+
detailLines.length = 0;
|
|
142
|
+
};
|
|
143
|
+
const bulletRe = /^-\s+\*\*([^*]+)\*\*\s*[—–-]\s*(.+)$/;
|
|
144
|
+
for (const rawLine of lines) {
|
|
145
|
+
const m = rawLine.match(bulletRe);
|
|
146
|
+
if (m) {
|
|
147
|
+
commit();
|
|
148
|
+
current = { id: m[1].trim(), summary: m[2].trim() };
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (current && /^\s+\S/.test(rawLine)) {
|
|
152
|
+
detailLines.push(rawLine.replace(/^\s+/, ''));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
commit();
|
|
156
|
+
if (changes.length === 0) {
|
|
157
|
+
throw new Error('Failed to parse changes file as markdown — expected bullet lines ' +
|
|
158
|
+
'like `- **change-1** — summary`. Try JSON format instead.');
|
|
159
|
+
}
|
|
160
|
+
return changes;
|
|
161
|
+
}
|
|
162
|
+
exports.retroStartHandler = {
|
|
163
|
+
builder: (yargs) => yargs
|
|
164
|
+
.option('doc', {
|
|
165
|
+
describe: 'Target brain document ID (default: pop.brain.retros)',
|
|
166
|
+
type: 'string',
|
|
167
|
+
default: 'pop.brain.retros',
|
|
168
|
+
})
|
|
169
|
+
.option('window-from', {
|
|
170
|
+
describe: 'First HB number covered by this retro',
|
|
171
|
+
type: 'number',
|
|
172
|
+
demandOption: true,
|
|
173
|
+
})
|
|
174
|
+
.option('window-to', {
|
|
175
|
+
describe: 'Last HB number covered by this retro',
|
|
176
|
+
type: 'number',
|
|
177
|
+
demandOption: true,
|
|
178
|
+
})
|
|
179
|
+
.option('observations-file', {
|
|
180
|
+
describe: 'Markdown file with `## What worked` and `## What didn\'t work` sections',
|
|
181
|
+
type: 'string',
|
|
182
|
+
})
|
|
183
|
+
.option('changes-file', {
|
|
184
|
+
describe: 'JSON or markdown file listing proposed changes. JSON: array of {id, summary, details?}. Markdown: bullet list with `- **id** — summary`.',
|
|
185
|
+
type: 'string',
|
|
186
|
+
demandOption: true,
|
|
187
|
+
})
|
|
188
|
+
.option('id', {
|
|
189
|
+
describe: 'Override the auto-generated retro id (default: retro-<hb>-<unix>)',
|
|
190
|
+
type: 'string',
|
|
191
|
+
})
|
|
192
|
+
.option('author', {
|
|
193
|
+
describe: 'Override the author label (default: signing wallet address)',
|
|
194
|
+
type: 'string',
|
|
195
|
+
})
|
|
196
|
+
.option('hb', {
|
|
197
|
+
describe: 'Heartbeat number at retro start (default: window-to)',
|
|
198
|
+
type: 'number',
|
|
199
|
+
}),
|
|
200
|
+
handler: async (argv) => {
|
|
201
|
+
try {
|
|
202
|
+
if (argv.windowFrom > argv.windowTo) {
|
|
203
|
+
output.error(`--window-from (${argv.windowFrom}) must be <= --window-to (${argv.windowTo})`);
|
|
204
|
+
process.exitCode = 1;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// Resolve author.
|
|
208
|
+
let authorLabel;
|
|
209
|
+
if (argv.author) {
|
|
210
|
+
authorLabel = argv.author;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const key = process.env.POP_PRIVATE_KEY;
|
|
214
|
+
if (!key) {
|
|
215
|
+
output.error('POP_PRIVATE_KEY not set — cannot derive default author. Pass --author explicitly.');
|
|
216
|
+
process.exitCode = 1;
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
authorLabel = new ethers_1.ethers.Wallet(key).address.toLowerCase();
|
|
220
|
+
}
|
|
221
|
+
// Read observations file if provided.
|
|
222
|
+
let observations = {};
|
|
223
|
+
if (argv.observationsFile) {
|
|
224
|
+
const p = (0, path_1.resolve)(argv.observationsFile);
|
|
225
|
+
if (!(0, fs_1.existsSync)(p)) {
|
|
226
|
+
output.error(`--observations-file not found: ${p}`);
|
|
227
|
+
process.exitCode = 1;
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const content = (0, fs_1.readFileSync)(p, 'utf8');
|
|
231
|
+
observations = parseObservationsFile(content);
|
|
232
|
+
}
|
|
233
|
+
// Read + parse changes file.
|
|
234
|
+
const changesPath = (0, path_1.resolve)(argv.changesFile);
|
|
235
|
+
if (!(0, fs_1.existsSync)(changesPath)) {
|
|
236
|
+
output.error(`--changes-file not found: ${changesPath}`);
|
|
237
|
+
process.exitCode = 1;
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const changesContent = (0, fs_1.readFileSync)(changesPath, 'utf8');
|
|
241
|
+
let proposedChanges;
|
|
242
|
+
try {
|
|
243
|
+
proposedChanges = parseChangesFile(changesContent);
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
output.error(err.message);
|
|
247
|
+
process.exitCode = 1;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (proposedChanges.length === 0) {
|
|
251
|
+
output.error('Changes file produced zero entries — retros must have at least one proposed change');
|
|
252
|
+
process.exitCode = 1;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const now = Math.floor(Date.now() / 1000);
|
|
256
|
+
const hb = argv.hb ?? argv.windowTo;
|
|
257
|
+
const retroId = argv.id ?? `retro-${hb}-${now}`;
|
|
258
|
+
const result = await (0, brain_ops_1.routedDispatch)({
|
|
259
|
+
type: 'startRetro',
|
|
260
|
+
docId: argv.doc,
|
|
261
|
+
retroId,
|
|
262
|
+
author: authorLabel,
|
|
263
|
+
hb,
|
|
264
|
+
window: { from: argv.windowFrom, to: argv.windowTo },
|
|
265
|
+
observations,
|
|
266
|
+
proposedChanges,
|
|
267
|
+
createdAt: now,
|
|
268
|
+
});
|
|
269
|
+
if (output.isJsonMode()) {
|
|
270
|
+
output.json({
|
|
271
|
+
status: 'ok',
|
|
272
|
+
docId: argv.doc,
|
|
273
|
+
retroId,
|
|
274
|
+
hb,
|
|
275
|
+
window: { from: argv.windowFrom, to: argv.windowTo },
|
|
276
|
+
author: authorLabel,
|
|
277
|
+
changeCount: proposedChanges.length,
|
|
278
|
+
changeIds: proposedChanges.map(c => c.id),
|
|
279
|
+
headCid: result.headCid,
|
|
280
|
+
envelopeAuthor: result.envelopeAuthor,
|
|
281
|
+
routedViaDaemon: result.routedViaDaemon,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
console.log('');
|
|
286
|
+
console.log(` Retro started in ${argv.doc}`);
|
|
287
|
+
console.log(` id: ${retroId}`);
|
|
288
|
+
console.log(` window: HB#${argv.windowFrom}..HB#${argv.windowTo}`);
|
|
289
|
+
console.log(` author: ${authorLabel}`);
|
|
290
|
+
console.log(` changes: ${proposedChanges.length} proposed`);
|
|
291
|
+
for (const c of proposedChanges) {
|
|
292
|
+
console.log(` - ${c.id}: ${c.summary}`);
|
|
293
|
+
}
|
|
294
|
+
console.log(` head: ${result.headCid}`);
|
|
295
|
+
console.log(` routed: ${result.routedViaDaemon ? 'via brain daemon' : 'in-process (no daemon)'}`);
|
|
296
|
+
console.log('');
|
|
297
|
+
console.log(` Next steps: other agents run "pop brain retro respond --to ${retroId}" ` +
|
|
298
|
+
`to discuss proposed changes. When changes are agreed, run ` +
|
|
299
|
+
`"pop brain retro file-tasks --retro ${retroId}" to convert them to on-chain tasks.`);
|
|
300
|
+
console.log('');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
output.error(err.message);
|
|
305
|
+
process.exitCode = 1;
|
|
306
|
+
}
|
|
307
|
+
finally {
|
|
308
|
+
await (0, brain_1.stopBrainNode)();
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pop brain search — keyword / tag / author / HB filters over brain lesson docs.
|
|
3
|
+
*
|
|
4
|
+
* Task #347 (Retro #1 fallback #6). The pop.brain.shared / pop.brain.lessons
|
|
5
|
+
* doc has grown past the "cold read is cheap" threshold. Agents reaching for
|
|
6
|
+
* "is there a lesson about X" were grepping heartbeat-log.md as a faster
|
|
7
|
+
* proxy, which defeated the purpose of the canonical lesson substrate.
|
|
8
|
+
* This command makes lesson search cheaper than log grep.
|
|
9
|
+
*
|
|
10
|
+
* Filters compose as AND:
|
|
11
|
+
* --query case-insensitive substring match over title + body
|
|
12
|
+
* --tag exact tag match (one tag per invocation; run twice to AND)
|
|
13
|
+
* --author exact author match (0x lowercase)
|
|
14
|
+
* --since HB number: only lessons with timestamp >= the HB's wall-clock.
|
|
15
|
+
* Heuristic — the HB number is not stored on the lesson; we
|
|
16
|
+
* approximate by comparing the lesson timestamp against a
|
|
17
|
+
* provided unix-seconds lower bound passed as --since-ts.
|
|
18
|
+
*
|
|
19
|
+
* Output is ranked by timestamp descending (most recent first) since that's
|
|
20
|
+
* the useful default for "what happened lately about X". JSON mode for
|
|
21
|
+
* programmatic consumption.
|
|
22
|
+
*/
|
|
23
|
+
import type { Argv, ArgumentsCamelCase } from 'yargs';
|
|
24
|
+
interface SearchArgs {
|
|
25
|
+
doc: string;
|
|
26
|
+
query?: string;
|
|
27
|
+
tag?: string;
|
|
28
|
+
author?: string;
|
|
29
|
+
sinceTs?: number;
|
|
30
|
+
limit?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare const searchHandler: {
|
|
33
|
+
builder: (yargs: Argv) => Argv<{
|
|
34
|
+
doc: string;
|
|
35
|
+
} & {
|
|
36
|
+
query: string | undefined;
|
|
37
|
+
} & {
|
|
38
|
+
tag: string | undefined;
|
|
39
|
+
} & {
|
|
40
|
+
author: string | undefined;
|
|
41
|
+
} & {
|
|
42
|
+
"since-ts": number | undefined;
|
|
43
|
+
} & {
|
|
44
|
+
limit: number;
|
|
45
|
+
}>;
|
|
46
|
+
handler: (argv: ArgumentsCamelCase<SearchArgs>) => Promise<void>;
|
|
47
|
+
};
|
|
48
|
+
export {};
|