@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 +37 -2
- package/package.json +2 -2
- package/src/binary.ts +1 -1
- package/src/commands/init.ts +7 -7
- package/src/commands/status.ts +1 -1
- package/src/commands/update.ts +2 -2
- package/src/commands/verify.ts +1 -1
- package/src/config-env.ts +1 -1
- package/src/paths.ts +1 -1
- package/src/provision.ts +1 -1
- package/src/sync-versions.ts +1 -1
- package/src/templates/guide-en.ts +1 -1
- package/src/templates/guide-ru.ts +1 -1
- package/src/templates/index.ts +7 -7
- package/src/templates/roles-en.ts +17 -17
- package/src/templates/roles-ru.ts +16 -16
- package/src/watcher.ts +7 -7
package/README.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @agfpd/iapeer-memory
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
|
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.
|
|
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 —
|
|
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
|
*
|
package/src/commands/init.ts
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
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
|
|
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 === "
|
|
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},
|
|
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
|
-
//
|
|
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
|
|
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
|
);
|
package/src/commands/status.ts
CHANGED
|
@@ -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
|
|
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
|
|
package/src/commands/update.ts
CHANGED
|
@@ -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=
|
|
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→
|
|
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
|
);
|
package/src/commands/verify.ts
CHANGED
|
@@ -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=
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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,
|
|
176
|
+
"# IAPEER_MEMORY_CURATOR_SET=index,scriber,dreamweaver",
|
|
177
177
|
"",
|
|
178
178
|
].join("\n");
|
|
179
179
|
}
|
package/src/sync-versions.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
* база — живой гайд
|
|
4
|
+
* база — живой гайд референс-реализации.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export const GUIDE_RU = `# iapeer-memory — общая память команды
|
package/src/templates/index.ts
CHANGED
|
@@ -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
|
-
|
|
20
|
+
SCRIBER_DOCTRINE_EN,
|
|
21
21
|
DREAMWEAVER_DOCTRINE_EN,
|
|
22
22
|
INDEX_DOCTRINE_EN,
|
|
23
23
|
} from "./roles-en.js";
|
|
24
24
|
import {
|
|
25
|
-
|
|
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", "
|
|
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» был занят живым
|
|
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
|
|
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
|
-
|
|
82
|
+
scriber: SCRIBER_DOCTRINE_EN,
|
|
83
83
|
dreamweaver: DREAMWEAVER_DOCTRINE_EN,
|
|
84
84
|
},
|
|
85
85
|
ru: {
|
|
86
86
|
index: INDEX_DOCTRINE_RU,
|
|
87
|
-
|
|
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
|
|
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
|
|
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
|
-
- **
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
107
|
-
role:
|
|
106
|
+
export const SCRIBER_DOCTRINE_EN = `---
|
|
107
|
+
role: scriber
|
|
108
108
|
locale: en
|
|
109
109
|
---
|
|
110
|
-
#
|
|
110
|
+
# Scriber — the writing contract
|
|
111
111
|
|
|
112
|
-
You are the
|
|
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,
|
|
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
|
-
|
|
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:
|
|
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
|
-
- **Отчёт
|
|
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
|
-
каждым файлом.
|
|
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
|
|
100
|
-
role:
|
|
99
|
+
export const SCRIBER_DOCTRINE_RU = `---
|
|
100
|
+
role: scriber
|
|
101
101
|
locale: ru
|
|
102
102
|
---
|
|
103
|
-
#
|
|
103
|
+
# Scriber — контракт записи
|
|
104
104
|
|
|
105
|
-
Ты —
|
|
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,
|
|
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,
|
|
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:
|
|
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
|
|
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
|
|
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 = "
|
|
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
|
|
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
|
|
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
|
|
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
|
-
// (
|
|
292
|
+
// (scriber, inverted pipeline) lives in registrationMessage.
|
|
293
293
|
target: opts.target,
|
|
294
294
|
id: opts.id,
|
|
295
295
|
}),
|