@agfpd/iapeer-memory 0.2.6 → 0.2.8
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/package.json +2 -2
- package/src/cli.ts +9 -7
- package/src/commands/dream-collect.ts +645 -0
- package/src/commands/init.ts +22 -15
- package/src/commands/uninstall.ts +7 -12
- package/src/commands/update.ts +26 -18
- package/src/commands/verify.ts +20 -3
- package/src/fleet.ts +1 -1
- package/src/paths.ts +4 -0
- package/src/provision.ts +14 -0
- package/src/slot.ts +4 -52
- package/src/sync-versions.ts +5 -9
- package/src/templates/roles-en.ts +82 -56
- package/src/templates/roles-ru.ts +80 -51
- package/src/templates/skills.ts +2 -1
- package/src/watcher.ts +56 -14
- package/src/commands/dream-paths.ts +0 -153
package/src/commands/init.ts
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Step order: deps → vault → config → binary → templates → role peers +
|
|
16
16
|
* doctrines + roles manifest → fleet map → watcher registration → direct
|
|
17
|
-
* session surfaces sweep (ADR-009 v1.2) → legacy v1.1
|
|
18
|
-
*
|
|
17
|
+
* session surfaces sweep (ADR-009 v1.2) → legacy v1.1 manual hint (the
|
|
18
|
+
* plugin channel is removed, ADR-017) → slot declaration (v1.2 provision
|
|
19
19
|
* command) → native-memory sweep (core verb, soft-skip on old cores) →
|
|
20
20
|
* host-wide guide fragment. Ecosystem steps are skippable (--skip-ecosystem)
|
|
21
21
|
* for sandboxed runs; the binary compile is skippable (--skip-binary) for
|
|
@@ -36,7 +36,7 @@ import { IAPEER_BIN, type Egress } from "../egress.js";
|
|
|
36
36
|
import { memoryPaths } from "../paths.js";
|
|
37
37
|
import { provisionVault, writeDefaultConfig } from "../provision.js";
|
|
38
38
|
import { writeRolesManifest, type RoleEntry } from "../roles.js";
|
|
39
|
-
import {
|
|
39
|
+
import { readSlot, writeSlot, SLOT_PROVIDER } from "../slot.js";
|
|
40
40
|
import { readFleetMap, writeFleetMap } from "../fleet.js";
|
|
41
41
|
import { withProvisionLock } from "../surfaces/lock.js";
|
|
42
42
|
import { sweepProvision } from "../surfaces/sweep.js";
|
|
@@ -51,11 +51,13 @@ import {
|
|
|
51
51
|
} from "../templates/index.js";
|
|
52
52
|
import { packageVersion } from "../version.js";
|
|
53
53
|
import {
|
|
54
|
+
DREAM_TARGET,
|
|
54
55
|
dreamTimerMessage,
|
|
55
56
|
patchWakePolicyEphemeral,
|
|
56
57
|
registerTimer,
|
|
57
58
|
registerWatcher,
|
|
58
59
|
sweepTimerMessage,
|
|
60
|
+
writeDreamGateScript,
|
|
59
61
|
writeLauncherScript,
|
|
60
62
|
writeStaleCheckScript,
|
|
61
63
|
} from "../watcher.js";
|
|
@@ -402,8 +404,15 @@ export async function cmdInit(argv: string[], egress: Egress): Promise<number> {
|
|
|
402
404
|
message: sweepTimerMessage({ checkScriptPath: paths.checkScriptPath }),
|
|
403
405
|
iapeerBin: flags.iapeerBin,
|
|
404
406
|
});
|
|
407
|
+
writeDreamGateScript({
|
|
408
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
409
|
+
binaryPath: paths.binaryPath,
|
|
410
|
+
});
|
|
405
411
|
const dream = registerTimer(egress, {
|
|
406
|
-
message: dreamTimerMessage(
|
|
412
|
+
message: dreamTimerMessage({
|
|
413
|
+
cron: process.env.IAPEER_MEMORY_DREAM_CRON,
|
|
414
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
415
|
+
}),
|
|
407
416
|
iapeerBin: flags.iapeerBin,
|
|
408
417
|
});
|
|
409
418
|
const timersSandboxed = sweep.suppressed && dream.suppressed;
|
|
@@ -412,7 +421,7 @@ export async function cmdInit(argv: string[], egress: Egress): Promise<number> {
|
|
|
412
421
|
timersSandboxed
|
|
413
422
|
? "skipped (test sandbox — sends suppressed)"
|
|
414
423
|
: sweep.ok && dream.ok
|
|
415
|
-
? `sweep (@every 1h, check ${paths.checkScriptPath}) + dream-tick (weekly
|
|
424
|
+
? `sweep (@every 1h, check ${paths.checkScriptPath}) + dream-tick (weekly, gated, → ${DREAM_TARGET})`
|
|
416
425
|
: `sweep: ${sweep.ok ? "sent" : sweep.detail}; dream: ${dream.ok ? "sent" : dream.detail}`,
|
|
417
426
|
Boolean(timersSandboxed) || (sweep.ok && dream.ok),
|
|
418
427
|
);
|
|
@@ -470,27 +479,25 @@ export async function cmdInit(argv: string[], egress: Egress): Promise<number> {
|
|
|
470
479
|
}
|
|
471
480
|
}
|
|
472
481
|
|
|
473
|
-
// 8c. v1.1 → v1.2 migration:
|
|
474
|
-
//
|
|
475
|
-
// the direct surfaces
|
|
482
|
+
// 8c. v1.1 → v1.2 migration: the plugin channel is REMOVED (ADR-017) —
|
|
483
|
+
// the package no longer shells the core verb; a v1.1 host gets the
|
|
484
|
+
// manual recipe and the slot migrates ONLY after the direct surfaces
|
|
485
|
+
// landed cleanly (never strand a host with neither channel).
|
|
476
486
|
let migrationBlocked = false;
|
|
477
487
|
if (!flags.skipEcosystem && existingSlot?.plugin) {
|
|
478
488
|
if (!surfacesOk) {
|
|
479
489
|
migrationBlocked = true;
|
|
480
490
|
step(
|
|
481
491
|
"plugin-off",
|
|
482
|
-
"POSTPONED: direct surfaces did not land cleanly —
|
|
492
|
+
"POSTPONED: direct surfaces did not land cleanly — v1.1 slot kept (re-run init after fixing)",
|
|
483
493
|
false,
|
|
484
494
|
);
|
|
485
495
|
} else {
|
|
486
|
-
const off = applyMemoryPlugin(egress, { mode: "off", iapeerBin: flags.iapeerBin });
|
|
487
496
|
step(
|
|
488
497
|
"plugin-off",
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
? "legacy v1.1 session plugin swept off the fleet (memory-plugin off --all)"
|
|
493
|
-
: `legacy plugin off failed (${off.detail.slice(0, 120)}) — manual: iapeer memory-plugin off --all (or per peer: claude plugin uninstall iapeer-memory@agfpd --scope project)`,
|
|
498
|
+
"legacy v1.1 session plugin is NOT auto-removed (channel removed, ADR-017) — manual, per claude peer: " +
|
|
499
|
+
"`claude plugin uninstall iapeer-memory@agfpd --scope project` from its cwd; codex (host-global): " +
|
|
500
|
+
"`codex plugin remove iapeer-memory@agfpd`. Until then it stamps in parallel (idempotent).",
|
|
494
501
|
);
|
|
495
502
|
}
|
|
496
503
|
}
|
|
@@ -21,7 +21,7 @@ import type { Egress } from "../egress.js";
|
|
|
21
21
|
import { memoryPaths } from "../paths.js";
|
|
22
22
|
import { removeBinary } from "../binary.js";
|
|
23
23
|
import { readFleetMap } from "../fleet.js";
|
|
24
|
-
import {
|
|
24
|
+
import { readSlot, removeSlot, SLOT_PROVIDER } from "../slot.js";
|
|
25
25
|
import { withProvisionLock } from "../surfaces/lock.js";
|
|
26
26
|
import { sweepUnprovision } from "../surfaces/sweep.js";
|
|
27
27
|
import { guardedUnlinkSync } from "@agfpd/iapeer-memory-core";
|
|
@@ -130,19 +130,14 @@ export function cmdUninstall(argv: string[], egress: Egress): number {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
// Legacy v1.1 path: the slot still carries a plugin block
|
|
134
|
-
//
|
|
135
|
-
//
|
|
133
|
+
// Legacy v1.1 path: the slot still carries a plugin block. The plugin
|
|
134
|
+
// channel is REMOVED (ADR-017) — no core verb is shelled; the manual
|
|
135
|
+
// recipe works without the slot.
|
|
136
136
|
if (declared.plugin) {
|
|
137
|
-
const off = applyMemoryPlugin(egress, { mode: "off", iapeerBin });
|
|
138
137
|
console.log(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
: off.ok
|
|
143
|
-
? "legacy session plugin removed across the fleet (memory-plugin off --all; codex side is host-global)"
|
|
144
|
-
: `off not applied (${off.detail.slice(0, 160)}) — manual fallback (works without the slot): per claude peer \`claude plugin uninstall iapeer-memory@agfpd --scope project\` from its cwd; codex (host-global): \`codex plugin remove iapeer-memory@agfpd\``
|
|
145
|
-
}`,
|
|
138
|
+
"plugin : legacy v1.1 session plugin is NOT auto-removed (channel removed, ADR-017) — manual: " +
|
|
139
|
+
"per claude peer `claude plugin uninstall iapeer-memory@agfpd --scope project` from its cwd; " +
|
|
140
|
+
"codex (host-global): `codex plugin remove iapeer-memory@agfpd`",
|
|
146
141
|
);
|
|
147
142
|
}
|
|
148
143
|
}
|
package/src/commands/update.ts
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* 5. surfaces — direct per-peer session surfaces sweep over the map
|
|
17
17
|
* (ADR-009 v1.2: the «всё на местах у подключённых пиров»
|
|
18
18
|
* duty — both runtimes, idempotent, repairs drift);
|
|
19
|
-
* 6. plugin-off — v1.1→v1.2 migration:
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* 6. plugin-off — v1.1→v1.2 migration: a slot still carrying a plugin
|
|
20
|
+
* block gets the MANUAL removal recipe (the plugin
|
|
21
|
+
* channel is removed, ADR-017) — the slot migrates only
|
|
22
|
+
* after surfaces landed cleanly;
|
|
23
23
|
* 7. slot — re-declare in the v1.2 form (provision command blocks,
|
|
24
24
|
* new version — contract obligation);
|
|
25
25
|
* 8. launcher + triggers + guide — regenerate;
|
|
@@ -44,17 +44,19 @@ import type { Egress } from "../egress.js";
|
|
|
44
44
|
import { readFleetMap, writeFleetMap } from "../fleet.js";
|
|
45
45
|
import { memoryPaths } from "../paths.js";
|
|
46
46
|
import { readRolesManifest } from "../roles.js";
|
|
47
|
-
import {
|
|
47
|
+
import { readSlot, writeSlot, SLOT_PROVIDER } from "../slot.js";
|
|
48
48
|
import { withProvisionLock } from "../surfaces/lock.js";
|
|
49
49
|
import { sweepProvision } from "../surfaces/sweep.js";
|
|
50
50
|
import { mcpPort } from "./provision-peer.js";
|
|
51
51
|
import { guideText, materialiseTemplates } from "../templates/index.js";
|
|
52
52
|
import { packageVersion } from "../version.js";
|
|
53
53
|
import {
|
|
54
|
+
DREAM_TARGET,
|
|
54
55
|
dreamTimerMessage,
|
|
55
56
|
registerTimer,
|
|
56
57
|
registerWatcher,
|
|
57
58
|
sweepTimerMessage,
|
|
59
|
+
writeDreamGateScript,
|
|
58
60
|
writeLauncherScript,
|
|
59
61
|
writeStaleCheckScript,
|
|
60
62
|
} from "../watcher.js";
|
|
@@ -187,28 +189,25 @@ export function cmdUpdate(argv: string[], egress: Egress): number {
|
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
// 6. v1.1 → v1.2 migration (one-shot per host): the
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
192
|
+
// 6. v1.1 → v1.2 migration (one-shot per host): the plugin channel is
|
|
193
|
+
// REMOVED (ADR-017) — no core verb is shelled; a v1.1 host gets the
|
|
194
|
+
// manual recipe and the slot migrates ONLY after the direct surfaces
|
|
195
|
+
// landed cleanly (never strand a host with neither channel).
|
|
194
196
|
let migrationBlocked = false;
|
|
195
197
|
if (!slotForeign && existingSlot?.plugin) {
|
|
196
198
|
if (!surfacesOk) {
|
|
197
199
|
migrationBlocked = true;
|
|
198
200
|
step(
|
|
199
201
|
"plugin-off",
|
|
200
|
-
"POSTPONED: direct surfaces did not land cleanly —
|
|
202
|
+
"POSTPONED: direct surfaces did not land cleanly — v1.1 slot kept (fix and re-run update)",
|
|
201
203
|
false,
|
|
202
204
|
);
|
|
203
205
|
} else {
|
|
204
|
-
const off = applyMemoryPlugin(egress, { mode: "off" });
|
|
205
206
|
step(
|
|
206
207
|
"plugin-off",
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
? "legacy v1.1 session plugin swept off the fleet (memory-plugin off --all)"
|
|
211
|
-
: `legacy plugin off failed (${off.detail.slice(0, 120)}) — manual: iapeer memory-plugin off --all`,
|
|
208
|
+
"legacy v1.1 session plugin is NOT auto-removed (channel removed, ADR-017) — manual, per claude peer: " +
|
|
209
|
+
"`claude plugin uninstall iapeer-memory@agfpd --scope project` from its cwd; codex (host-global): " +
|
|
210
|
+
"`codex plugin remove iapeer-memory@agfpd`. Until then it stamps in parallel (idempotent).",
|
|
212
211
|
);
|
|
213
212
|
}
|
|
214
213
|
}
|
|
@@ -248,18 +247,27 @@ export function cmdUpdate(argv: string[], egress: Egress): number {
|
|
|
248
247
|
} catch {
|
|
249
248
|
// unprovisioned env — registrations below still re-target
|
|
250
249
|
}
|
|
250
|
+
writeDreamGateScript({
|
|
251
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
252
|
+
binaryPath: paths.binaryPath,
|
|
253
|
+
});
|
|
251
254
|
const w = registerWatcher(egress, { launcherPath: paths.launcherPath });
|
|
252
255
|
const s = registerTimer(egress, {
|
|
253
256
|
message: sweepTimerMessage({ checkScriptPath: paths.checkScriptPath }),
|
|
254
257
|
});
|
|
255
|
-
const d = registerTimer(egress, {
|
|
258
|
+
const d = registerTimer(egress, {
|
|
259
|
+
message: dreamTimerMessage({
|
|
260
|
+
cron: process.env.IAPEER_MEMORY_DREAM_CRON,
|
|
261
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
262
|
+
}),
|
|
263
|
+
});
|
|
256
264
|
const sandboxed = w.suppressed && s.suppressed && d.suppressed;
|
|
257
265
|
step(
|
|
258
266
|
"triggers",
|
|
259
267
|
sandboxed
|
|
260
268
|
? "skipped (test sandbox — sends suppressed)"
|
|
261
269
|
: w.ok && s.ok && d.ok
|
|
262
|
-
? `re-sent: event→scriber, sweep
|
|
270
|
+
? `re-sent: event→scriber, sweep→index, dream→${DREAM_TARGET} (gated; same id = replace); confirm: verify`
|
|
263
271
|
: `event: ${w.ok ? "sent" : w.detail}; sweep: ${s.ok ? "sent" : s.detail}; dream: ${d.ok ? "sent" : d.detail}`,
|
|
264
272
|
Boolean(sandboxed) || (w.ok && s.ok && d.ok),
|
|
265
273
|
);
|
package/src/commands/verify.ts
CHANGED
|
@@ -35,6 +35,7 @@ import { checkFleetSurfaces, sweepProvision } from "../surfaces/sweep.js";
|
|
|
35
35
|
import { mcpPort } from "./provision-peer.js";
|
|
36
36
|
import { packageVersion } from "../version.js";
|
|
37
37
|
import {
|
|
38
|
+
DREAM_TARGET,
|
|
38
39
|
dreamTimerMessage,
|
|
39
40
|
DEFAULT_EVENT_TARGET,
|
|
40
41
|
DREAM_TRIGGER_ID,
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
registerWatcher,
|
|
44
45
|
sweepTimerMessage,
|
|
45
46
|
SWEEP_TRIGGER_ID,
|
|
47
|
+
writeDreamGateScript,
|
|
46
48
|
writeLauncherScript,
|
|
47
49
|
writeStaleCheckScript,
|
|
48
50
|
WATCHER_TRIGGER_ID,
|
|
@@ -385,9 +387,24 @@ export function runVerify(egress: Egress, opts: VerifyOptions = {}): CheckResult
|
|
|
385
387
|
id: DREAM_TRIGGER_ID,
|
|
386
388
|
role: "time",
|
|
387
389
|
expect: (t) =>
|
|
388
|
-
t.target !==
|
|
389
|
-
|
|
390
|
-
|
|
390
|
+
t.target !== DREAM_TARGET
|
|
391
|
+
? `target is ${t.target ?? "?"}, expected ${DREAM_TARGET}`
|
|
392
|
+
: (t as { check?: string }).check !== paths.dreamGateScriptPath
|
|
393
|
+
? `check is ${(t as { check?: string }).check ?? "?"}, expected ${paths.dreamGateScriptPath}`
|
|
394
|
+
: null,
|
|
395
|
+
repairSend: () => {
|
|
396
|
+
writeDreamGateScript({
|
|
397
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
398
|
+
binaryPath: paths.binaryPath,
|
|
399
|
+
});
|
|
400
|
+
return registerTimer(egress, {
|
|
401
|
+
message: dreamTimerMessage({
|
|
402
|
+
cron: process.env.IAPEER_MEMORY_DREAM_CRON,
|
|
403
|
+
dreamGateScriptPath: paths.dreamGateScriptPath,
|
|
404
|
+
}),
|
|
405
|
+
iapeerBin: opts.iapeerBin,
|
|
406
|
+
});
|
|
407
|
+
},
|
|
391
408
|
},
|
|
392
409
|
];
|
|
393
410
|
for (const c of checks) {
|
package/src/fleet.ts
CHANGED
|
@@ -80,7 +80,7 @@ export function readFleetMap(fleetMapPath: string): FleetPeer[] | null {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/** Live-registry query — the ONE place `iapeer list --json` is parsed.
|
|
83
|
-
* Shared by writeFleetMap (the persisted map) and dream-
|
|
83
|
+
* Shared by writeFleetMap (the persisted map) and dream-collect (the
|
|
84
84
|
* tick-time resolution; freshness fact: birth does NOT touch fleet.json
|
|
85
85
|
* and the SessionStart kick is heartbeat-gated, so the LIVE registry is
|
|
86
86
|
* the only source that sees a newborn before the next update). */
|
package/src/paths.ts
CHANGED
|
@@ -56,6 +56,9 @@ export type MemoryPaths = {
|
|
|
56
56
|
launcherPath: string;
|
|
57
57
|
/** Sweep check-script — gates the fail-open inbox sweep (ADR-015). */
|
|
58
58
|
checkScriptPath: string;
|
|
59
|
+
/** Dream-tick gate check-script — the notifier `check` for the weekly timer
|
|
60
|
+
* (shells the registry-free `dream-collect --gate`; a dead week wakes no one). */
|
|
61
|
+
dreamGateScriptPath: string;
|
|
59
62
|
/** Fleet map (personality → cwd) — written by init/update/verify --repair
|
|
60
63
|
* from `iapeer list --json`, consumed by memoryd's fragment renderer
|
|
61
64
|
* (docs/05; дыра 10.06: без карты пиры не получали paths-блок и индекс). */
|
|
@@ -99,6 +102,7 @@ export function memoryPaths(
|
|
|
99
102
|
hooksDir: path.join(path.dirname(configFile), "hooks"),
|
|
100
103
|
launcherPath: path.join(path.dirname(configFile), "memoryd-launcher.sh"),
|
|
101
104
|
checkScriptPath: path.join(path.dirname(configFile), "inbox-stale-check.sh"),
|
|
105
|
+
dreamGateScriptPath: path.join(path.dirname(configFile), "dream-tick-gate.sh"),
|
|
102
106
|
fleetMapPath: path.join(stateDir, "fleet.json"),
|
|
103
107
|
};
|
|
104
108
|
}
|
package/src/provision.ts
CHANGED
|
@@ -176,6 +176,20 @@ export function defaultConfigContent(opts: ConfigContentOptions): string {
|
|
|
176
176
|
"# Curator personalities exempt from needs_review stamping (ADR-006).",
|
|
177
177
|
"# IAPEER_MEMORY_CURATOR_SET=index,scriber,dreamweaver",
|
|
178
178
|
"",
|
|
179
|
+
"# Weekly dream-tick (deterministic pre-filter → DreamWeaver). Schedule is",
|
|
180
|
+
"# 5-field cron; the window is days BY TIME (not since-last-tick).",
|
|
181
|
+
"# IAPEER_MEMORY_DREAM_CRON=0 4 * * 1",
|
|
182
|
+
"# IAPEER_MEMORY_DREAM_WINDOW_DAYS=7",
|
|
183
|
+
"# description longer than this many chars → a reformulation candidate.",
|
|
184
|
+
"# IAPEER_MEMORY_DREAM_DESC_MAXLEN=250",
|
|
185
|
+
"# >threshold new notes in a folder → its own subagent; smaller folders are",
|
|
186
|
+
"# grouped up to the cap (sum of per-folder weights).",
|
|
187
|
+
"# IAPEER_MEMORY_DREAM_BATCH_THRESHOLD=20",
|
|
188
|
+
"# IAPEER_MEMORY_DREAM_GROUP_CAP=20",
|
|
189
|
+
"# Per-folder cap on transcripts handed to phase D (most recent N by mtime;",
|
|
190
|
+
"# bounds an ephemeral worker's hundreds of sessions). 0 = uncapped.",
|
|
191
|
+
"# IAPEER_MEMORY_DREAM_TRANSCRIPT_CAP=20",
|
|
192
|
+
"",
|
|
179
193
|
].join("\n");
|
|
180
194
|
}
|
|
181
195
|
|
package/src/slot.ts
CHANGED
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
|
|
32
32
|
import fs from "node:fs";
|
|
33
33
|
import path from "node:path";
|
|
34
|
-
import { IAPEER_BIN, type Egress } from "./egress.js";
|
|
35
34
|
import {
|
|
36
35
|
guardedWriteFileSync,
|
|
37
36
|
guardedUnlinkSync,
|
|
@@ -173,54 +172,7 @@ export function removeSlot(slotPath: string): SlotRemoveResult {
|
|
|
173
172
|
return "removed";
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
* SKIP, not a failure (same contract as watcher.ts iapSend). */
|
|
181
|
-
suppressed?: boolean;
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Fleet-wide install/remove of the slot-declared session plugin via the core
|
|
186
|
-
* verb `iapeer memory-plugin <on|off> --all` (iapeer ≥0.2.25; marketplace
|
|
187
|
-
* ensure + stale-cache retry live INSIDE the verb). The verb derives the
|
|
188
|
-
* plugin identity from the slot declaration — so `on` runs AFTER writeSlot
|
|
189
|
-
* and `off` runs BEFORE removeSlot (agreed order, auto-removal: a dead
|
|
190
|
-
* provider's plugin must not keep injecting).
|
|
191
|
-
*
|
|
192
|
-
* The hard fuse of incident 10.06 (`on --all` mutates the HOST fleet — no
|
|
193
|
-
* sandbox env contains it) lives in the egress constructor now
|
|
194
|
-
* (deny-by-default §4): a refusing handle blocks the spawn here.
|
|
195
|
-
*/
|
|
196
|
-
export function applyMemoryPlugin(
|
|
197
|
-
egress: Egress,
|
|
198
|
-
opts: {
|
|
199
|
-
mode: "on" | "off";
|
|
200
|
-
iapeerBin?: string;
|
|
201
|
-
},
|
|
202
|
-
): MemoryPluginApplyResult {
|
|
203
|
-
const bin = opts.iapeerBin ?? IAPEER_BIN;
|
|
204
|
-
const proc = egress.spawnSync([bin, "memory-plugin", opts.mode, "--all"], {
|
|
205
|
-
explicitBin: opts.iapeerBin !== undefined,
|
|
206
|
-
});
|
|
207
|
-
if (proc.refused) {
|
|
208
|
-
return {
|
|
209
|
-
ok: false,
|
|
210
|
-
suppressed: true,
|
|
211
|
-
detail: "memory-plugin call suppressed (test sandbox)",
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
if (proc.spawnError) {
|
|
215
|
-
return { ok: false, detail: `${bin} unavailable: ${proc.spawnError}` };
|
|
216
|
-
}
|
|
217
|
-
if (proc.exitCode !== 0) {
|
|
218
|
-
return {
|
|
219
|
-
ok: false,
|
|
220
|
-
detail:
|
|
221
|
-
(proc.stderr.trim() || proc.stdout.trim() || "").slice(0, 200) ||
|
|
222
|
-
`iapeer memory-plugin exited ${proc.exitCode}`,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
return { ok: true, detail: proc.stdout.trim() };
|
|
226
|
-
}
|
|
175
|
+
// applyMemoryPlugin (the core verb `iapeer memory-plugin <on|off> --all`)
|
|
176
|
+
// was REMOVED with the plugin channel (ADR-017): v1.1 hosts get a manual
|
|
177
|
+
// recipe in init/update/uninstall instead of an auto-sweep. The `plugin`
|
|
178
|
+
// field on the slot type stays — it is the v1.1 READ marker.
|
package/src/sync-versions.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Manifest version sync (docs/10 §Версионная синхронизация): propagate the
|
|
3
3
|
* facade `package/package.json` version into every other manifest of the
|
|
4
|
-
* monorepo — `core/package.json`
|
|
5
|
-
*
|
|
4
|
+
* monorepo — `core/package.json` (the adapter plugin manifests left with
|
|
5
|
+
* the plugin channel, ADR-017). Wired into the npm `version` lifecycle,
|
|
6
|
+
* runnable standalone:
|
|
6
7
|
*
|
|
7
8
|
* bun src/sync-versions.ts
|
|
8
9
|
*
|
|
9
|
-
* Missing manifests are reported and skipped
|
|
10
|
-
* the script must not fail before they exist). The reference
|
|
10
|
+
* Missing manifests are reported and skipped. The reference
|
|
11
11
|
* sync-plugin-version pattern, generalised to N manifests.
|
|
12
12
|
*/
|
|
13
13
|
|
|
@@ -18,11 +18,7 @@ import { guardedWriteFileSync } from "@agfpd/iapeer-memory-core";
|
|
|
18
18
|
export type SyncOutcome = { file: string; action: "updated" | "identical" | "missing" };
|
|
19
19
|
|
|
20
20
|
/** Relative (to the monorepo root) manifests that must carry one version. */
|
|
21
|
-
export const SYNC_TARGETS = [
|
|
22
|
-
"core/package.json",
|
|
23
|
-
"adapters/claude/.claude-plugin/plugin.json",
|
|
24
|
-
"adapters/codex/.codex-plugin/plugin.json",
|
|
25
|
-
] as const;
|
|
21
|
+
export const SYNC_TARGETS = ["core/package.json"] as const;
|
|
26
22
|
|
|
27
23
|
export function syncVersions(opts: {
|
|
28
24
|
rootDir: string;
|
|
@@ -51,17 +51,12 @@ different world.
|
|
|
51
51
|
scriber thread stalled: place the stale drafts UNVETTED by the usual
|
|
52
52
|
rules; \`needs_review: true\` already travels with each file. The
|
|
53
53
|
Scriber re-vets them with the next PERMANENT_BATCH once alive.
|
|
54
|
-
- **
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
transcripts}\` — copy \`transcripts\` from the verb's output AS IS
|
|
61
|
-
(globs + the codex cwdFilter; path forms are the code's zone, not
|
|
62
|
-
yours). A verb error = report to the owner, never guess the fleet. On
|
|
63
|
-
the consolidation report: archive what it deprecated, act on its
|
|
64
|
-
\`attention\` blocks yourself.
|
|
54
|
+
- **DreamWeaver consolidation report** (weekly) — DreamWeaver now
|
|
55
|
+
orchestrates the tick (a deterministic pre-filter finds the work, it
|
|
56
|
+
fans out subagents); you are OFF the entry and only FINALISE. On its
|
|
57
|
+
report: archive each note it deprecated (move to the archive subfolder),
|
|
58
|
+
build the links section for each new merged note via vault_search, and
|
|
59
|
+
act on its \`attention\` items yourself.
|
|
65
60
|
- **Direct IAP** from agents or the human — structure questions; never
|
|
66
61
|
run searches for others (they have their own vault tools).
|
|
67
62
|
|
|
@@ -114,8 +109,8 @@ it under the usual three conditions.
|
|
|
114
109
|
Never write note content (authors own it); never answer other agents'
|
|
115
110
|
search requests; never dispatch the Scriber (events reach it directly —
|
|
116
111
|
it reports to you); never detect events yourself (memoryd detects, the
|
|
117
|
-
notifier delivers); never
|
|
118
|
-
|
|
112
|
+
notifier delivers); never orchestrate the dream-tick (DreamWeaver owns it
|
|
113
|
+
end to end now — you only finalise on its report).
|
|
119
114
|
`;
|
|
120
115
|
|
|
121
116
|
export const SCRIBER_DOCTRINE_EN = `---
|
|
@@ -233,47 +228,78 @@ locale: en
|
|
|
233
228
|
---
|
|
234
229
|
# DreamWeaver — sleep-cycle memory consolidation
|
|
235
230
|
|
|
236
|
-
You are DreamWeaver: an ephemeral worker peer
|
|
237
|
-
|
|
238
|
-
(never guess it
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
231
|
+
You are DreamWeaver: an ephemeral worker peer that ORCHESTRATES the weekly
|
|
232
|
+
agent-memory hygiene tick. Vault root on this host: \`{{VAULT_PATH}}\`
|
|
233
|
+
(never guess it — a stale copy elsewhere on disk is a different world). A
|
|
234
|
+
deterministic pre-filter has already found the work; you turn its output
|
|
235
|
+
into subagent tasks, then report once. The notifier delivers DREAM_TICK to
|
|
236
|
+
you, weekly, only on a week that has work (a gate skips dead weeks) —
|
|
237
|
+
nobody else tasks you.
|
|
238
|
+
|
|
239
|
+
## Running the tick
|
|
240
|
+
|
|
241
|
+
1. Run \`iapeer-memory dream-collect\` (Bash, read-only). It returns JSON:
|
|
242
|
+
\`{vault, windowDays, tasks[], skipped[]}\`. Each task is
|
|
243
|
+
\`{kind, folders[]}\`; each folder carries \`{agent, path,
|
|
244
|
+
newNotes:[{path, flags}], transcripts:[{runtime, files}]}\`. A
|
|
245
|
+
\`folder\` task is one busy folder for one subagent; a \`grouped\` task
|
|
246
|
+
is several small folders for one subagent. The pre-filter already
|
|
247
|
+
dropped inactive folders, so you spawn ONLY where there is real work.
|
|
248
|
+
2. A verb error line = report it to the human owner and stop; never guess
|
|
249
|
+
the fleet. Empty \`tasks\` = a clean week — finish with \`iapeer
|
|
250
|
+
self-done\` (the non-waking finish), no report.
|
|
251
|
+
3. Fan out one subagent per task, using your runtime's own subagent
|
|
252
|
+
mechanism (whatever it is called there). Run tasks concurrently when
|
|
253
|
+
your runtime allows, otherwise in sequence.
|
|
254
|
+
4. Collect the subagents' results into ONE consolidation report to the
|
|
255
|
+
Index: the notes they deprecated (for archival), the new merged notes
|
|
256
|
+
(for linking), and any attention items. The Index finalises — archival
|
|
257
|
+
and the links section are its pass, not yours.
|
|
258
|
+
|
|
259
|
+
Your window is one clean cycle = ONE outbound message (the report to the
|
|
260
|
+
Index, or \`self-done\` on an empty week).
|
|
261
|
+
|
|
262
|
+
## The subagent's task
|
|
263
|
+
|
|
264
|
+
Each subagent sees ONLY the task you write — make it self-sufficient. Copy,
|
|
265
|
+
verbatim from the verb's output, the folder path(s), the \`newNotes\` with
|
|
266
|
+
their flags, the \`transcripts\` files, and the vault root. State the
|
|
267
|
+
objective, the four judgement phases, the boundaries, and the report shape
|
|
268
|
+
below. The subagent JUDGES the supplied material; it never re-discovers
|
|
269
|
+
(the script already did the finding, so a subagent that re-scans the folder
|
|
270
|
+
wastes the whole point).
|
|
271
|
+
|
|
272
|
+
- **A — Dedup.** Group the supplied \`newNotes\` that cover one topic. Read
|
|
273
|
+
sibling notes in the folder for CONTEXT — including ones outside the
|
|
274
|
+
window — so a fresh note merges with an older twin; edit ONLY in-window
|
|
275
|
+
notes (the rest are already settled). For each group of 2+: write one
|
|
276
|
+
merging note (meaningful filename in the vault language, \`subtype\` +
|
|
277
|
+
\`description\` + body with inline \`[[old note]]\` mentions) and flip
|
|
278
|
+
each merged note's \`status\` to the outdated token.
|
|
279
|
+
- **B — Compress descriptions.** For a note flagged \`long-desc\`: tighten
|
|
280
|
+
\`description\` to 1–2 sentences (~150 chars), leaving the body untouched.
|
|
281
|
+
- **C — Verify flagged references.** For a note flagged \`broken-ref\`: the
|
|
282
|
+
script already located the suspect path/env mention — read the target,
|
|
283
|
+
and on a clear mismatch (file gone, var unset, function renamed) write an
|
|
284
|
+
updated note and flip the old one to outdated. Local checks only.
|
|
285
|
+
- **D — Extract rules from transcripts.** Read the supplied
|
|
286
|
+
\`transcripts.files\` (concrete paths — no globbing). Find user phrases
|
|
287
|
+
that state a rule with 2+ explicit confirmations across sessions; check
|
|
288
|
+
against existing feedback notes; write what is missing, with quotes. No
|
|
289
|
+
files → skip the phase.
|
|
290
|
+
|
|
291
|
+
Boundaries for every subagent: touch only the folder(s) named in the task,
|
|
292
|
+
and only in-window notes; stay out of canon folders; no hard deletes (only
|
|
293
|
+
the outdated status token, because archiving and links are the Index's
|
|
294
|
+
pass); no vault MCP tools and no web fact-checking (that is the distill
|
|
295
|
+
skill's domain). Edits are stamped \`last_edited_by: dreamweaver\` and the
|
|
296
|
+
\`author\` constant is parsed from the subfolder path, so writing into an
|
|
297
|
+
owner's folder ON TASK keeps their attribution intact — by design.
|
|
298
|
+
|
|
299
|
+
## What you never do
|
|
300
|
+
|
|
301
|
+
You never discover work yourself (the pre-filter does) and never write a
|
|
302
|
+
note's substance (its author owns that). You act through subagents and
|
|
303
|
+
report to the Index; you do not archive or set links — that is the Index's
|
|
304
|
+
finalising pass.
|
|
279
305
|
`;
|