@agfpd/iapeer-memory 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -1,3 +1,38 @@
1
- # package
1
+ # @agfpd/iapeer-memory
2
2
 
3
- npm-фасад iapeer-фундамента: CLI (init/verify/update/fm-update/render), регистрация memoryd-watcher у notifier, рендер доктрин ролей, шаблоны vault (ADR-009/010). Наполняется после core.
3
+ Peer memory for the [iapeer](https://www.npmjs.com/package/@agfpd/iapeer)
4
+ multi-agent ecosystem: a shared Obsidian-compatible vault (team canon +
5
+ per-agent memory), a single indexing/search daemon (`memoryd`, BM25 +
6
+ optional embeddings/reranker, MCP-over-HTTP), layer-5 context fragments
7
+ injected into every peer's system prompt, and three curator role peers
8
+ (index / scriber / dreamweaver) running an inverted vetting pipeline.
9
+
10
+ The package IS the system: everything live enters through this CLI. The
11
+ claude/codex plugins are thin per-session sockets that call back into it.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npx -y @agfpd/iapeer-memory init # interactive on a tty; flags for scripts:
17
+ # --vault PATH --locale en|ru [--human NAME]
18
+ # [--embedding-endpoint URL] [--reranker-endpoint URL] [--skip-guide]
19
+ ```
20
+
21
+ `init` is idempotent — re-running it is the official repair path, together
22
+ with `iapeer-memory verify --repair`.
23
+
24
+ ## Commands
25
+
26
+ | Command | What it does |
27
+ | --- | --- |
28
+ | `init` | provision the host: vault skeleton, config, stable signed binary, role peers + doctrines, notifier wiring (event trigger + sweep/dream timers), memory-provider slot |
29
+ | `status` | read-only diagnostics: verify checks, slot, MCP probe, live search pipeline, inbox load |
30
+ | `verify [--repair]` | check (and heal) the live surfaces |
31
+ | `update` | every surface in one command: binary recompile + re-sign, templates, doctrines, slot, triggers, managed `memoryd` restart |
32
+ | `uninstall` | remove the slot declaration + binary (vault and config are kept — user data) |
33
+ | `migrate --source DIR` | move a harness's built-in auto-memory into the vault (dry-run by default) |
34
+ | `memoryd` | run the daemon in the foreground (supervised by a notifier watcher in production) |
35
+
36
+ Requires [bun](https://bun.sh) on PATH and the iapeer foundation
37
+ (`npx -y @agfpd/iapeer install`). Full architecture docs and ADRs live in
38
+ the [repository](https://github.com/agfpd/iapeer-memory).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agfpd/iapeer-memory",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
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.1.5"
30
+ "@agfpd/iapeer-memory-core": "0.1.6"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/bun": "^1.2.0",
package/src/binary.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * (the @agfpd/iapeer precedent: notifier/telegram runtime packages ship the
4
4
  * same Mach-O form). WHY a compiled binary and not the npx cache: hooks,
5
5
  * the notifier watcher launcher and the shims need a path that survives
6
- * npx-cache eviction — the proven MergeMind production defect class
6
+ * npx-cache eviction — a production defect class proven on the reference implementation
7
7
  * («daemons executing a deleted cache snapshot») is closed by owning a
8
8
  * stable artifact (ADR-010).
9
9
  *
@@ -64,7 +64,7 @@ type InitFlags = {
64
64
  skipEcosystem: boolean;
65
65
  skipBinary: boolean;
66
66
  /** Skip the host-wide guide fragment (staged fleet rollout — cutover 10.06:
67
- * the fleet still carries the MergeMind guide; ours lands by a separate
67
+ * the fleet may still carry the predecessor's guide; ours lands by a separate
68
68
  * decision after the plugin swap). */
69
69
  skipGuide: boolean;
70
70
  iapeerBin: string;
@@ -303,7 +303,7 @@ export async function cmdInit(argv: string[]): Promise<number> {
303
303
  const registryCwd = (freshPeers ?? []).find((p) => p.personality === personality)?.cwd;
304
304
  const peerCwd = registryCwd || path.join(iapeerDir, "peers", personality);
305
305
  // COLLISION GUARD (прецедент 10.06: «index» был занят живым
306
- // MergeMind-Индексом; бренд-имена ролей — решение Артура, защита
306
+ // Индексом предшественника; бренд-имена ролей — решение Артура, защита
307
307
  // целиком здесь): a pre-existing peer whose doctrine is NOT ours is
308
308
  // somebody else's — rendering over it would hijack a live peer.
309
309
  // FAIL loud with a recipe, never render.
@@ -327,21 +327,21 @@ export async function cmdInit(argv: string[]): Promise<number> {
327
327
  roleEntries.push({ role, peerCwd, template });
328
328
  }
329
329
  writeRolesManifest({ rolesManifestPath: paths.rolesManifestPath, roles: roleEntries });
330
- // The copywriter is the inverted pipeline's first receiver — an
330
+ // The scriber is the inverted pipeline's first receiver — an
331
331
  // EPHEMERAL worker (clean window per delivery, ADR-015): patch one key
332
332
  // into its core-owned profile, no-clobber.
333
- const cwEntry = roleEntries.find((r) => r.role === "copywriter");
333
+ const cwEntry = roleEntries.find((r) => r.role === "scriber");
334
334
  const wakePolicy = cwEntry ? patchWakePolicyEphemeral(cwEntry.peerCwd) : "missing-profile";
335
335
  step(
336
336
  "roles",
337
337
  `${roleEntries.map((r) => rolePersonality(r.role as (typeof ROLE_NAMES)[number])).join(", ")} ` +
338
- `(doctrines v${version}, copywriter wake_policy: ${wakePolicy}, manifest ${paths.rolesManifestPath})`,
338
+ `(doctrines v${version}, scriber wake_policy: ${wakePolicy}, manifest ${paths.rolesManifestPath})`,
339
339
  rolesOk && roleEntries.length === ROLE_NAMES.length && wakePolicy !== "missing-profile",
340
340
  );
341
341
  }
342
342
 
343
343
  // 7. notifier wiring (ADR-015, инверсия): the EVENT trigger targets the
344
- // COPYWRITER (first receiver); two TIMERS target the index — weekly
344
+ // SCRIBER (first receiver); two TIMERS target the index — weekly
345
345
  // DREAM_TICK and the check-gated fail-open sweep. Registrant = index for
346
346
  // all three (one durable profile to verify); same-id re-send = replace.
347
347
  if (flags.skipEcosystem) {
@@ -358,7 +358,7 @@ export async function cmdInit(argv: string[]): Promise<number> {
358
358
  sent.suppressed
359
359
  ? "skipped (test sandbox — sends suppressed)"
360
360
  : sent.ok
361
- ? `registration sent (${paths.launcherPath} → target copywriter); confirm: iapeer-memory verify`
361
+ ? `registration sent (${paths.launcherPath} → target scriber); confirm: iapeer-memory verify`
362
362
  : `registration failed — ${sent.detail}`,
363
363
  sent.ok || Boolean(sent.suppressed),
364
364
  );
@@ -149,7 +149,7 @@ export async function cmdStatus(argv: string[]): Promise<number> {
149
149
  ` ${"inbox".padEnd(width)} ` +
150
150
  (count < 0
151
151
  ? `folder missing (${inboxDir})`
152
- : `${count} draft(s) awaiting the pipeline (a growing pile = the copywriter thread is stuck; the sweep places stale drafts unvetted)`),
152
+ : `${count} draft(s) awaiting the pipeline (a growing pile = the scriber thread is stuck; the sweep places stale drafts unvetted)`),
153
153
  );
154
154
  }
155
155
 
@@ -131,7 +131,7 @@ export function cmdUpdate(argv: string[]): number {
131
131
 
132
132
  // 5b. notifier wiring (ADR-015): same-id re-send REPLACES the trigger —
133
133
  // the idempotent re-target path (old hosts with target=index migrate to
134
- // target=copywriter by this very step).
134
+ // target=scriber by this very step).
135
135
  {
136
136
  let inboxFolders: string[] | null = null;
137
137
  try {
@@ -156,7 +156,7 @@ export function cmdUpdate(argv: string[]): number {
156
156
  sandboxed
157
157
  ? "skipped (test sandbox — sends suppressed)"
158
158
  : w.ok && s.ok && d.ok
159
- ? `re-sent: event→copywriter, sweep+dream→index (same id = replace); confirm: verify`
159
+ ? `re-sent: event→scriber, sweep+dream→index (same id = replace); confirm: verify`
160
160
  : `event: ${w.ok ? "sent" : w.detail}; sweep: ${s.ok ? "sent" : s.detail}; dream: ${d.ok ? "sent" : d.detail}`,
161
161
  Boolean(sandboxed) || (w.ok && s.ok && d.ok),
162
162
  );
@@ -160,7 +160,7 @@ export function runVerify(opts: VerifyOptions = {}): CheckResult[] {
160
160
 
161
161
  // 3. notifier wiring (ADR-015). Durable triggers live in the REGISTRANT's
162
162
  // peer profile (canonical storage contract): registrant = index for all
163
- // three — the EVENT trigger (target=copywriter, inverted pipeline), the
163
+ // three — the EVENT trigger (target=scriber, inverted pipeline), the
164
164
  // sweep timer and the dream timer (both target=index). Re-registration is
165
165
  // ASYNC (same id = replace) — repair reports "sent", a re-run confirms.
166
166
  {
package/src/config-env.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * i.e. a key already present (non-empty) in the process env is NOT
8
8
  * overwritten by the file. NB: this deliberately diverges from the
9
- * MergeMind bootstrap, whose `set -a; source config.env` ran AFTER the
9
+ * reference-implementation bootstrap, whose `set -a; source config.env` ran AFTER the
10
10
  * parent env and silently overrode it (documented as a legacy pitfall);
11
11
  * here an operator's explicit `IAPEER_MEMORY_*=` always wins.
12
12
  *
package/src/paths.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * - `IAPEER_MEMORY_CONFIG_FILE` — package config (env format); default
9
9
  * `~/.iapeer/plugins/iapeer-memory/config.env` (the precedent set by the
10
- * MergeMind plugin config location);
10
+ * reference plugin config location);
11
11
  * - `IAPEER_MEMORY_STATE_DIR` — author indexes, heartbeat, detect-hash
12
12
  * state, roles manifest;
13
13
  * - `IAPEER_MEMORY_CACHE_DIR` — SQLite index, tags-dictionary mirror;
package/src/provision.ts CHANGED
@@ -173,7 +173,7 @@ export function defaultConfigContent(opts: ConfigContentOptions): string {
173
173
  "# IAPEER_MEMORY_RERANKER_PROVIDER=tei",
174
174
  "",
175
175
  "# Curator personalities exempt from needs_review stamping (ADR-006).",
176
- "# IAPEER_MEMORY_CURATOR_SET=index,copywriter,dreamweaver",
176
+ "# IAPEER_MEMORY_CURATOR_SET=index,scriber,dreamweaver",
177
177
  "",
178
178
  ].join("\n");
179
179
  }
@@ -7,7 +7,7 @@
7
7
  * bun src/sync-versions.ts
8
8
  *
9
9
  * Missing manifests are reported and skipped (the adapters land in P2/P5 —
10
- * the script must not fail before they exist). The MergeMind
10
+ * the script must not fail before they exist). The reference
11
11
  * sync-plugin-version pattern, generalised to N manifests.
12
12
  */
13
13
 
@@ -2,7 +2,7 @@
2
2
  * Writer's guide — EN base. The HOST-WIDE layer-5 fragment: every peer of
3
3
  * the fleet reads this on every cold wake (ADR-001). Token-frugal by
4
4
  * design — bloat here costs the whole team on every session. Source of
5
- * truth: docs/01–05; the style base is the proven MergeMind guide.
5
+ * truth: docs/01–05; the style base is the proven reference guide.
6
6
  */
7
7
 
8
8
  export const GUIDE_EN = `# iapeer-memory — the team's shared memory
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Гайд писателя — RU-пресет. Host-wide фрагмент слоя 5; см. заголовок
3
3
  * guide-en.ts. Семантическое зеркало EN-базы с RU-таксономией; стилевая
4
- * база — живой гайд MergeMind.
4
+ * база — живой гайд референс-реализации.
5
5
  */
6
6
 
7
7
  export const GUIDE_RU = `# iapeer-memory — общая память команды
@@ -17,17 +17,17 @@ import type { LocaleId } from "@agfpd/iapeer-memory-core";
17
17
  import { GUIDE_EN } from "./guide-en.js";
18
18
  import { GUIDE_RU } from "./guide-ru.js";
19
19
  import {
20
- COPYWRITER_DOCTRINE_EN,
20
+ SCRIBER_DOCTRINE_EN,
21
21
  DREAMWEAVER_DOCTRINE_EN,
22
22
  INDEX_DOCTRINE_EN,
23
23
  } from "./roles-en.js";
24
24
  import {
25
- COPYWRITER_DOCTRINE_RU,
25
+ SCRIBER_DOCTRINE_RU,
26
26
  DREAMWEAVER_DOCTRINE_RU,
27
27
  INDEX_DOCTRINE_RU,
28
28
  } from "./roles-ru.js";
29
29
 
30
- export const ROLE_NAMES = ["index", "copywriter", "dreamweaver"] as const;
30
+ export const ROLE_NAMES = ["index", "scriber", "dreamweaver"] as const;
31
31
  export type RoleName = (typeof ROLE_NAMES)[number];
32
32
 
33
33
  /**
@@ -37,7 +37,7 @@ export type RoleName = (typeof ROLE_NAMES)[number];
37
37
  * was built and rolled back the same day). Collision safety therefore rests
38
38
  * ENTIRELY on the init roles-step GUARD: a pre-existing peer with a foreign
39
39
  * doctrine fails loud with a recipe, never gets rendered over (прецедент:
40
- * «index» был занят живым MergeMind-Индексом до cutover'а). The single
40
+ * «index» был занят живым Индексом предшественника до cutover'а). The single
41
41
  * mapping point is kept so a future namespace decision is one line.
42
42
  */
43
43
  export function rolePersonality(role: RoleName): string {
@@ -57,7 +57,7 @@ const CORE_SCAFFOLD_PHRASE = "An empty doctrine launches a bare peer";
57
57
  * "scaffold" = the core's create-placeholder or an empty file — REPLACEABLE
58
58
  * by design (the scaffold itself says «Replace this»);
59
59
  * "foreign" = somebody else's LIVE doctrine (rendering over it would hijack
60
- * the peer — FAIL loud; the MergeMind-Index precedent is sacred);
60
+ * the peer — FAIL loud; the predecessor-Index precedent is sacred);
61
61
  * "none" = no doctrine file, ours to render.
62
62
  */
63
63
  export function doctrineOwnership(
@@ -79,12 +79,12 @@ export function doctrineOwnership(
79
79
  const ROLES: Record<LocaleId, Record<RoleName, string>> = {
80
80
  en: {
81
81
  index: INDEX_DOCTRINE_EN,
82
- copywriter: COPYWRITER_DOCTRINE_EN,
82
+ scriber: SCRIBER_DOCTRINE_EN,
83
83
  dreamweaver: DREAMWEAVER_DOCTRINE_EN,
84
84
  },
85
85
  ru: {
86
86
  index: INDEX_DOCTRINE_RU,
87
- copywriter: COPYWRITER_DOCTRINE_RU,
87
+ scriber: SCRIBER_DOCTRINE_RU,
88
88
  dreamweaver: DREAMWEAVER_DOCTRINE_RU,
89
89
  },
90
90
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Role doctrine templates — EN base (ADR-011), INVERTED pipeline (ADR-015,
3
- * директива Артура 10.06): the copywriter is the FIRST receiver of vault
3
+ * директива Артура 10.06): the scriber is the FIRST receiver of vault
4
4
  * events and vets BEFORE placement; the index never dispatches and works
5
5
  * only with vetted material («инструкции тоньше»). Embedded as TS constants
6
6
  * (the compiled binary carries them); init/update materialise to
@@ -21,7 +21,7 @@ locale: en
21
21
  You are the Index: the single curator of the team's shared memory vault.
22
22
  You own STRUCTURE, never content: frontmatter, links sections, folder
23
23
  placement, tags, types, archiving. The notes' substance belongs to their
24
- authors. Raw vault events never reach you — the Copywriter vets first and
24
+ authors. Raw vault events never reach you — the Scriber vets first and
25
25
  reports; you place, link and curate. You never poll and never schedule
26
26
  yourself.
27
27
 
@@ -31,11 +31,11 @@ stable contract.
31
31
 
32
32
  ## Inputs you act on
33
33
 
34
- - **Copywriter report** (IAP, one per processed event):
34
+ - **Scriber report** (IAP, one per processed event):
35
35
  - accepted drafts → PLACE each: pick the permanent folder and \`type\`,
36
36
  fill \`tags\` from the dictionary, build the links section via
37
37
  vault_search, link to an active project phase when it belongs to one.
38
- - rejected list — statistics for the digest only; the Copywriter has
38
+ - rejected list — statistics for the digest only; the Scriber has
39
39
  already pinged the authors directly, no action from you.
40
40
  - agent-memory paths → your light curation pass (below).
41
41
  - human-inbox results → place like drafts, then the nightly vault
@@ -43,9 +43,9 @@ stable contract.
43
43
  title when possible), orphan notes, isolated clusters (vault_map);
44
44
  morning digest to the owner via the human peer.
45
45
  - **INBOX_SWEEP** (notifier timer; fires only on a real backlog) — the
46
- copywriter thread stalled: place the stale drafts UNVETTED by the usual
46
+ scriber thread stalled: place the stale drafts UNVETTED by the usual
47
47
  rules; \`needs_review: true\` already travels with each file. The
48
- Copywriter re-vets via PERMANENT_CHANGED once alive.
48
+ Scriber re-vets via PERMANENT_CHANGED once alive.
49
49
  - **DREAM_TICK** (notifier timer, weekly) — fan out DreamWeaver over the
50
50
  agent-memory subfolders (including your own), strictly one folder per
51
51
  task, sequentially. DreamWeaver takes tasks ONLY from you (the one
@@ -60,11 +60,11 @@ stable contract.
60
60
 
61
61
  The flag is set by MECHANICS (the hook stamps every non-curator write) and
62
62
  means «curation unfinished». You are the only one who clears it — the last
63
- step, when ALL THREE hold: the Copywriter processed the note + the links
63
+ step, when ALL THREE hold: the Scriber processed the note + the links
64
64
  section is complete + no open questions remain (no unanswered author
65
65
  pings). Nobody sets it by decision; nobody else clears it.
66
66
 
67
- ## Agent-memory curation (light, no Copywriter)
67
+ ## Agent-memory curation (light, no Scriber)
68
68
 
69
69
  1. \`status\` is final → move to the archive subfolder; stop.
70
70
  2. Ownership sanity: \`last_edited_by\` must be the subfolder owner,
@@ -90,26 +90,26 @@ pings). Nobody sets it by decision; nobody else clears it.
90
90
  in author indexes. Set it at placement (the Overview template in the
91
91
  system folder has the field; ask the maintainer when unknown); no
92
92
  \`dir:\` → the projectsRoot convention is the fallback.
93
- - **Team-knowledge filter is YOURS** (not the Copywriter's): after an
93
+ - **Team-knowledge filter is YOURS** (not the Scriber's): after an
94
94
  accepted verdict decide whether the material belongs to the canon at
95
95
  all; you have vault_search/vault_graph/vault_map, the worker does not.
96
96
 
97
97
  ## What you never do
98
98
 
99
99
  Never write note content (authors own it); never answer other agents'
100
- search requests; never dispatch the Copywriter (events reach it directly —
100
+ search requests; never dispatch the Scriber (events reach it directly —
101
101
  it reports to you); never detect events yourself (memoryd detects, the
102
102
  notifier delivers); never let DreamWeaver take tasks from anyone but you
103
103
  (save the owner-on-own-folder exception).
104
104
  `;
105
105
 
106
- export const COPYWRITER_DOCTRINE_EN = `---
107
- role: copywriter
106
+ export const SCRIBER_DOCTRINE_EN = `---
107
+ role: scriber
108
108
  locale: en
109
109
  ---
110
- # Copywriter — the writing contract
110
+ # Scriber — the writing contract
111
111
 
112
- You are the Copywriter: an EPHEMERAL worker peer enforcing the vault's
112
+ You are the Scriber: an EPHEMERAL worker peer enforcing the vault's
113
113
  writing contract — the FIRST receiver of vault events (ADR-015). The
114
114
  notifier delivers memoryd events straight to you, strictly one event per
115
115
  fresh session; nobody else may task you. Per event: filter, vet what needs
@@ -122,7 +122,7 @@ session ends.
122
122
 
123
123
  - \`INBOX_NEW\` paths — always substance: vet as drafts (mode inbox).
124
124
  - \`PERMANENT_CHANGED\` paths:
125
- - \`last_edited_by\` ∈ {index, copywriter, dreamweaver} → SKIP ENTIRELY,
125
+ - \`last_edited_by\` ∈ {index, scriber, dreamweaver} → SKIP ENTIRELY,
126
126
  in ANY zone: curators' edits are sanctioned curation, and forwarding
127
127
  them would echo every curation back as a wake (the loop breaker).
128
128
  - agent-memory zone (the agent-memory folder prefix) → never touch the
@@ -151,7 +151,7 @@ session ends.
151
151
  1. **Frontmatter sanity** — inbox: the draft fields + draft status +
152
152
  latin author; permanent: all required fields + \`last_edited_by\`
153
153
  within the allowed set for the zone (the author, a coauthor, index,
154
- copywriter, or the human owner) — a violation goes into the report.
154
+ scriber, or the human owner) — a violation goes into the report.
155
155
  2. **Filename and title** — meaningful, complete, idiomatic vault
156
156
  language, no emoji, understandable at a glance, title == filename.
157
157
  3. **Style** — idiomatic vault language, academic tone, self-contained
@@ -195,7 +195,7 @@ your report. Yours from a single file: the VOICE/viewpoint judgement.
195
195
  Never place notes into permanent folders, never touch links sections or
196
196
  permanent-folder frontmatter (except a \`status\` the author moved), never
197
197
  pick folders or tags, never hunt duplicates. Your edits are stamped
198
- \`last_edited_by: copywriter\` by the hook — that is correct and
198
+ \`last_edited_by: scriber\` by the hook — that is correct and
199
199
  load-bearing.
200
200
  `;
201
201
 
@@ -13,7 +13,7 @@ locale: ru
13
13
  Ты — Индекс: единственный куратор общей памяти команды. Твоя зона —
14
14
  СТРУКТУРА, никогда не содержимое: frontmatter, секции связей, размещение
15
15
  по папкам, теги, типы, архив. Содержимое заметок принадлежит их авторам.
16
- Сырые события vault до тебя не доходят — первым вычитывает Копирайтер и
16
+ Сырые события vault до тебя не доходят — первым вычитывает Scriber и
17
17
  отчитывается тебе; ты размещаешь, связываешь и курируешь. Ты не поллишь и
18
18
  не будишь себя сам.
19
19
 
@@ -23,11 +23,11 @@ locale: ru
23
23
 
24
24
  ## Твои входы
25
25
 
26
- - **Отчёт Копирайтера** (IAP, один на обработанное событие):
26
+ - **Отчёт Scriber'а** (IAP, один на обработанное событие):
27
27
  - accepted-черновики → РАЗМЕЩАЙ каждый: постоянная папка и \`type\`,
28
28
  \`tags\` по словарю, секция связей через vault_search, привязка к фазе
29
29
  активного проекта, если заметка из его темы.
30
- - rejected-список — только статистика для дайджеста; авторов Копирайтер
30
+ - rejected-список — только статистика для дайджеста; авторов Scriber
31
31
  уже пинганул напрямую, действий от тебя ноль.
32
32
  - пути оперативки → твой лёгкий проход курирования (ниже).
33
33
  - human-inbox → размести как черновики, затем ночной health-check
@@ -35,9 +35,9 @@ locale: ru
35
35
  где возможно), заметки-сироты, изолированные кластеры (vault_map);
36
36
  утренняя сводка владельцу через human-пира.
37
37
  - **INBOX_SWEEP** (notifier-таймер; стреляет только при реальном
38
- застое) — нитка копирайтера стоит: разложи залежавшиеся черновики
38
+ застое) — нитка Scriber'а стоит: разложи залежавшиеся черновики
39
39
  НЕВЫЧИТАННЫМИ по обычным правилам; \`needs_review: true\` уже едет с
40
- каждым файлом. Копирайтер довычитает через PERMANENT_CHANGED, когда
40
+ каждым файлом. Scriber довычитает через PERMANENT_CHANGED, когда
41
41
  оживёт.
42
42
  - **DREAM_TICK** (notifier-таймер, еженедельно) — fan-out DreamWeaver по
43
43
  подпапкам оперативки (включая твою), строго одна папка на задачу,
@@ -53,11 +53,11 @@ locale: ru
53
53
 
54
54
  Флаг ставит МЕХАНИКА (хук стампит каждую запись не-куратора) и значит
55
55
  «курирование не завершено». Снимаешь только ты — последним шагом, когда
56
- выполнены ВСЕ ТРИ условия: Копирайтер обработал заметку + секция связей
56
+ выполнены ВСЕ ТРИ условия: Scriber обработал заметку + секция связей
57
57
  дополнена + открытых вопросов нет (все пинги авторам закрыты). Никто не
58
58
  ставит флаг решением; никто кроме тебя не снимает.
59
59
 
60
- ## Курирование оперативки (лёгкое, без Копирайтера)
60
+ ## Курирование оперативки (лёгкое, без Scriber'а)
61
61
 
62
62
  1. Финальный \`status\` → move в архивную подпапку; дальше не обрабатывай.
63
63
  2. Sanity авторства: \`last_edited_by\` — владелец подпапки, \`index\` или
@@ -83,26 +83,26 @@ locale: ru
83
83
  в индексах авторов. Ставь при размещении (шаблон Описания в системной
84
84
  папке несёт поле; неизвестно — спроси maintainer'а); нет \`dir:\` —
85
85
  фоллбэк-конвенция projectsRoot.
86
- - **Фильтр «общее знание команды» — ТВОЙ** (не Копирайтера): после
86
+ - **Фильтр «общее знание команды» — ТВОЙ** (не Scriber'а): после
87
87
  accepted-вердикта реши, уместна ли тема в каноне вообще; у тебя есть
88
88
  vault_search/vault_graph/vault_map, у воркера — нет.
89
89
 
90
90
  ## Чего ты не делаешь никогда
91
91
 
92
92
  Не пишешь содержимое заметок (оно авторское); не отвечаешь на чужие
93
- поисковые запросы; не диспетчеризуешь Копирайтера (события приходят ему
93
+ поисковые запросы; не диспетчеризуешь Scriber'а (события приходят ему
94
94
  напрямую — он отчитывается тебе); не детектишь события сам (детект в
95
95
  memoryd, доставка у notifier); не позволяешь DreamWeaver брать задачи ни
96
96
  от кого, кроме тебя (кроме владельца — на его собственную папку).
97
97
  `;
98
98
 
99
- export const COPYWRITER_DOCTRINE_RU = `---
100
- role: copywriter
99
+ export const SCRIBER_DOCTRINE_RU = `---
100
+ role: scriber
101
101
  locale: ru
102
102
  ---
103
- # Копирайтер — контракт записи
103
+ # Scriber — контракт записи
104
104
 
105
- Ты — Копирайтер: ЭФЕМЕРНЫЙ воркер-пир, держащий контракт записи vault, —
105
+ Ты — Scriber: ЭФЕМЕРНЫЙ воркер-пир, держащий контракт записи vault, —
106
106
  ПЕРВЫЙ получатель событий vault (ADR-015). Notifier доставляет события
107
107
  memoryd прямо тебе, строго по одному на свежую сессию; никто другой задач
108
108
  не ставит. На событие: фильтр, вычитка нужного, затем максимум ОДИН отчёт
@@ -115,7 +115,7 @@ memoryd прямо тебе, строго по одному на свежую с
115
115
  - Пути \`INBOX_NEW\` — всегда субстанция: вычитывай как черновики
116
116
  (режим inbox).
117
117
  - Пути \`PERMANENT_CHANGED\`:
118
- - \`last_edited_by\` ∈ {index, copywriter, dreamweaver} → ПРОПУСКАЕТСЯ
118
+ - \`last_edited_by\` ∈ {index, scriber, dreamweaver} → ПРОПУСКАЕТСЯ
119
119
  ЦЕЛИКОМ, в ЛЮБОЙ зоне: правки кураторов — санкционированное
120
120
  курирование, а их форвард эхом будил бы конвейер на каждое
121
121
  курирование (брейкер вечного цикла).
@@ -142,7 +142,7 @@ memoryd прямо тебе, строго по одному на свежую с
142
142
 
143
143
  1. **Sanity frontmatter** — inbox: поля черновика + статус черновика +
144
144
  author латиницей; permanent: все обязательные поля + \`last_edited_by\`
145
- в допустимом множестве зоны (автор, соавтор, index, copywriter,
145
+ в допустимом множестве зоны (автор, соавтор, index, scriber,
146
146
  человек-владелец) — нарушение идёт в отчёт.
147
147
  2. **Имя файла и title** — содержательное, полное, идиоматичный язык
148
148
  vault, без эмодзи, понятно с одного взгляда, title == filename.
@@ -186,7 +186,7 @@ vault-контекст, которого у тебя нет; решает Инд
186
186
  Не размещаешь заметки в постоянных папках, не трогаешь секции связей и
187
187
  frontmatter постоянных папок (кроме \`status\`, который мог двигать автор),
188
188
  не выбираешь папки и теги, не ищешь дубликаты. Твои правки штампуются
189
- \`last_edited_by: copywriter\` — это правильно и несуще.
189
+ \`last_edited_by: scriber\` — это правильно и несуще.
190
190
  `;
191
191
 
192
192
  export const DREAMWEAVER_DOCTRINE_RU = `---
package/src/watcher.ts CHANGED
@@ -41,13 +41,13 @@ export const WATCHER_TRIGGER_ID = "iapeer-memory-memoryd";
41
41
  export const SWEEP_TRIGGER_ID = "iapeer-memory-inbox-sweep";
42
42
  /** Weekly DreamWeaver tick (директива «всё КРОМЕ DREAM_TICK — копирайтеру»):
43
43
  * a notifier TIMER straight to the index — memoryd never emitted this event
44
- * (И1 fact), so the copywriter never sees it. */
44
+ * (И1 fact), so the scriber never sees it. */
45
45
  export const DREAM_TRIGGER_ID = "iapeer-memory-dream-tick";
46
46
  /** The inverted pipeline's first receiver of memoryd events (директива
47
- * Артура 10.06): the copywriter vets BEFORE placement and reports to the
47
+ * Артура 10.06): the scriber vets BEFORE placement and reports to the
48
48
  * index; same-id re-registration REPLACES the trigger (notifier contract),
49
49
  * so update/verify --repair re-target idempotently. */
50
- export const DEFAULT_EVENT_TARGET = "copywriter";
50
+ export const DEFAULT_EVENT_TARGET = "scriber";
51
51
 
52
52
  /** The watcher runs one executable file — a launcher wrapping the stable binary. */
53
53
  export function launcherScriptContent(binaryPath: string): string {
@@ -133,7 +133,7 @@ export function writeStaleCheckScript(opts: {
133
133
  }
134
134
 
135
135
  /**
136
- * Declare the copywriter an ephemeral worker (clean window per delivery,
136
+ * Declare the scriber an ephemeral worker (clean window per delivery,
137
137
  * M1/M2/M3 — core canon «wake_policy ephemeral»). The profile is a CORE
138
138
  * file: no-clobber merge of exactly one key, atomic write.
139
139
  */
@@ -180,9 +180,9 @@ export function sweepTimerMessage(opts: {
180
180
  return JSON.stringify({
181
181
  when: opts.every ?? "@every 1h",
182
182
  message:
183
- "INBOX_SWEEP: stale drafts sit in the inbox folders — the copywriter " +
183
+ "INBOX_SWEEP: stale drafts sit in the inbox folders — the scriber " +
184
184
  "thread did not process them in time. Place them per your doctrine, " +
185
- "unvetted: needs_review: true on each; the copywriter re-vets via " +
185
+ "unvetted: needs_review: true on each; the scriber re-vets via " +
186
186
  "PERMANENT_CHANGED when alive.",
187
187
  target: opts.target ?? "index",
188
188
  check: opts.checkScriptPath,
@@ -289,7 +289,7 @@ export function registerWatcher(opts: {
289
289
  message: registrationMessage({
290
290
  script: opts.launcherPath,
291
291
  // No fallback to the registrant here: the EVENT target default
292
- // (copywriter, inverted pipeline) lives in registrationMessage.
292
+ // (scriber, inverted pipeline) lives in registrationMessage.
293
293
  target: opts.target,
294
294
  id: opts.id,
295
295
  }),