@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,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* pop brain list — enumerate all known brain docs with their current head CIDs.
|
|
4
|
+
*
|
|
5
|
+
* Thin wrapper over listBrainDocs() which reads the manifest file directly
|
|
6
|
+
* (no Helia process required). Useful for:
|
|
7
|
+
*
|
|
8
|
+
* - Discovering what docs an agent has locally without knowing the ID
|
|
9
|
+
* - Sanity-checking that a subscribe session actually merged a remote head
|
|
10
|
+
* - Feeding `pop brain read --doc <id>` for any doc returned here
|
|
11
|
+
*
|
|
12
|
+
* Implementation intentionally avoids spinning up a Helia node — listing
|
|
13
|
+
* is a pure manifest read.
|
|
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.listHandler = void 0;
|
|
50
|
+
const brain_1 = require("../../lib/brain");
|
|
51
|
+
const output = __importStar(require("@poa-box/cli/lib/output"));
|
|
52
|
+
exports.listHandler = {
|
|
53
|
+
builder: (yargs) => yargs,
|
|
54
|
+
handler: async (_argv) => {
|
|
55
|
+
try {
|
|
56
|
+
const docs = (0, brain_1.listBrainDocs)();
|
|
57
|
+
if (output.isJsonMode()) {
|
|
58
|
+
output.json({ count: docs.length, docs });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.log('');
|
|
62
|
+
if (docs.length === 0) {
|
|
63
|
+
console.log(' No brain docs found in local manifest.');
|
|
64
|
+
console.log(' (Write one via applyBrainChange or sync via `pop brain subscribe`.)');
|
|
65
|
+
console.log('');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(` Brain docs (${docs.length}):`);
|
|
69
|
+
console.log(' ' + '─'.repeat(60));
|
|
70
|
+
for (const { docId, headCid } of docs) {
|
|
71
|
+
console.log(` ${docId}`);
|
|
72
|
+
console.log(` head: ${headCid}`);
|
|
73
|
+
}
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(' Inspect any doc: pop brain read --doc <docId>');
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
output.error(err.message);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pop brain migrate-projects — one-shot import of a hand-written
|
|
3
|
+
* projects.md file into a brain projects doc. Same shape as
|
|
4
|
+
* `pop brain migrate` (#296) but for pop.brain.projects instead of
|
|
5
|
+
* pop.brain.shared. Parses the "Active Projects" H2 section only.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* pop brain migrate-projects \
|
|
9
|
+
* --from agent/brain/Knowledge/projects.md \
|
|
10
|
+
* --doc pop.brain.projects.test \
|
|
11
|
+
* --dry-run
|
|
12
|
+
*
|
|
13
|
+
* Dry-run reports parse results without persisting. Without --dry-run,
|
|
14
|
+
* refuses to write if the target doc already has content unless --force.
|
|
15
|
+
*/
|
|
16
|
+
import type { Argv, ArgumentsCamelCase } from 'yargs';
|
|
17
|
+
interface MigrateProjectsArgs {
|
|
18
|
+
from: string;
|
|
19
|
+
doc: string;
|
|
20
|
+
force?: boolean;
|
|
21
|
+
dryRun?: boolean;
|
|
22
|
+
author?: string;
|
|
23
|
+
currentHb?: number;
|
|
24
|
+
noBanner?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare const migrateProjectsHandler: {
|
|
27
|
+
builder: (yargs: Argv) => Argv<{
|
|
28
|
+
from: string;
|
|
29
|
+
} & {
|
|
30
|
+
doc: string;
|
|
31
|
+
} & {
|
|
32
|
+
force: boolean;
|
|
33
|
+
} & {
|
|
34
|
+
"dry-run": boolean;
|
|
35
|
+
} & {
|
|
36
|
+
"current-hb": number;
|
|
37
|
+
} & {
|
|
38
|
+
author: string;
|
|
39
|
+
} & {
|
|
40
|
+
"no-banner": boolean;
|
|
41
|
+
}>;
|
|
42
|
+
handler: (argv: ArgumentsCamelCase<MigrateProjectsArgs>) => Promise<void>;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* pop brain migrate-projects — one-shot import of a hand-written
|
|
4
|
+
* projects.md file into a brain projects doc. Same shape as
|
|
5
|
+
* `pop brain migrate` (#296) but for pop.brain.projects instead of
|
|
6
|
+
* pop.brain.shared. Parses the "Active Projects" H2 section only.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* pop brain migrate-projects \
|
|
10
|
+
* --from agent/brain/Knowledge/projects.md \
|
|
11
|
+
* --doc pop.brain.projects.test \
|
|
12
|
+
* --dry-run
|
|
13
|
+
*
|
|
14
|
+
* Dry-run reports parse results without persisting. Without --dry-run,
|
|
15
|
+
* refuses to write if the target doc already has content unless --force.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.migrateProjectsHandler = void 0;
|
|
52
|
+
const fs_1 = require("fs");
|
|
53
|
+
const path_1 = require("path");
|
|
54
|
+
const brain_1 = require("../../lib/brain");
|
|
55
|
+
const brain_migrate_projects_1 = require("../../lib/brain-migrate-projects");
|
|
56
|
+
const output = __importStar(require("@poa-box/cli/lib/output"));
|
|
57
|
+
const DEPRECATED_BANNER = (docId, headCid) => `<!-- DEPRECATED: migrated to ${docId} at CID ${headCid} -->
|
|
58
|
+
<!-- Source of truth is now agent/brain/Knowledge/${docId}.generated.md -->
|
|
59
|
+
<!-- regenerated by \`pop brain snapshot --doc ${docId}\` at end of every heartbeat. -->
|
|
60
|
+
<!-- Edit via \`pop brain\` CLI; hand-edits here will NOT propagate. -->
|
|
61
|
+
|
|
62
|
+
`;
|
|
63
|
+
exports.migrateProjectsHandler = {
|
|
64
|
+
builder: (yargs) => yargs
|
|
65
|
+
.option('from', {
|
|
66
|
+
describe: 'Path to the hand-written projects.md to migrate',
|
|
67
|
+
type: 'string',
|
|
68
|
+
demandOption: true,
|
|
69
|
+
})
|
|
70
|
+
.option('doc', {
|
|
71
|
+
describe: 'Target brain document ID (typically pop.brain.projects)',
|
|
72
|
+
type: 'string',
|
|
73
|
+
demandOption: true,
|
|
74
|
+
})
|
|
75
|
+
.option('force', {
|
|
76
|
+
describe: 'Re-migrate even if the target doc already has live projects',
|
|
77
|
+
type: 'boolean',
|
|
78
|
+
default: false,
|
|
79
|
+
})
|
|
80
|
+
.option('dry-run', {
|
|
81
|
+
describe: 'Parse and print the structured output without persisting',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
default: false,
|
|
84
|
+
})
|
|
85
|
+
.option('current-hb', {
|
|
86
|
+
describe: 'Current heartbeat number for HB#→timestamp estimation (default 285)',
|
|
87
|
+
type: 'number',
|
|
88
|
+
default: 285,
|
|
89
|
+
})
|
|
90
|
+
.option('author', {
|
|
91
|
+
describe: 'Default author for projects without explicit attribution',
|
|
92
|
+
type: 'string',
|
|
93
|
+
default: 'migration',
|
|
94
|
+
})
|
|
95
|
+
.option('no-banner', {
|
|
96
|
+
describe: 'Do NOT write a DEPRECATED banner to the source file after migration',
|
|
97
|
+
type: 'boolean',
|
|
98
|
+
default: false,
|
|
99
|
+
}),
|
|
100
|
+
handler: async (argv) => {
|
|
101
|
+
const srcPath = (0, path_1.resolve)(argv.from);
|
|
102
|
+
const docId = argv.doc;
|
|
103
|
+
try {
|
|
104
|
+
if (!(0, fs_1.existsSync)(srcPath)) {
|
|
105
|
+
output.error(`Source file not found: ${srcPath}`);
|
|
106
|
+
process.exitCode = 1;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const raw = (0, fs_1.readFileSync)(srcPath, 'utf8');
|
|
110
|
+
const now = Math.floor(Date.now() / 1000);
|
|
111
|
+
const currentHB = argv.currentHb ?? 285;
|
|
112
|
+
const ctx = {
|
|
113
|
+
defaultAuthor: argv.author ?? 'migration',
|
|
114
|
+
defaultTimestamp: now,
|
|
115
|
+
timestampForHB: (hb) => now - (currentHB - hb) * 15 * 60,
|
|
116
|
+
};
|
|
117
|
+
const parsed = (0, brain_migrate_projects_1.parseProjectsMarkdown)(raw, ctx);
|
|
118
|
+
const projects = parsed.projects ?? [];
|
|
119
|
+
if (argv.dryRun) {
|
|
120
|
+
if (output.isJsonMode()) {
|
|
121
|
+
output.json({ status: 'dry-run', docId, parsed });
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log('');
|
|
125
|
+
console.log(` Dry-run migration: ${srcPath}`);
|
|
126
|
+
console.log(` Target doc: ${docId}`);
|
|
127
|
+
console.log(' ' + '─'.repeat(60));
|
|
128
|
+
console.log(` Projects parsed: ${projects.length}`);
|
|
129
|
+
console.log('');
|
|
130
|
+
const stageCounts = {};
|
|
131
|
+
for (const p of projects) {
|
|
132
|
+
stageCounts[p.stage] = (stageCounts[p.stage] ?? 0) + 1;
|
|
133
|
+
}
|
|
134
|
+
console.log(' Stage counts:');
|
|
135
|
+
for (const [stage, n] of Object.entries(stageCounts)) {
|
|
136
|
+
console.log(` ${stage}: ${n}`);
|
|
137
|
+
}
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(' First 5 projects:');
|
|
140
|
+
for (const p of projects.slice(0, 5)) {
|
|
141
|
+
console.log(` - ${p.id} ${p.name.slice(0, 60)} [${p.stage}]`);
|
|
142
|
+
}
|
|
143
|
+
console.log('');
|
|
144
|
+
console.log(' No changes persisted (--dry-run).');
|
|
145
|
+
console.log('');
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Refuse to overwrite an existing doc unless --force. Count only
|
|
150
|
+
// LIVE projects (not tombstoned) when deciding "has content".
|
|
151
|
+
const existing = await (0, brain_1.openBrainDoc)(docId);
|
|
152
|
+
const existingLiveCount = Array.isArray(existing.doc?.projects)
|
|
153
|
+
? existing.doc.projects.filter((p) => p?.removed !== true).length
|
|
154
|
+
: 0;
|
|
155
|
+
if (existingLiveCount > 0 && !argv.force) {
|
|
156
|
+
output.error(`Target doc "${docId}" already has ${existingLiveCount} live project(s) at head ${existing.headCid}. ` +
|
|
157
|
+
'Re-run with --force to re-migrate (will merge via Automerge).');
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const result = await (0, brain_1.applyBrainChange)(docId, (doc) => {
|
|
162
|
+
if (!Array.isArray(doc.projects))
|
|
163
|
+
doc.projects = [];
|
|
164
|
+
if (argv.force) {
|
|
165
|
+
// Force re-migration: clear existing and re-seed.
|
|
166
|
+
doc.projects.splice(0, doc.projects.length);
|
|
167
|
+
}
|
|
168
|
+
for (const p of projects)
|
|
169
|
+
doc.projects.push({ ...p });
|
|
170
|
+
});
|
|
171
|
+
if (!argv.noBanner) {
|
|
172
|
+
const banner = DEPRECATED_BANNER(docId, result.headCid);
|
|
173
|
+
if (!raw.includes('DEPRECATED: migrated to')) {
|
|
174
|
+
(0, fs_1.writeFileSync)(srcPath, banner + raw);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (output.isJsonMode()) {
|
|
178
|
+
output.json({
|
|
179
|
+
status: 'ok',
|
|
180
|
+
docId,
|
|
181
|
+
headCid: result.headCid,
|
|
182
|
+
projectsMigrated: projects.length,
|
|
183
|
+
sourceFile: srcPath,
|
|
184
|
+
bannerWritten: !argv.noBanner,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
console.log('');
|
|
189
|
+
console.log(` Migration complete: ${srcPath} → ${docId}`);
|
|
190
|
+
console.log(` New head CID: ${result.headCid}`);
|
|
191
|
+
console.log(` Projects: ${projects.length}`);
|
|
192
|
+
if (!argv.noBanner) {
|
|
193
|
+
console.log(` Banner written to source file.`);
|
|
194
|
+
}
|
|
195
|
+
console.log('');
|
|
196
|
+
console.log(` Run \`pop brain read --doc ${docId}\` to inspect.`);
|
|
197
|
+
console.log(` Run \`pop brain snapshot --doc ${docId}\` to produce the .generated.md.`);
|
|
198
|
+
console.log('');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
output.error(err.message);
|
|
203
|
+
process.exitCode = 1;
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
await (0, brain_1.stopBrainNode)();
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pop brain migrate — one-shot import of a hand-written brain knowledge
|
|
3
|
+
* file into a CRDT Automerge doc. Step 8 of the brain plan.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* pop brain migrate --from agent/brain/Knowledge/shared.md \
|
|
7
|
+
* --doc pop.brain.shared
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* 1. Read the markdown file from disk.
|
|
11
|
+
* 2. parseSharedMarkdown → SharedBrainDoc (rules + lessons).
|
|
12
|
+
* 3. --dry-run: print the parsed structure and exit.
|
|
13
|
+
* 4. Otherwise: check that the target doc is empty (or --force),
|
|
14
|
+
* then apply the parsed content via applyBrainChange. This
|
|
15
|
+
* auto-signs + auto-publishes via the step 5 gossipsub layer
|
|
16
|
+
* so any live subscriber picks up the migration immediately.
|
|
17
|
+
* 5. Write a DEPRECATED banner to the top of the source file
|
|
18
|
+
* pointing agents at <docId>.generated.md as the new source
|
|
19
|
+
* of truth. Original content is preserved below the banner
|
|
20
|
+
* for historical reference — the banner is opt-in.
|
|
21
|
+
*
|
|
22
|
+
* Idempotence: running the command twice on a doc that already has
|
|
23
|
+
* content errors out unless --force is supplied. This protects
|
|
24
|
+
* against accidental clobbering during a fumbled migration.
|
|
25
|
+
*/
|
|
26
|
+
import type { Argv, ArgumentsCamelCase } from 'yargs';
|
|
27
|
+
interface MigrateArgs {
|
|
28
|
+
from: string;
|
|
29
|
+
doc: string;
|
|
30
|
+
force?: boolean;
|
|
31
|
+
merge?: boolean;
|
|
32
|
+
dryRun?: boolean;
|
|
33
|
+
currentHb?: number;
|
|
34
|
+
author?: string;
|
|
35
|
+
noBanner?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pure helper: compute which parsed entries should be appended to an
|
|
39
|
+
* existing list vs skipped because an entry with the same `id` already
|
|
40
|
+
* exists. Extracted so the --merge dedup logic is unit-testable
|
|
41
|
+
* independent of the brain daemon / Automerge doc layer.
|
|
42
|
+
*
|
|
43
|
+
* Entries without an `id` are ALWAYS added (we can't dedup what has no
|
|
44
|
+
* key). Callers should ensure parsed entries have ids if they want
|
|
45
|
+
* dedup semantics — parseSharedMarkdown always assigns an id via
|
|
46
|
+
* slugify fallback, so in practice every parsed lesson has an id.
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeMergeDelta<T extends {
|
|
49
|
+
id?: string;
|
|
50
|
+
}>(existing: readonly T[], parsed: readonly T[]): {
|
|
51
|
+
toAdd: T[];
|
|
52
|
+
skippedCount: number;
|
|
53
|
+
};
|
|
54
|
+
export declare const migrateHandler: {
|
|
55
|
+
builder: (yargs: Argv) => Argv<{
|
|
56
|
+
from: string;
|
|
57
|
+
} & {
|
|
58
|
+
doc: string;
|
|
59
|
+
} & {
|
|
60
|
+
force: boolean;
|
|
61
|
+
} & {
|
|
62
|
+
merge: boolean;
|
|
63
|
+
} & {
|
|
64
|
+
"dry-run": boolean;
|
|
65
|
+
} & {
|
|
66
|
+
"current-hb": number;
|
|
67
|
+
} & {
|
|
68
|
+
author: string;
|
|
69
|
+
} & {
|
|
70
|
+
"no-banner": boolean;
|
|
71
|
+
}>;
|
|
72
|
+
handler: (argv: ArgumentsCamelCase<MigrateArgs>) => Promise<void>;
|
|
73
|
+
};
|
|
74
|
+
export {};
|