@agfpd/iapeer-memory 0.2.3 → 0.2.4
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 +7 -0
- package/src/commands/dream-paths.ts +153 -0
- package/src/fleet.ts +49 -42
- package/src/templates/roles-en.ts +20 -13
- package/src/templates/roles-ru.ts +19 -13
- package/src/watcher.ts +6 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agfpd/iapeer-memory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "iapeer-memory — peer memory for the iapeer ecosystem: vault, memoryd (index/search/MCP-http), layer-5 context fragments, role doctrines. The package IS the system; the claude/codex plugins are thin session sockets (docs/10-distribution.md, ADR-009).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agfpd/iapeer-memory-core": "0.2.
|
|
30
|
+
"@agfpd/iapeer-memory-core": "0.2.4"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/bun": "^1.2.0",
|
package/src/cli.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { cmdInit } from "./commands/init.js";
|
|
|
24
24
|
import { cmdInstallBinary } from "./commands/install-binary.js";
|
|
25
25
|
import { cmdMemoryd } from "./commands/memoryd.js";
|
|
26
26
|
import { cmdMigrate } from "./commands/migrate.js";
|
|
27
|
+
import { cmdDreamPaths } from "./commands/dream-paths.js";
|
|
27
28
|
import { cmdProvisionPeer, cmdUnprovisionPeer } from "./commands/provision-peer.js";
|
|
28
29
|
import { cmdRender } from "./commands/render.js";
|
|
29
30
|
import { cmdStatus } from "./commands/status.js";
|
|
@@ -61,6 +62,10 @@ Commands:
|
|
|
61
62
|
fm-update [ops] FILE... structural frontmatter edits + attribution stamp
|
|
62
63
|
migrate --source DIR move harness auto-memory into the vault
|
|
63
64
|
(dry-run by default; --apply to execute)
|
|
65
|
+
dream-paths tick-time DreamWeaver fan-out resolution: agent
|
|
66
|
+
memory folders + transcript globs per runtime
|
|
67
|
+
from the LIVE registry (the Index shells this on
|
|
68
|
+
DREAM_TICK; read-only)
|
|
64
69
|
render index|fragment|doctrine|guide
|
|
65
70
|
render one artifact explicitly (memoryd does this
|
|
66
71
|
continuously; render is the manual/scripted path)
|
|
@@ -125,6 +130,8 @@ export async function main(argv: string[]): Promise<number> {
|
|
|
125
130
|
return cmdUpdate(rest, egress);
|
|
126
131
|
case "install-binary":
|
|
127
132
|
return cmdInstallBinary(rest, egress);
|
|
133
|
+
case "dream-paths":
|
|
134
|
+
return cmdDreamPaths(rest, egress);
|
|
128
135
|
case "provision-peer":
|
|
129
136
|
return cmdProvisionPeer(rest, egress);
|
|
130
137
|
case "unprovision-peer":
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `iapeer-memory dream-paths [--iapeer-bin P]` — tick-time resolution of the
|
|
3
|
+
* DreamWeaver fan-out (P5 §4.3, boris-accepted form (б) + source (1)).
|
|
4
|
+
*
|
|
5
|
+
* The weekly DREAM_TICK lands in a FRESH index session; the Index shells
|
|
6
|
+
* THIS verb and fans DreamWeaver out over its output — one agent-memory
|
|
7
|
+
* subfolder per task, transcript globs riding along. Resolution happens AT
|
|
8
|
+
* THE TICK, never baked into the timer registration: a baked snapshot
|
|
9
|
+
* re-creates the «фаза D мертва, glob-skip маскирует» class one layer down.
|
|
10
|
+
*
|
|
11
|
+
* SOURCE = the LIVE registry (`iapeer list --json`), not fleet.json — the
|
|
12
|
+
* freshness proof (facts, 11.06): birth-provision does NOT touch fleet.json
|
|
13
|
+
* (writeFleetMap call sites: init/update/verify --repair only) and the
|
|
14
|
+
* SessionStart kick is heartbeat-gated (silent on a healthy host), so a
|
|
15
|
+
* peer born after the last update is INVISIBLE to fleet.json for weeks —
|
|
16
|
+
* the live registry is the only source that sees it. Read-as-egress: a
|
|
17
|
+
* legitimate live channel of the prod CLI (the refusing test handle blocks
|
|
18
|
+
* it; hermetic tests pass --iapeer-bin).
|
|
19
|
+
*
|
|
20
|
+
* READ-ONLY by contract: one registry list spawn + vault readdir +
|
|
21
|
+
* realpath. No writes, no signals, no detached spawns.
|
|
22
|
+
*
|
|
23
|
+
* Transcript path forms (host facts):
|
|
24
|
+
* claude — `~/.claude/projects/<slug(cwd)>/*.jsonl`; slug = every
|
|
25
|
+
* non-alphanumeric of the REGISTRY cwd → '-' (live form:
|
|
26
|
+
* /Users/macmini/.iapeer/peers/index → -Users-macmini--iapeer-peers-index;
|
|
27
|
+
* the registry cwd verbatim, NOT realpath — claude slugs the path the
|
|
28
|
+
* session launched in);
|
|
29
|
+
* codex — `~/.codex/sessions/**\/rollout-*.jsonl` (HOST-WIDE pool) +
|
|
30
|
+
* `cwdFilter` = realpath(cwd): the worker matches the payload's
|
|
31
|
+
* session_meta.cwd — the iapeer-contract realpath rule.
|
|
32
|
+
*
|
|
33
|
+
* Folders without a live peer get `transcripts: []` — phase D skips them
|
|
34
|
+
* honestly (A–C still run); peers without a memory subfolder are not in
|
|
35
|
+
* the fan-out (nothing to consolidate).
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import fs from "node:fs";
|
|
39
|
+
import os from "node:os";
|
|
40
|
+
import path from "node:path";
|
|
41
|
+
import { getTaxonomy, isLocaleId } from "@agfpd/iapeer-memory-core";
|
|
42
|
+
import type { Egress } from "../egress.js";
|
|
43
|
+
import { queryRegistry, type FleetPeer } from "../fleet.js";
|
|
44
|
+
|
|
45
|
+
/** Claude projects-dir slug — the live disk form (ls ~/.claude/projects). */
|
|
46
|
+
export function claudeProjectSlug(cwd: string): string {
|
|
47
|
+
return cwd.replace(/[^A-Za-z0-9]/g, "-");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type TranscriptSpec = {
|
|
51
|
+
runtime: "claude" | "codex";
|
|
52
|
+
glob: string;
|
|
53
|
+
/** codex only: the worker filters the HOST-WIDE pool by the payload's
|
|
54
|
+
* session_meta.cwd against this realpath (iapeer contract). */
|
|
55
|
+
cwdFilter?: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export function transcriptSpecs(peer: FleetPeer, home: string): TranscriptSpec[] {
|
|
59
|
+
const specs: TranscriptSpec[] = [];
|
|
60
|
+
if (peer.runtimes.includes("claude")) {
|
|
61
|
+
specs.push({
|
|
62
|
+
runtime: "claude",
|
|
63
|
+
glob: path.join(home, ".claude", "projects", claudeProjectSlug(peer.cwd), "*.jsonl"),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (peer.runtimes.includes("codex")) {
|
|
67
|
+
let real = peer.cwd;
|
|
68
|
+
try {
|
|
69
|
+
real = fs.realpathSync(peer.cwd);
|
|
70
|
+
} catch {
|
|
71
|
+
// vanished cwd — keep the registry form; the filter simply matches nothing
|
|
72
|
+
}
|
|
73
|
+
specs.push({
|
|
74
|
+
runtime: "codex",
|
|
75
|
+
glob: path.join(home, ".codex", "sessions", "**", "rollout-*.jsonl"),
|
|
76
|
+
cwdFilter: real,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return specs;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export type DreamFolder = {
|
|
83
|
+
agent: string;
|
|
84
|
+
path: string;
|
|
85
|
+
transcripts: TranscriptSpec[];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export function buildDreamPaths(opts: {
|
|
89
|
+
vault: string;
|
|
90
|
+
agentMemoryFolder: string;
|
|
91
|
+
peers: FleetPeer[];
|
|
92
|
+
home: string;
|
|
93
|
+
}): DreamFolder[] {
|
|
94
|
+
const memoryRoot = path.join(opts.vault, opts.agentMemoryFolder);
|
|
95
|
+
let entries: fs.Dirent[];
|
|
96
|
+
try {
|
|
97
|
+
entries = fs.readdirSync(memoryRoot, { withFileTypes: true });
|
|
98
|
+
} catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const byPersonality = new Map(opts.peers.map((p) => [p.personality, p]));
|
|
102
|
+
return entries
|
|
103
|
+
.filter((e) => e.isDirectory() && !e.name.startsWith("."))
|
|
104
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
105
|
+
.map((e) => {
|
|
106
|
+
const peer = byPersonality.get(e.name);
|
|
107
|
+
return {
|
|
108
|
+
agent: e.name,
|
|
109
|
+
path: path.join(memoryRoot, e.name),
|
|
110
|
+
transcripts: peer ? transcriptSpecs(peer, opts.home) : [],
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function cmdDreamPaths(argv: string[], egress: Egress): number {
|
|
116
|
+
let iapeerBin: string | undefined;
|
|
117
|
+
for (let i = 0; i < argv.length; i++) {
|
|
118
|
+
const a = argv[i];
|
|
119
|
+
if (a === "--iapeer-bin") iapeerBin = argv[++i];
|
|
120
|
+
else {
|
|
121
|
+
console.error(`iapeer-memory dream-paths: unknown flag: ${a}`);
|
|
122
|
+
return 2;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const vault = process.env.IAPEER_MEMORY_VAULT_PATH ?? "";
|
|
127
|
+
if (!vault) {
|
|
128
|
+
console.error("iapeer-memory dream-paths: IAPEER_MEMORY_VAULT_PATH is not set — not provisioned");
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
const localeRaw = process.env.IAPEER_MEMORY_LOCALE || "en";
|
|
132
|
+
if (!isLocaleId(localeRaw)) {
|
|
133
|
+
console.error(`iapeer-memory dream-paths: unknown locale "${localeRaw}"`);
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const q = queryRegistry(egress, { iapeerBin });
|
|
138
|
+
if ("error" in q) {
|
|
139
|
+
// LOUD: a silent empty fan-out would re-create the masked-dead-phase
|
|
140
|
+
// class — the Index sees this line and reports instead of guessing.
|
|
141
|
+
console.error(`iapeer-memory dream-paths: live registry unavailable — ${q.error}`);
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const folders = buildDreamPaths({
|
|
146
|
+
vault,
|
|
147
|
+
agentMemoryFolder: getTaxonomy(localeRaw).folders.agentMemory,
|
|
148
|
+
peers: q.peers,
|
|
149
|
+
home: os.homedir(),
|
|
150
|
+
});
|
|
151
|
+
console.log(JSON.stringify({ vault, folders }, null, 2));
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
package/src/fleet.ts
CHANGED
|
@@ -70,65 +70,72 @@ export function readFleetMap(fleetMapPath: string): FleetPeer[] | null {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
/** Live-registry query — the ONE place `iapeer list --json` is parsed.
|
|
74
|
+
* Shared by writeFleetMap (the persisted map) and dream-paths (the
|
|
75
|
+
* tick-time resolution; freshness fact: birth does NOT touch fleet.json
|
|
76
|
+
* and the SessionStart kick is heartbeat-gated, so the LIVE registry is
|
|
77
|
+
* the only source that sees a newborn before the next update). */
|
|
78
|
+
export function queryRegistry(
|
|
74
79
|
egress: Egress,
|
|
75
|
-
opts: {
|
|
76
|
-
|
|
77
|
-
iapeerBin?: string;
|
|
78
|
-
/** Injectable for tests. */
|
|
79
|
-
nowIso?: string;
|
|
80
|
-
},
|
|
81
|
-
): FleetMapResult {
|
|
80
|
+
opts: { iapeerBin?: string },
|
|
81
|
+
): { peers: FleetPeer[] } | { error: string } {
|
|
82
82
|
const bin = opts.iapeerBin ?? IAPEER_BIN;
|
|
83
83
|
const proc = egress.spawnSync([bin, "list", "--json"], {
|
|
84
84
|
explicitBin: opts.iapeerBin !== undefined,
|
|
85
85
|
});
|
|
86
86
|
if (proc.refused) {
|
|
87
|
-
return {
|
|
88
|
-
action: "failed",
|
|
89
|
-
count: 0,
|
|
90
|
-
detail: "live-registry query suppressed (test sandbox) — pass a fake iapeerBin",
|
|
91
|
-
};
|
|
87
|
+
return { error: "live-registry query suppressed (test sandbox) — pass a fake iapeerBin" };
|
|
92
88
|
}
|
|
93
89
|
if (proc.spawnError) {
|
|
94
|
-
return {
|
|
90
|
+
return { error: `${bin} unavailable: ${proc.spawnError}` };
|
|
95
91
|
}
|
|
96
92
|
if (proc.exitCode !== 0) {
|
|
97
|
-
return {
|
|
98
|
-
action: "failed",
|
|
99
|
-
count: 0,
|
|
100
|
-
detail: (proc.stderr.trim() || `iapeer list exited ${proc.exitCode}`).slice(0, 160),
|
|
101
|
-
};
|
|
93
|
+
return { error: (proc.stderr.trim() || `iapeer list exited ${proc.exitCode}`).slice(0, 160) };
|
|
102
94
|
}
|
|
103
|
-
const stdout = proc.stdout;
|
|
104
|
-
|
|
105
95
|
let listed: ListedPeer[];
|
|
106
96
|
try {
|
|
107
|
-
const raw = JSON.parse(stdout) as unknown;
|
|
97
|
+
const raw = JSON.parse(proc.stdout) as unknown;
|
|
108
98
|
listed = Array.isArray(raw) ? (raw as ListedPeer[]) : [];
|
|
109
99
|
} catch {
|
|
110
|
-
return {
|
|
100
|
+
return { error: "iapeer list --json: unparsable output" };
|
|
111
101
|
}
|
|
102
|
+
return {
|
|
103
|
+
peers: listed
|
|
104
|
+
.filter(
|
|
105
|
+
(p): p is ListedPeer & { personality: string; cwd: string } =>
|
|
106
|
+
typeof p.personality === "string" &&
|
|
107
|
+
p.personality.trim() !== "" &&
|
|
108
|
+
typeof p.cwd === "string" &&
|
|
109
|
+
p.cwd.trim() !== "",
|
|
110
|
+
)
|
|
111
|
+
.map((p) => ({
|
|
112
|
+
personality: p.personality.trim(),
|
|
113
|
+
cwd: p.cwd.trim(),
|
|
114
|
+
runtimes: [
|
|
115
|
+
...new Set(
|
|
116
|
+
(Array.isArray(p.runtimes) ? p.runtimes : [])
|
|
117
|
+
.map((r) => (typeof r?.runtime === "string" ? r.runtime.trim() : ""))
|
|
118
|
+
.filter(Boolean),
|
|
119
|
+
),
|
|
120
|
+
],
|
|
121
|
+
})),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
.map((r) => (typeof r?.runtime === "string" ? r.runtime.trim() : ""))
|
|
128
|
-
.filter(Boolean),
|
|
129
|
-
),
|
|
130
|
-
],
|
|
131
|
-
}));
|
|
125
|
+
export function writeFleetMap(
|
|
126
|
+
egress: Egress,
|
|
127
|
+
opts: {
|
|
128
|
+
fleetMapPath: string;
|
|
129
|
+
iapeerBin?: string;
|
|
130
|
+
/** Injectable for tests. */
|
|
131
|
+
nowIso?: string;
|
|
132
|
+
},
|
|
133
|
+
): FleetMapResult {
|
|
134
|
+
const q = queryRegistry(egress, { iapeerBin: opts.iapeerBin });
|
|
135
|
+
if ("error" in q) {
|
|
136
|
+
return { action: "failed", count: 0, detail: q.error };
|
|
137
|
+
}
|
|
138
|
+
const peers = q.peers;
|
|
132
139
|
|
|
133
140
|
const body =
|
|
134
141
|
JSON.stringify(
|
|
@@ -51,13 +51,17 @@ 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
|
-
- **DREAM_TICK** (notifier timer, weekly) —
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
- **DREAM_TICK** (notifier timer, weekly) — run \`iapeer-memory
|
|
55
|
+
dream-paths\` (read-only; the LIVE registry at tick time) and fan out
|
|
56
|
+
DreamWeaver over the folders of its output (including your own),
|
|
57
|
+
strictly one folder per task, sequentially. DreamWeaver takes tasks ONLY
|
|
58
|
+
from you (the one exception: a folder's owner may task it on their own
|
|
59
|
+
folder). Task: \`{agent, path, mode, transcripts_window_days,
|
|
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.
|
|
61
65
|
- **Direct IAP** from agents or the human — structure questions; never
|
|
62
66
|
run searches for others (they have their own vault tools).
|
|
63
67
|
|
|
@@ -237,7 +241,7 @@ on-demand from a folder's OWNER for their own folder only. One task = one
|
|
|
237
241
|
clean window = ONE outbound message (the final consolidation report to the
|
|
238
242
|
task sender). Discipline: touch ONLY the folder named in the task.
|
|
239
243
|
|
|
240
|
-
Task: \`{agent, path, mode, transcripts_window_days}\`.
|
|
244
|
+
Task: \`{agent, path, mode, transcripts_window_days, transcripts}\`.
|
|
241
245
|
|
|
242
246
|
## The four phases
|
|
243
247
|
|
|
@@ -253,11 +257,14 @@ Task: \`{agent, path, mode, transcripts_window_days}\`.
|
|
|
253
257
|
mentions in bodies; read the targets; on a clear mismatch (file gone,
|
|
254
258
|
function renamed) write an updated note and flip the old one to the
|
|
255
259
|
outdated token. LOCAL checks only.
|
|
256
|
-
- **D — Transcript scan.** Read the
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
- **D — Transcript scan.** Read the session transcripts for the window
|
|
261
|
+
(\`transcripts_window_days\`) per the task's \`transcripts\`: each entry
|
|
262
|
+
is a glob; for \`runtime: codex\` the store is HOST-WIDE — take ONLY the
|
|
263
|
+
sessions whose \`session_meta.cwd\` equals the entry's \`cwdFilter\`
|
|
264
|
+
(foreign cwds are foreign memory). No entries / empty glob → skip the
|
|
265
|
+
phase. Find user phrases that formulate a rule with 2+ explicit
|
|
266
|
+
confirmations in different sessions; check against existing feedback
|
|
267
|
+
notes; write new notes with quotes for what's missing.
|
|
261
268
|
|
|
262
269
|
## Hard limits
|
|
263
270
|
|
|
@@ -44,13 +44,16 @@ locale: ru
|
|
|
44
44
|
НЕВЫЧИТАННЫМИ по обычным правилам; \`needs_review: true\` уже едет с
|
|
45
45
|
каждым файлом. Scriber довычитает их со следующей PERMANENT_BATCH,
|
|
46
46
|
когда оживёт.
|
|
47
|
-
- **DREAM_TICK** (notifier-таймер, еженедельно) —
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
\`
|
|
47
|
+
- **DREAM_TICK** (notifier-таймер, еженедельно) — выполни
|
|
48
|
+
\`iapeer-memory dream-paths\` (read-only; живой реестр на момент тика) и
|
|
49
|
+
fan-out DreamWeaver по папкам его вывода (включая твою), строго одна
|
|
50
|
+
папка на задачу, последовательно. DreamWeaver берёт задачи ТОЛЬКО от
|
|
51
|
+
тебя (единственное исключение: владелец папки — на свою собственную).
|
|
52
|
+
Задача: \`{agent, path, mode, transcripts_window_days, transcripts}\` —
|
|
53
|
+
\`transcripts\` перекладывай из вывода verb'а КАК ЕСТЬ (глобы + codex
|
|
54
|
+
cwdFilter; формы путей — зона кода, не твоя). Ошибка verb'а = доложи
|
|
55
|
+
владельцу, флот не угадывай. По отчёту консолидации архивируй
|
|
56
|
+
устаревшее, \`attention\`-блоки отрабатывай сам.
|
|
54
57
|
- **Прямые IAP** от агентов и человека — вопросы структуры; чужие поиски
|
|
55
58
|
не выполняешь (у агентов свои vault-тулы).
|
|
56
59
|
|
|
@@ -224,7 +227,7 @@ on-demand от ВЛАДЕЛЬЦА папки — только на его соб
|
|
|
224
227
|
одно чистое окно = ОДНО исходящее (финальный отчёт консолидации
|
|
225
228
|
постановщику). Дисциплина: трогай ТОЛЬКО папку из задачи.
|
|
226
229
|
|
|
227
|
-
Задача: \`{agent, path, mode, transcripts_window_days}\`.
|
|
230
|
+
Задача: \`{agent, path, mode, transcripts_window_days, transcripts}\`.
|
|
228
231
|
|
|
229
232
|
## Четыре фазы
|
|
230
233
|
|
|
@@ -239,11 +242,14 @@ on-demand от ВЛАДЕЛЬЦА папки — только на его соб
|
|
|
239
242
|
env-переменных; прочитай цели; при явном расхождении (файла нет, функция
|
|
240
243
|
переименована) — новая updated-заметка + старая в «устарело». Только
|
|
241
244
|
ЛОКАЛЬНЫЕ проверки.
|
|
242
|
-
- **D — Скан транскриптов.** Прочитай транскрипты сессий
|
|
243
|
-
(\`transcripts_window_days
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
- **D — Скан транскриптов.** Прочитай транскрипты сессий за окно
|
|
246
|
+
(\`transcripts_window_days\`) по \`transcripts\` из задачи: для каждой
|
|
247
|
+
записи — glob; у \`runtime: codex\` хранилище HOST-WIDE, бери ТОЛЬКО
|
|
248
|
+
сессии, чей \`session_meta.cwd\` равен \`cwdFilter\` записи (чужие cwd —
|
|
249
|
+
чужая память). Записей нет / glob пуст — фаза пропускается. Найди
|
|
250
|
+
user-фразы, формулирующие правило, с 2+ явными подтверждениями в разных
|
|
251
|
+
сессиях; сверь с существующими feedback-заметками; недостающее — новой
|
|
252
|
+
заметкой с цитатами.
|
|
247
253
|
|
|
248
254
|
## Жёсткие границы
|
|
249
255
|
|
package/src/watcher.ts
CHANGED
|
@@ -201,9 +201,12 @@ export function dreamTimerMessage(opts?: {
|
|
|
201
201
|
return JSON.stringify({
|
|
202
202
|
when: opts?.cron ?? "0 4 * * 1",
|
|
203
203
|
message:
|
|
204
|
-
"DREAM_TICK: weekly agent-memory consolidation.
|
|
205
|
-
"
|
|
206
|
-
"folder per task, sequentially
|
|
204
|
+
"DREAM_TICK: weekly agent-memory consolidation. Run `iapeer-memory " +
|
|
205
|
+
"dream-paths` (read-only) and fan out DreamWeaver over its folders — " +
|
|
206
|
+
"strictly one folder per task, sequentially, carrying that folder's " +
|
|
207
|
+
"`transcripts` (globs + codex cwdFilter) into the task — per your " +
|
|
208
|
+
"doctrine. The verb resolves the LIVE registry at tick time; an error " +
|
|
209
|
+
"line from it = report, do not guess the fleet.",
|
|
207
210
|
target: opts?.target ?? "index",
|
|
208
211
|
id: opts?.id ?? DREAM_TRIGGER_ID,
|
|
209
212
|
});
|