@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,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 {};