mister-wolf 2.16.3 → 2.17.1
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 +24 -11
- package/README.ru.md +25 -14
- package/dist/adapters/cli/cli-entry.d.ts.map +1 -1
- package/dist/adapters/cli/cli-entry.js +25 -0
- package/dist/adapters/cli/cli-entry.js.map +1 -1
- package/dist/adapters/cli/commands/claim.d.ts +6 -0
- package/dist/adapters/cli/commands/claim.d.ts.map +1 -0
- package/dist/adapters/cli/commands/claim.js +65 -0
- package/dist/adapters/cli/commands/claim.js.map +1 -0
- package/dist/adapters/cli/commands/face.d.ts +3 -0
- package/dist/adapters/cli/commands/face.d.ts.map +1 -0
- package/dist/adapters/cli/commands/face.js +227 -0
- package/dist/adapters/cli/commands/face.js.map +1 -0
- package/dist/adapters/cli/commands/memory-add.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-add.js +1 -1
- package/dist/adapters/cli/commands/memory-add.js.map +1 -1
- package/dist/adapters/cli/commands/memory-doctor.d.ts +20 -0
- package/dist/adapters/cli/commands/memory-doctor.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-doctor.js +123 -7
- package/dist/adapters/cli/commands/memory-doctor.js.map +1 -1
- package/dist/adapters/cli/commands/memory-edit.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-edit.js +6 -52
- package/dist/adapters/cli/commands/memory-edit.js.map +1 -1
- package/dist/adapters/cli/commands/memory-init.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-init.js +37 -54
- package/dist/adapters/cli/commands/memory-init.js.map +1 -1
- package/dist/adapters/cli/commands/memory-list.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-list.js +1 -1
- package/dist/adapters/cli/commands/memory-list.js.map +1 -1
- package/dist/adapters/cli/commands/memory-scaffold.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-scaffold.js +2 -1
- package/dist/adapters/cli/commands/memory-scaffold.js.map +1 -1
- package/dist/adapters/cli/commands/memory-search.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-search.js +1 -1
- package/dist/adapters/cli/commands/memory-search.js.map +1 -1
- package/dist/adapters/cli/commands/memory-sync.js +1 -1
- package/dist/adapters/cli/commands/memory-sync.js.map +1 -1
- package/dist/adapters/cli/commands/propose.d.ts +3 -0
- package/dist/adapters/cli/commands/propose.d.ts.map +1 -0
- package/dist/adapters/cli/commands/propose.js +94 -0
- package/dist/adapters/cli/commands/propose.js.map +1 -0
- package/dist/adapters/cli/type-command-generator.d.ts.map +1 -1
- package/dist/adapters/cli/type-command-generator.js +2 -0
- package/dist/adapters/cli/type-command-generator.js.map +1 -1
- package/dist/adapters/fs/claim-registry.d.ts +85 -0
- package/dist/adapters/fs/claim-registry.d.ts.map +1 -0
- package/dist/adapters/fs/claim-registry.js +276 -0
- package/dist/adapters/fs/claim-registry.js.map +1 -0
- package/dist/adapters/fs/memory-root.d.ts +26 -1
- package/dist/adapters/fs/memory-root.d.ts.map +1 -1
- package/dist/adapters/fs/memory-root.js +88 -2
- package/dist/adapters/fs/memory-root.js.map +1 -1
- package/dist/app/use-cases/add-memory-object.d.ts +5 -0
- package/dist/app/use-cases/add-memory-object.d.ts.map +1 -1
- package/dist/app/use-cases/add-memory-object.js +24 -5
- package/dist/app/use-cases/add-memory-object.js.map +1 -1
- package/dist/app/use-cases/claim-artifact.d.ts +31 -0
- package/dist/app/use-cases/claim-artifact.d.ts.map +1 -0
- package/dist/app/use-cases/claim-artifact.js +38 -0
- package/dist/app/use-cases/claim-artifact.js.map +1 -0
- package/dist/app/use-cases/create-face-version.d.ts +101 -0
- package/dist/app/use-cases/create-face-version.d.ts.map +1 -0
- package/dist/app/use-cases/create-face-version.js +100 -0
- package/dist/app/use-cases/create-face-version.js.map +1 -0
- package/dist/app/use-cases/create-mutation-record.d.ts +55 -0
- package/dist/app/use-cases/create-mutation-record.d.ts.map +1 -0
- package/dist/app/use-cases/create-mutation-record.js +78 -0
- package/dist/app/use-cases/create-mutation-record.js.map +1 -0
- package/dist/app/use-cases/deliver-proposal.d.ts +26 -0
- package/dist/app/use-cases/deliver-proposal.d.ts.map +1 -0
- package/dist/app/use-cases/deliver-proposal.js +35 -0
- package/dist/app/use-cases/deliver-proposal.js.map +1 -0
- package/dist/app/use-cases/edit-memory-object.d.ts +26 -0
- package/dist/app/use-cases/edit-memory-object.d.ts.map +1 -0
- package/dist/app/use-cases/edit-memory-object.js +57 -0
- package/dist/app/use-cases/edit-memory-object.js.map +1 -0
- package/dist/app/use-cases/face-operation.d.ts +81 -0
- package/dist/app/use-cases/face-operation.d.ts.map +1 -0
- package/dist/app/use-cases/face-operation.js +503 -0
- package/dist/app/use-cases/face-operation.js.map +1 -0
- package/dist/app/use-cases/get-call-injections.d.ts +12 -1
- package/dist/app/use-cases/get-call-injections.d.ts.map +1 -1
- package/dist/app/use-cases/get-call-injections.js +73 -12
- package/dist/app/use-cases/get-call-injections.js.map +1 -1
- package/dist/app/use-cases/migrate-faces.d.ts +81 -0
- package/dist/app/use-cases/migrate-faces.d.ts.map +1 -0
- package/dist/app/use-cases/migrate-faces.js +267 -0
- package/dist/app/use-cases/migrate-faces.js.map +1 -0
- package/dist/app/use-cases/promote-memory.d.ts +14 -1
- package/dist/app/use-cases/promote-memory.d.ts.map +1 -1
- package/dist/app/use-cases/promote-memory.js +36 -5
- package/dist/app/use-cases/promote-memory.js.map +1 -1
- package/dist/app/use-cases/record-relation.d.ts.map +1 -1
- package/dist/app/use-cases/record-relation.js +6 -0
- package/dist/app/use-cases/record-relation.js.map +1 -1
- package/dist/app/use-cases/save-proposal.d.ts +49 -0
- package/dist/app/use-cases/save-proposal.d.ts.map +1 -0
- package/dist/app/use-cases/save-proposal.js +32 -0
- package/dist/app/use-cases/save-proposal.js.map +1 -0
- package/dist/app/use-cases/scaffold-agent.d.ts.map +1 -1
- package/dist/app/use-cases/scaffold-agent.js +20 -52
- package/dist/app/use-cases/scaffold-agent.js.map +1 -1
- package/dist/app/use-cases/scaffold-artifact.d.ts +5 -0
- package/dist/app/use-cases/scaffold-artifact.d.ts.map +1 -1
- package/dist/app/use-cases/scaffold-artifact.js +2 -0
- package/dist/app/use-cases/scaffold-artifact.js.map +1 -1
- package/dist/app/use-cases/seed-base-playbooks.d.ts +17 -96
- package/dist/app/use-cases/seed-base-playbooks.d.ts.map +1 -1
- package/dist/app/use-cases/seed-base-playbooks.js +77 -32
- package/dist/app/use-cases/seed-base-playbooks.js.map +1 -1
- package/dist/app/use-cases/supersede-memory-object.d.ts +3 -1
- package/dist/app/use-cases/supersede-memory-object.d.ts.map +1 -1
- package/dist/app/use-cases/supersede-memory-object.js +8 -1
- package/dist/app/use-cases/supersede-memory-object.js.map +1 -1
- package/dist/app/use-cases/transition-memory-object.d.ts.map +1 -1
- package/dist/app/use-cases/transition-memory-object.js +6 -0
- package/dist/app/use-cases/transition-memory-object.js.map +1 -1
- package/dist/domain/facet-colors.d.ts.map +1 -1
- package/dist/domain/facet-colors.js +1 -0
- package/dist/domain/facet-colors.js.map +1 -1
- package/dist/domain/memory-types.d.ts +36 -1
- package/dist/domain/memory-types.d.ts.map +1 -1
- package/dist/domain/memory-types.js +36 -2
- package/dist/domain/memory-types.js.map +1 -1
- package/dist/domain/schemas/memory-event-schema.d.ts +8 -0
- package/dist/domain/schemas/memory-event-schema.d.ts.map +1 -1
- package/dist/domain/schemas/memory-event-schema.js +42 -1
- package/dist/domain/schemas/memory-event-schema.js.map +1 -1
- package/dist/domain/schemas/relation-schema.d.ts +6 -2
- package/dist/domain/schemas/relation-schema.d.ts.map +1 -1
- package/dist/domain/schemas/relation-schema.js +8 -0
- package/dist/domain/schemas/relation-schema.js.map +1 -1
- package/dist/domain/schemas/session-checkpoint-schema.d.ts +1 -1
- package/dist/domain/type-schema-builder.d.ts +4 -2
- package/dist/domain/type-schema-builder.d.ts.map +1 -1
- package/dist/domain/type-schema-builder.js +32 -1
- package/dist/domain/type-schema-builder.js.map +1 -1
- package/package.json +1 -1
- package/templates/.wolf/router.log +1 -1
- package/templates/base/agents/steward.md +9 -6
- package/templates/base/playbooks/complaint-protocol.md +1 -1
- package/templates/base/playbooks/steward-nastavnik.md +36 -17
- package/templates/opencode/plugins/wolf-router.ts +60 -10
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { resolveCreatedBy, resolveSessionId } from '../../domain/actor.js';
|
|
2
|
+
import { resolveMemoryRoot } from '../../adapters/fs/memory-root.js';
|
|
3
|
+
import { acquireClaim, listClaims, releaseClaim, requireClaim, } from '../../adapters/fs/claim-registry.js';
|
|
4
|
+
function identityOf(deps) {
|
|
5
|
+
return {
|
|
6
|
+
owner: resolveCreatedBy(undefined, deps.env ?? process.env),
|
|
7
|
+
sessionId: resolveSessionId(deps.env ?? process.env),
|
|
8
|
+
pid: deps.pid ?? process.pid,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function registryDeps(deps) {
|
|
12
|
+
return {
|
|
13
|
+
root: resolveMemoryRoot(deps.baseDir).root,
|
|
14
|
+
now: deps.now,
|
|
15
|
+
isAlive: deps.isAlive,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function acquireArtifactClaim(deps, artifact) {
|
|
19
|
+
return acquireClaim(registryDeps(deps), {
|
|
20
|
+
artifact,
|
|
21
|
+
identity: identityOf(deps),
|
|
22
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function releaseArtifactClaim(deps, artifact, transferTo) {
|
|
26
|
+
return releaseClaim(registryDeps(deps), { artifact, identity: identityOf(deps), transferTo });
|
|
27
|
+
}
|
|
28
|
+
export function listArtifactClaims(deps) {
|
|
29
|
+
return listClaims(registryDeps(deps));
|
|
30
|
+
}
|
|
31
|
+
export function makeClaimGuard(deps) {
|
|
32
|
+
const registry = registryDeps(deps);
|
|
33
|
+
const who = identityOf(deps);
|
|
34
|
+
return {
|
|
35
|
+
requireClaim: (artifact) => requireClaim(registry, artifact, { owner: who.owner, sessionId: who.sessionId }),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=claim-artifact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-artifact.js","sourceRoot":"","sources":["../../../src/app/use-cases/claim-artifact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,GAIb,MAAM,qCAAqC,CAAC;AAoB7C,SAAS,UAAU,CAAC,IAAuB;IACzC,OAAO;QACL,KAAK,EAAE,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QAC3D,SAAS,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QACpD,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAuB;IAC3C,OAAO;QACL,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI;QAC1C,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAuB,EAAE,QAAgB;IAC5E,OAAO,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;QACtC,QAAQ;QACR,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC;QAC1B,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;KAC/B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAuB,EACvB,QAAgB,EAChB,UAAmB;IAEnB,OAAO,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,OAAO,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AACxC,CAAC;AASD,MAAM,UAAU,cAAc,CAAC,IAAuB;IACpD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO;QACL,YAAY,EAAE,CAAC,QAAgB,EAAE,EAAE,CACjC,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;KACnF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Clock } from '../../ports/clock.port.js';
|
|
2
|
+
import { IdGenerator } from '../../ports/id-generator.port.js';
|
|
3
|
+
import { SearchIndex } from '../../ports/search-index.port.js';
|
|
4
|
+
import { MemoryLock } from '../../ports/memory-lock.port.js';
|
|
5
|
+
import { MemoryStore } from '../../ports/memory-store.port.js';
|
|
6
|
+
import { EventLog } from '../../ports/event-log.port.js';
|
|
7
|
+
import { RelationLog } from '../../ports/relation-log.port.js';
|
|
8
|
+
import { MemoryTypeDeclaration } from '../../domain/memory-types.js';
|
|
9
|
+
import { MemoryObject } from '../../domain/schemas/memory-object-schema.js';
|
|
10
|
+
import { type FaceFaultInjector } from './face-operation.js';
|
|
11
|
+
/** Волна 2.17 REQ-03/REQ-04 (design §«Механика версий», §Guard): единая
|
|
12
|
+
* версионирующая механика лиц — guard, номер версии, supersede head, журнал;
|
|
13
|
+
* всё под внешним MemoryLock (прецедент tool-librarian.ts:167: вложенные
|
|
14
|
+
* addMemoryObject/supersedeMemoryObject идут с lock: undefined).
|
|
15
|
+
* REQ-06 (design §«Запись мутации Стюарда»): мутация Стюарда (initiator
|
|
16
|
+
* 'steward') атомарно создаёт G17-запись + relation 'mutates' → версия.
|
|
17
|
+
* T-05: 'migrate'/'seed' — служебные пути (вход migrateFaces/посева base-set,
|
|
18
|
+
* design §Guard «посев идёт внутренним путём с initiator: 'seed'»): guard
|
|
19
|
+
* полномочий не применяется, содержание задаёт вызывающий.
|
|
20
|
+
*
|
|
21
|
+
* 2.17.1 REQ-03 (R04, design §3.3/ADR-3): сама цепочка — журналируемая
|
|
22
|
+
* операция в face-operation.ts (add_face(candidate) → G17 → relations →
|
|
23
|
+
* activate(commit) → supersede_prev → announce → op_committed) с resume
|
|
24
|
+
* по opId, авто-resume и abort; этот файл — валидация входа и guard
|
|
25
|
+
* (guard — до op_started, под lock). */
|
|
26
|
+
export type FaceCommand = 'new' | 'restore' | 'breakglass' | 'migrate' | 'seed';
|
|
27
|
+
export type FaceInitiator = 'steward' | 'owner' | 'breakglass' | 'migration' | 'seed';
|
|
28
|
+
/** Поля типа face поверх MemoryObject (декларация — memory-types.ts, T-01). */
|
|
29
|
+
export interface FaceFields {
|
|
30
|
+
owner_skill: string;
|
|
31
|
+
/** '1','2',… — номер назначает операция add_face под lock. */
|
|
32
|
+
version: string;
|
|
33
|
+
/** id версии-основы; отсутствует у первой версии (optional, не null). */
|
|
34
|
+
based_on?: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
initiator: FaceInitiator;
|
|
37
|
+
/** 2.17.1 REQ-03 (§3.3): привязка к операции — правило усыновления candidate. */
|
|
38
|
+
op_id?: string;
|
|
39
|
+
}
|
|
40
|
+
export type FaceObject = MemoryObject & FaceFields;
|
|
41
|
+
export interface CreateFaceVersionDeps {
|
|
42
|
+
store: MemoryStore;
|
|
43
|
+
log: EventLog;
|
|
44
|
+
clock: Clock;
|
|
45
|
+
idGen: IdGenerator;
|
|
46
|
+
index?: SearchIndex;
|
|
47
|
+
lock?: MemoryLock;
|
|
48
|
+
relations?: RelationLog;
|
|
49
|
+
declarations?: readonly MemoryTypeDeclaration[];
|
|
50
|
+
/** Атрибуция только из env (WOLF_ACTOR / WOLF_SESSION), по умолчанию process.env.
|
|
51
|
+
* Параметра-актёра у API нет: подмена инициатора (--created-by-подобная)
|
|
52
|
+
* исключена структурно (design §Guard, F-04). */
|
|
53
|
+
env?: NodeJS.ProcessEnv;
|
|
54
|
+
/** Тестовый seam (test-plan REQ-03): fault(point) бросается после завершения
|
|
55
|
+
* шага операции; прод-код не задаёт. */
|
|
56
|
+
fault?: FaceFaultInjector;
|
|
57
|
+
}
|
|
58
|
+
export interface CreateFaceVersionInput {
|
|
59
|
+
command: FaceCommand;
|
|
60
|
+
ownerSkill: string;
|
|
61
|
+
/** REQ-04 AC2: причина обязательна — без неё операция падает. */
|
|
62
|
+
reason: string;
|
|
63
|
+
/** Тело лица; для new обязательно, restore/breakglass берут из версии-основы. */
|
|
64
|
+
body?: string;
|
|
65
|
+
title?: string;
|
|
66
|
+
tags?: string[];
|
|
67
|
+
/** Основа: id записи или номер версии ('v2'/'2'). Обязателен для restore/breakglass. */
|
|
68
|
+
from?: string;
|
|
69
|
+
/** REQ-06 (G17): обязательны для command='new' (мутация Стюарда); для
|
|
70
|
+
* restore/breakglass шаблон не применяется (ADR-2: только мутации Стюарда). */
|
|
71
|
+
minimalChange?: string;
|
|
72
|
+
boundaries?: string;
|
|
73
|
+
exampleHelps?: string;
|
|
74
|
+
exampleKeep?: string;
|
|
75
|
+
verification?: string;
|
|
76
|
+
rollback?: string;
|
|
77
|
+
/** T-09 (design §«Механика версий», строка 88): id предложения, породившего
|
|
78
|
+
* версию — записывает relation ('proposes', proposal, faceNew). Связь только
|
|
79
|
+
* фиксируется: применение предложения остаётся решением Стюарда (REQ-09). */
|
|
80
|
+
fromProposal?: string;
|
|
81
|
+
/** 2.17.1 REQ-03 (§3.3): идентификатор операции — resume/идемпотентный
|
|
82
|
+
* повтор; при отсутствии генерируется faceop-<ts>-<rand4> (в результате). */
|
|
83
|
+
opId?: string;
|
|
84
|
+
/** 2.17.1 REQ-04 (design §3.4, F9): id активного legacy-head волны 2.17 —
|
|
85
|
+
* добавляет шаг supersede_legacy операции (между supersede_prev и announce).
|
|
86
|
+
* Служебный вход migrateFaces и посева 2.16.3 (§3.6); resume берёт значение
|
|
87
|
+
* из op_started input. */
|
|
88
|
+
legacyHeadId?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface CreateFaceVersionResult {
|
|
91
|
+
face: FaceObject;
|
|
92
|
+
/** Прежняя активная версия, superseded этой операцией; null у первой версии. */
|
|
93
|
+
supersededId: string | null;
|
|
94
|
+
/** G17-запись мутации (REQ-06): id note(history); null, если мутация не
|
|
95
|
+
* Стюардом (restore/breakglass). */
|
|
96
|
+
mutationRecordId: string | null;
|
|
97
|
+
/** 2.17.1 REQ-03: id журналируемой операции (печатают CLI/MCP для recover). */
|
|
98
|
+
opId: string;
|
|
99
|
+
}
|
|
100
|
+
export declare function createFaceVersion(deps: CreateFaceVersionDeps, input: CreateFaceVersionInput): Promise<CreateFaceVersionResult>;
|
|
101
|
+
//# sourceMappingURL=create-face-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-face-version.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/create-face-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { resolveCreatedBy, resolveSessionId } from '../../domain/actor.js';
|
|
2
|
+
import { UserFacingError } from '../../domain/errors.js';
|
|
3
|
+
import { missingG17Field } from './create-mutation-record.js';
|
|
4
|
+
import { resolveBase, runFaceMutation } from './face-operation.js';
|
|
5
|
+
/** Guard (design §Guard): new — строго agent:steward; restore/breakglass — user:*;
|
|
6
|
+
* breakglass дополнительно отказывает из агент-сессии (WOLF_SESSION=opc-*).
|
|
7
|
+
* migrate/seed — служебные пути (T-05): без проверки полномочий — вход
|
|
8
|
+
* внутренний (migrateFaces / посев base-set), содержание переносится дословно.
|
|
9
|
+
* null — доступ разрешён. */
|
|
10
|
+
function guardFailure(command, actor, sessionId) {
|
|
11
|
+
if (command === 'migrate' || command === 'seed')
|
|
12
|
+
return null;
|
|
13
|
+
if (command === 'new') {
|
|
14
|
+
if (actor !== 'agent:steward') {
|
|
15
|
+
return `Face mutation is steward-only: actor "${actor}" is not agent:steward (attribution is env-only, WOLF_ACTOR)`;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (!actor.startsWith('user:')) {
|
|
20
|
+
return `face ${command} is owner-only: actor "${actor}" is not user:* (attribution is env-only, WOLF_ACTOR)`;
|
|
21
|
+
}
|
|
22
|
+
if (command === 'breakglass' && sessionId !== null && sessionId.startsWith('opc-')) {
|
|
23
|
+
return 'breakglass is not available from an agent session (WOLF_SESSION=opc-*)';
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
async function appendDenied(deps, ownerSkill, actor, command) {
|
|
28
|
+
const now = deps.clock.now();
|
|
29
|
+
const event = {
|
|
30
|
+
id: deps.idGen.generateEventId(now),
|
|
31
|
+
type: 'memory.face.denied',
|
|
32
|
+
timestamp: now.toISOString(),
|
|
33
|
+
actor,
|
|
34
|
+
payload: { owner_skill: ownerSkill, actor, command },
|
|
35
|
+
};
|
|
36
|
+
await deps.log.append(event);
|
|
37
|
+
}
|
|
38
|
+
export async function createFaceVersion(deps, input) {
|
|
39
|
+
const env = deps.env ?? process.env;
|
|
40
|
+
const actor = resolveCreatedBy(undefined, env);
|
|
41
|
+
const sessionId = resolveSessionId(env);
|
|
42
|
+
if (!input.ownerSkill || input.ownerSkill.trim() === '') {
|
|
43
|
+
throw new UserFacingError('Face version requires owner_skill');
|
|
44
|
+
}
|
|
45
|
+
if (!input.reason || input.reason.trim() === '') {
|
|
46
|
+
throw new UserFacingError('Face version requires a reason (REQ-04)');
|
|
47
|
+
}
|
|
48
|
+
if ((input.command === 'restore' || input.command === 'breakglass') && !input.from) {
|
|
49
|
+
throw new UserFacingError(`face ${input.command} requires the base version (--from <id|vN>)`);
|
|
50
|
+
}
|
|
51
|
+
const restoreLikeCommand = input.command === 'restore' || input.command === 'breakglass';
|
|
52
|
+
if (!restoreLikeCommand && (input.body === undefined || input.body.trim() === '')) {
|
|
53
|
+
throw new UserFacingError(`face ${input.command} requires a body`);
|
|
54
|
+
}
|
|
55
|
+
const run = async () => {
|
|
56
|
+
const deny = guardFailure(input.command, actor, sessionId);
|
|
57
|
+
if (deny !== null) {
|
|
58
|
+
await appendDenied(deps, input.ownerSkill, actor, input.command);
|
|
59
|
+
throw new UserFacingError(deny);
|
|
60
|
+
}
|
|
61
|
+
// REQ-06 AC2: шаблон G17 неопционален для мутации Стюарда — проверка ДО
|
|
62
|
+
// любых записей: без обязательных полей операция целиком не выполняется.
|
|
63
|
+
const g17 = {
|
|
64
|
+
reason: input.reason,
|
|
65
|
+
minimalChange: input.minimalChange,
|
|
66
|
+
boundaries: input.boundaries,
|
|
67
|
+
exampleHelps: input.exampleHelps,
|
|
68
|
+
exampleKeep: input.exampleKeep,
|
|
69
|
+
verification: input.verification,
|
|
70
|
+
rollback: input.rollback,
|
|
71
|
+
};
|
|
72
|
+
if (input.command === 'new') {
|
|
73
|
+
const missing = missingG17Field(g17);
|
|
74
|
+
if (missing !== null) {
|
|
75
|
+
throw new UserFacingError(`Face mutation requires G17 field "${missing}" (REQ-06: the template is not optional)`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// T-09: валидация предложения ДО любых записей — битая ссылка не оставляет
|
|
79
|
+
// половину операции (та же атомарность, что у G17-проверки выше)
|
|
80
|
+
if (input.fromProposal !== undefined) {
|
|
81
|
+
const proposal = await deps.store.get(input.fromProposal);
|
|
82
|
+
if (!proposal) {
|
|
83
|
+
throw new UserFacingError(`Proposal not found: ${input.fromProposal}`);
|
|
84
|
+
}
|
|
85
|
+
if (proposal.facet !== 'proposal') {
|
|
86
|
+
throw new UserFacingError(`Memory object ${input.fromProposal} is not a proposal (facet=proposal required)`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Основа (restore/breakglass) проверяется до op_started: битая ссылка не
|
|
90
|
+
// оставляет незавершённую операцию в журнале (fail fast).
|
|
91
|
+
if (input.from) {
|
|
92
|
+
await resolveBase(deps.store, input.ownerSkill, input.from);
|
|
93
|
+
}
|
|
94
|
+
// 2.17.1 REQ-03: цепочка шагов — журналируемая операция (face-operation.ts);
|
|
95
|
+
// мы уже под lock, engine его не пере-берёт.
|
|
96
|
+
return runFaceMutation(deps, { input, actor });
|
|
97
|
+
};
|
|
98
|
+
return deps.lock ? deps.lock.withLock(run) : run();
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=create-face-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-face-version.js","sourceRoot":"","sources":["../../../src/app/use-cases/create-face-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { MemoryStore } from '../../ports/memory-store.port.js';
|
|
2
|
+
import { EventLog } from '../../ports/event-log.port.js';
|
|
3
|
+
import { Clock } from '../../ports/clock.port.js';
|
|
4
|
+
import { IdGenerator } from '../../ports/id-generator.port.js';
|
|
5
|
+
import { SearchIndex } from '../../ports/search-index.port.js';
|
|
6
|
+
import { RelationLog } from '../../ports/relation-log.port.js';
|
|
7
|
+
import { MemoryObject } from '../../domain/schemas/memory-object-schema.js';
|
|
8
|
+
/** Волна 2.17 REQ-06 (design ADR-2, §«Запись мутации Стюарда»): G17-запись
|
|
9
|
+
* note(history), атомарно создаваемая вместе с версией лица при мутации
|
|
10
|
+
* Стюардом; relation ('mutates', запись, face-версия). Прецедент спец-полей
|
|
11
|
+
* note — scaffold-agent.ts:152: addMemoryObject не пускает G17-поля в extra
|
|
12
|
+
* (guard полей note), поэтому запись сеем напрямую через store.save — она
|
|
13
|
+
* создаётся только версионирующим путём, не свободным add. Вызывается из-под
|
|
14
|
+
* внешнего MemoryLock (createFaceVersion) — lock здесь не пере-берётся. */
|
|
15
|
+
/** Поля шаблона G17 (имена на записи — snake_case дословно из design). */
|
|
16
|
+
export interface MutationG17Input {
|
|
17
|
+
reason: string;
|
|
18
|
+
minimalChange: string;
|
|
19
|
+
boundaries: string;
|
|
20
|
+
exampleHelps: string;
|
|
21
|
+
exampleKeep: string;
|
|
22
|
+
verification: string;
|
|
23
|
+
rollback: string;
|
|
24
|
+
}
|
|
25
|
+
/** REQ-06 AC2: шаблон неопционален — имя первого пустого/отсутствующего поля
|
|
26
|
+
* (null — всё на месте). Общая проверка для createFaceVersion и записи. */
|
|
27
|
+
export declare function missingG17Field(input: Partial<MutationG17Input>): string | null;
|
|
28
|
+
/** boundaries (REQ-06 AC3) фиксирует, что НЕ меняется — суть/рамка агента. */
|
|
29
|
+
export type MutationRecord = MemoryObject & {
|
|
30
|
+
facet: 'history';
|
|
31
|
+
reason: string;
|
|
32
|
+
minimal_change: string;
|
|
33
|
+
boundaries: string;
|
|
34
|
+
example_helps: string;
|
|
35
|
+
example_keep: string;
|
|
36
|
+
verification: string;
|
|
37
|
+
rollback: string;
|
|
38
|
+
};
|
|
39
|
+
export interface CreateMutationRecordDeps {
|
|
40
|
+
store: MemoryStore;
|
|
41
|
+
log: EventLog;
|
|
42
|
+
clock: Clock;
|
|
43
|
+
idGen: IdGenerator;
|
|
44
|
+
index?: SearchIndex;
|
|
45
|
+
relations?: RelationLog;
|
|
46
|
+
}
|
|
47
|
+
export interface CreateMutationRecordInput extends MutationG17Input {
|
|
48
|
+
ownerSkill: string;
|
|
49
|
+
/** Номер создаваемой версии (title: 'mutation: <owner_skill> v<ver>'). */
|
|
50
|
+
version: string;
|
|
51
|
+
faceId: string;
|
|
52
|
+
createdBy: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function createMutationRecord(deps: CreateMutationRecordDeps, input: CreateMutationRecordInput): Promise<MutationRecord>;
|
|
55
|
+
//# sourceMappingURL=create-mutation-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-mutation-record.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/create-mutation-record.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAK5E;;;;;;2EAM2E;AAE3E,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAYD;2EAC2E;AAC3E,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,MAAM,GAAG,IAAI,CAM/E;AAED,8EAA8E;AAC9E,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG;IAC1C,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,wBAAwB,EAC9B,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAiEzB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { governanceDefaults } from '../../domain/governance.js';
|
|
2
|
+
import { UserFacingError } from '../../domain/errors.js';
|
|
3
|
+
import { recordRelation } from './record-relation.js';
|
|
4
|
+
const G17_FIELDS = [
|
|
5
|
+
{ key: 'reason', name: 'reason' },
|
|
6
|
+
{ key: 'minimalChange', name: 'minimal_change' },
|
|
7
|
+
{ key: 'boundaries', name: 'boundaries' },
|
|
8
|
+
{ key: 'exampleHelps', name: 'example_helps' },
|
|
9
|
+
{ key: 'exampleKeep', name: 'example_keep' },
|
|
10
|
+
{ key: 'verification', name: 'verification' },
|
|
11
|
+
{ key: 'rollback', name: 'rollback' },
|
|
12
|
+
];
|
|
13
|
+
/** REQ-06 AC2: шаблон неопционален — имя первого пустого/отсутствующего поля
|
|
14
|
+
* (null — всё на месте). Общая проверка для createFaceVersion и записи. */
|
|
15
|
+
export function missingG17Field(input) {
|
|
16
|
+
for (const { key, name } of G17_FIELDS) {
|
|
17
|
+
const v = input[key];
|
|
18
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
19
|
+
return name;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
export async function createMutationRecord(deps, input) {
|
|
24
|
+
const missing = missingG17Field(input);
|
|
25
|
+
if (missing !== null) {
|
|
26
|
+
throw new UserFacingError(`Face mutation record requires G17 field "${missing}" (REQ-06: the template is not optional)`);
|
|
27
|
+
}
|
|
28
|
+
const now = deps.clock.now();
|
|
29
|
+
const defaults = governanceDefaults(input.createdBy);
|
|
30
|
+
const title = `mutation: ${input.ownerSkill} v${input.version}`;
|
|
31
|
+
const note = {
|
|
32
|
+
id: deps.idGen.generateMemoryId(now, title),
|
|
33
|
+
type: 'note',
|
|
34
|
+
facet: 'history',
|
|
35
|
+
title,
|
|
36
|
+
body: '',
|
|
37
|
+
status: 'active',
|
|
38
|
+
review_state: input.createdBy.startsWith('agent:') ? 'proposed' : 'accepted',
|
|
39
|
+
confidence: 'medium',
|
|
40
|
+
importance: 0.5,
|
|
41
|
+
created_at: now.toISOString(),
|
|
42
|
+
updated_at: now.toISOString(),
|
|
43
|
+
created_by: input.createdBy,
|
|
44
|
+
schema_version: 1,
|
|
45
|
+
source: { kind: 'manual' },
|
|
46
|
+
related: { files: [], docs: [], decisions: [] },
|
|
47
|
+
tags: [],
|
|
48
|
+
superseded_by: null,
|
|
49
|
+
memory_class: defaults.memory_class,
|
|
50
|
+
truth_role: defaults.truth_role,
|
|
51
|
+
lifetime: defaults.lifetime,
|
|
52
|
+
reason: input.reason,
|
|
53
|
+
minimal_change: input.minimalChange,
|
|
54
|
+
boundaries: input.boundaries,
|
|
55
|
+
example_helps: input.exampleHelps,
|
|
56
|
+
example_keep: input.exampleKeep,
|
|
57
|
+
verification: input.verification,
|
|
58
|
+
rollback: input.rollback,
|
|
59
|
+
};
|
|
60
|
+
await deps.store.save(note);
|
|
61
|
+
await deps.log.append({
|
|
62
|
+
id: deps.idGen.generateEventId(now),
|
|
63
|
+
type: 'memory.added',
|
|
64
|
+
timestamp: now.toISOString(),
|
|
65
|
+
actor: input.createdBy,
|
|
66
|
+
payload: { memory_id: note.id, type: 'note' },
|
|
67
|
+
});
|
|
68
|
+
if (deps.index) {
|
|
69
|
+
await deps.index.indexObject(note);
|
|
70
|
+
}
|
|
71
|
+
// Та же lock-транзакция, что и версия: lock не передаём (FsMemoryLock не
|
|
72
|
+
// реентерабелен, внешний withLock держит createFaceVersion).
|
|
73
|
+
if (deps.relations) {
|
|
74
|
+
await recordRelation({ relations: deps.relations, idGen: deps.idGen }, now, note.id, 'mutates', input.faceId, 'system');
|
|
75
|
+
}
|
|
76
|
+
return note;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=create-mutation-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-mutation-record.js","sourceRoot":"","sources":["../../../src/app/use-cases/create-mutation-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MemoryStore } from '../../ports/memory-store.port.js';
|
|
2
|
+
import { EventLog } from '../../ports/event-log.port.js';
|
|
3
|
+
import { Clock } from '../../ports/clock.port.js';
|
|
4
|
+
import { IdGenerator } from '../../ports/id-generator.port.js';
|
|
5
|
+
import { SearchIndex } from '../../ports/search-index.port.js';
|
|
6
|
+
import { MemoryLock } from '../../ports/memory-lock.port.js';
|
|
7
|
+
import type { ProposalObject } from './save-proposal.js';
|
|
8
|
+
/** Волна 2.17 T-09 (REQ-09, design §«Сигнал-фасет proposal»): доставка
|
|
9
|
+
* предложения — явный отдельный шаг `wolf propose deliver <id>`. Только
|
|
10
|
+
* заполняет delivered_at и журналирует memory.proposal.delivered {id,
|
|
11
|
+
* addressee}: императивный текст НЕ применяется, лицо/память адресата не
|
|
12
|
+
* меняются, полномочия автора не меняются — предложение остаётся сигналом
|
|
13
|
+
* до решения Стюарда/владельца. Сохранение ≠ доставка ≠ обработка (AC4):
|
|
14
|
+
* повторная доставка — отказ. */
|
|
15
|
+
export interface DeliverProposalDeps {
|
|
16
|
+
store: MemoryStore;
|
|
17
|
+
log: EventLog;
|
|
18
|
+
clock: Clock;
|
|
19
|
+
idGen: IdGenerator;
|
|
20
|
+
index?: SearchIndex;
|
|
21
|
+
lock?: MemoryLock;
|
|
22
|
+
/** Атрибуция доставляющего — только env (WOLF_ACTOR). */
|
|
23
|
+
env?: NodeJS.ProcessEnv;
|
|
24
|
+
}
|
|
25
|
+
export declare function deliverProposal(deps: DeliverProposalDeps, id: string): Promise<ProposalObject>;
|
|
26
|
+
//# sourceMappingURL=deliver-proposal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliver-proposal.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/deliver-proposal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAI7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;iCAMiC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAiCpG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { resolveCreatedBy } from '../../domain/actor.js';
|
|
2
|
+
import { UserFacingError } from '../../domain/errors.js';
|
|
3
|
+
export async function deliverProposal(deps, id) {
|
|
4
|
+
const actor = resolveCreatedBy(undefined, deps.env ?? process.env);
|
|
5
|
+
const run = async () => {
|
|
6
|
+
const obj = (await deps.store.get(id));
|
|
7
|
+
if (!obj)
|
|
8
|
+
throw new UserFacingError(`Memory object not found: ${id}`);
|
|
9
|
+
if (obj.facet !== 'proposal') {
|
|
10
|
+
throw new UserFacingError(`Memory object ${id} is not a proposal (facet: ${obj.facet ?? '—'})`);
|
|
11
|
+
}
|
|
12
|
+
if (obj.delivered_at !== undefined) {
|
|
13
|
+
throw new UserFacingError(`Proposal ${id} was already delivered at ${obj.delivered_at} (saving ≠ delivery ≠ processing; delivery is a one-time step)`);
|
|
14
|
+
}
|
|
15
|
+
const now = deps.clock.now();
|
|
16
|
+
// delivered_at вне схемы сохранения (type-schema-builder) — пишется только
|
|
17
|
+
// здесь; passthrough-схема объекта пропускает ключ через frontmatter
|
|
18
|
+
const updated = await deps.store.update(id, {
|
|
19
|
+
delivered_at: now.toISOString(),
|
|
20
|
+
});
|
|
21
|
+
await deps.log.append({
|
|
22
|
+
id: deps.idGen.generateEventId(now),
|
|
23
|
+
type: 'memory.proposal.delivered',
|
|
24
|
+
timestamp: now.toISOString(),
|
|
25
|
+
actor,
|
|
26
|
+
payload: { id, addressee: obj.addressee },
|
|
27
|
+
});
|
|
28
|
+
if (deps.index) {
|
|
29
|
+
await deps.index.indexObject(updated);
|
|
30
|
+
}
|
|
31
|
+
return updated;
|
|
32
|
+
};
|
|
33
|
+
return deps.lock ? deps.lock.withLock(run) : run();
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=deliver-proposal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliver-proposal.js","sourceRoot":"","sources":["../../../src/app/use-cases/deliver-proposal.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAsBzD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyB,EAAE,EAAU;IACzE,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,KAAK,IAA6B,EAAE;QAC9C,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAA0B,CAAC;QAChE,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,eAAe,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,GAAG,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,IAAI,eAAe,CAAC,iBAAiB,EAAE,8BAA8B,GAAG,CAAC,KAAK,IAAI,GAAG,GAAG,CAAC,CAAC;QAClG,CAAC;QACD,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,eAAe,CACvB,YAAY,EAAE,6BAA6B,GAAG,CAAC,YAAY,gEAAgE,CAC5H,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,2EAA2E;QAC3E,qEAAqE;QACrE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE;YAC1C,YAAY,EAAE,GAAG,CAAC,WAAW,EAAE;SACP,CAAC,CAAC;QAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YACpB,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC;YACnC,IAAI,EAAE,2BAA2B;YACjC,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;YAC5B,KAAK;YACL,OAAO,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;SAC1C,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,OAAyB,CAAC;IACnC,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MemoryStore } from '../../ports/memory-store.port.js';
|
|
2
|
+
import { EventLog } from '../../ports/event-log.port.js';
|
|
3
|
+
import { Clock } from '../../ports/clock.port.js';
|
|
4
|
+
import { IdGenerator } from '../../ports/id-generator.port.js';
|
|
5
|
+
import { SearchIndex } from '../../ports/search-index.port.js';
|
|
6
|
+
import { MemoryLock } from '../../ports/memory-lock.port.js';
|
|
7
|
+
export interface EditMemoryObjectDeps {
|
|
8
|
+
store: MemoryStore;
|
|
9
|
+
log: EventLog;
|
|
10
|
+
clock: Clock;
|
|
11
|
+
idGen: IdGenerator;
|
|
12
|
+
index?: SearchIndex;
|
|
13
|
+
lock?: MemoryLock;
|
|
14
|
+
}
|
|
15
|
+
export interface EditMemoryObjectInput {
|
|
16
|
+
id: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
body?: string;
|
|
19
|
+
actor: string;
|
|
20
|
+
}
|
|
21
|
+
export interface EditMemoryObjectResult {
|
|
22
|
+
id: string;
|
|
23
|
+
fields: Array<'title' | 'body'>;
|
|
24
|
+
}
|
|
25
|
+
export declare function editMemoryObject(deps: EditMemoryObjectDeps, input: EditMemoryObjectInput): Promise<EditMemoryObjectResult>;
|
|
26
|
+
//# sourceMappingURL=edit-memory-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-memory-object.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/edit-memory-object.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAa7D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CA6CjC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { UserFacingError } from '../../domain/errors.js';
|
|
2
|
+
// wolf edit (спека 2.13 §6.1): правка title/body с diff-аудитом — отдельное
|
|
3
|
+
// событие memory.edited на каждое изменённое поле, before/after обрезаны до
|
|
4
|
+
// 200 симв (прецедент target-обрезки волны 0, session-metrics-log.ts:482).
|
|
5
|
+
// 2.17.1 REQ-04 (R05, design §7): edit вынесен из CLI в use-case слой —
|
|
6
|
+
// face-тип запрещён (лицо меняется только версионирующим путём wolf face);
|
|
7
|
+
// guard здесь, не в CLI (AC-4: негативный сценарий на уровне use-case).
|
|
8
|
+
const CLIP = 200;
|
|
9
|
+
const clip = (s) => (s.length > CLIP ? s.slice(0, CLIP) : s);
|
|
10
|
+
export async function editMemoryObject(deps, input) {
|
|
11
|
+
const existing = await deps.store.get(input.id);
|
|
12
|
+
if (!existing)
|
|
13
|
+
throw new UserFacingError(`Memory object not found: ${input.id}`);
|
|
14
|
+
if (existing.type === 'face') {
|
|
15
|
+
throw new UserFacingError('type "face" cannot be edited: faces are versioned, use "wolf face" commands (new | restore | breakglass)');
|
|
16
|
+
}
|
|
17
|
+
const fields = [];
|
|
18
|
+
if (input.title !== undefined) {
|
|
19
|
+
if (input.title.trim() === '')
|
|
20
|
+
throw new UserFacingError('Title must not be empty');
|
|
21
|
+
fields.push('title');
|
|
22
|
+
}
|
|
23
|
+
if (input.body !== undefined) {
|
|
24
|
+
if (input.body.trim() === '')
|
|
25
|
+
throw new UserFacingError('Body must not be empty');
|
|
26
|
+
fields.push('body');
|
|
27
|
+
}
|
|
28
|
+
if (fields.length === 0)
|
|
29
|
+
throw new UserFacingError('Nothing to edit: pass a title and/or body');
|
|
30
|
+
const patch = {};
|
|
31
|
+
if (input.title !== undefined)
|
|
32
|
+
patch.title = input.title;
|
|
33
|
+
if (input.body !== undefined)
|
|
34
|
+
patch.body = input.body;
|
|
35
|
+
const run = async () => {
|
|
36
|
+
const updated = await deps.store.update(input.id, patch);
|
|
37
|
+
const now = deps.clock.now();
|
|
38
|
+
for (const field of fields) {
|
|
39
|
+
await deps.log.append({
|
|
40
|
+
id: deps.idGen.generateEventId(now),
|
|
41
|
+
type: 'memory.edited',
|
|
42
|
+
timestamp: now.toISOString(),
|
|
43
|
+
actor: input.actor,
|
|
44
|
+
payload: {
|
|
45
|
+
memory_id: input.id,
|
|
46
|
+
field,
|
|
47
|
+
before: clip(existing[field]),
|
|
48
|
+
after: clip(input[field]),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
await deps.index?.indexObject(updated);
|
|
53
|
+
return { id: input.id, fields };
|
|
54
|
+
};
|
|
55
|
+
return deps.lock ? deps.lock.withLock(run) : run();
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=edit-memory-object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-memory-object.js","sourceRoot":"","sources":["../../../src/app/use-cases/edit-memory-object.ts"],"names":[],"mappings":"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"}
|