mister-wolf 2.16.2 → 2.17.0

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.
Files changed (96) hide show
  1. package/README.md +4 -4
  2. package/README.ru.md +4 -4
  3. package/dist/adapters/cli/cli-entry.d.ts.map +1 -1
  4. package/dist/adapters/cli/cli-entry.js +17 -0
  5. package/dist/adapters/cli/cli-entry.js.map +1 -1
  6. package/dist/adapters/cli/commands/face.d.ts +3 -0
  7. package/dist/adapters/cli/commands/face.d.ts.map +1 -0
  8. package/dist/adapters/cli/commands/face.js +194 -0
  9. package/dist/adapters/cli/commands/face.js.map +1 -0
  10. package/dist/adapters/cli/commands/memory-add.d.ts.map +1 -1
  11. package/dist/adapters/cli/commands/memory-add.js +1 -1
  12. package/dist/adapters/cli/commands/memory-add.js.map +1 -1
  13. package/dist/adapters/cli/commands/memory-doctor.d.ts +20 -0
  14. package/dist/adapters/cli/commands/memory-doctor.d.ts.map +1 -1
  15. package/dist/adapters/cli/commands/memory-doctor.js +87 -3
  16. package/dist/adapters/cli/commands/memory-doctor.js.map +1 -1
  17. package/dist/adapters/cli/commands/memory-init.d.ts.map +1 -1
  18. package/dist/adapters/cli/commands/memory-init.js +11 -53
  19. package/dist/adapters/cli/commands/memory-init.js.map +1 -1
  20. package/dist/adapters/cli/commands/memory-list.d.ts.map +1 -1
  21. package/dist/adapters/cli/commands/memory-list.js +1 -1
  22. package/dist/adapters/cli/commands/memory-list.js.map +1 -1
  23. package/dist/adapters/cli/commands/memory-search.d.ts.map +1 -1
  24. package/dist/adapters/cli/commands/memory-search.js +1 -1
  25. package/dist/adapters/cli/commands/memory-search.js.map +1 -1
  26. package/dist/adapters/cli/commands/memory-sync.js +1 -1
  27. package/dist/adapters/cli/commands/memory-sync.js.map +1 -1
  28. package/dist/adapters/cli/commands/propose.d.ts +3 -0
  29. package/dist/adapters/cli/commands/propose.d.ts.map +1 -0
  30. package/dist/adapters/cli/commands/propose.js +94 -0
  31. package/dist/adapters/cli/commands/propose.js.map +1 -0
  32. package/dist/adapters/cli/type-command-generator.d.ts.map +1 -1
  33. package/dist/adapters/cli/type-command-generator.js +2 -0
  34. package/dist/adapters/cli/type-command-generator.js.map +1 -1
  35. package/dist/app/use-cases/add-memory-object.d.ts +5 -0
  36. package/dist/app/use-cases/add-memory-object.d.ts.map +1 -1
  37. package/dist/app/use-cases/add-memory-object.js +24 -5
  38. package/dist/app/use-cases/add-memory-object.js.map +1 -1
  39. package/dist/app/use-cases/create-face-version.d.ts +79 -0
  40. package/dist/app/use-cases/create-face-version.d.ts.map +1 -0
  41. package/dist/app/use-cases/create-face-version.js +224 -0
  42. package/dist/app/use-cases/create-face-version.js.map +1 -0
  43. package/dist/app/use-cases/create-mutation-record.d.ts +55 -0
  44. package/dist/app/use-cases/create-mutation-record.d.ts.map +1 -0
  45. package/dist/app/use-cases/create-mutation-record.js +78 -0
  46. package/dist/app/use-cases/create-mutation-record.js.map +1 -0
  47. package/dist/app/use-cases/deliver-proposal.d.ts +26 -0
  48. package/dist/app/use-cases/deliver-proposal.d.ts.map +1 -0
  49. package/dist/app/use-cases/deliver-proposal.js +35 -0
  50. package/dist/app/use-cases/deliver-proposal.js.map +1 -0
  51. package/dist/app/use-cases/migrate-faces.d.ts +47 -0
  52. package/dist/app/use-cases/migrate-faces.d.ts.map +1 -0
  53. package/dist/app/use-cases/migrate-faces.js +65 -0
  54. package/dist/app/use-cases/migrate-faces.js.map +1 -0
  55. package/dist/app/use-cases/record-relation.d.ts.map +1 -1
  56. package/dist/app/use-cases/record-relation.js +6 -0
  57. package/dist/app/use-cases/record-relation.js.map +1 -1
  58. package/dist/app/use-cases/save-proposal.d.ts +49 -0
  59. package/dist/app/use-cases/save-proposal.d.ts.map +1 -0
  60. package/dist/app/use-cases/save-proposal.js +32 -0
  61. package/dist/app/use-cases/save-proposal.js.map +1 -0
  62. package/dist/app/use-cases/scaffold-agent.d.ts.map +1 -1
  63. package/dist/app/use-cases/scaffold-agent.js +20 -52
  64. package/dist/app/use-cases/scaffold-agent.js.map +1 -1
  65. package/dist/app/use-cases/seed-base-playbooks.d.ts +16 -95
  66. package/dist/app/use-cases/seed-base-playbooks.d.ts.map +1 -1
  67. package/dist/app/use-cases/seed-base-playbooks.js +22 -23
  68. package/dist/app/use-cases/seed-base-playbooks.js.map +1 -1
  69. package/dist/domain/facet-colors.d.ts.map +1 -1
  70. package/dist/domain/facet-colors.js +1 -0
  71. package/dist/domain/facet-colors.js.map +1 -1
  72. package/dist/domain/memory-types.d.ts +32 -1
  73. package/dist/domain/memory-types.d.ts.map +1 -1
  74. package/dist/domain/memory-types.js +32 -2
  75. package/dist/domain/memory-types.js.map +1 -1
  76. package/dist/domain/schemas/memory-event-schema.d.ts +4 -0
  77. package/dist/domain/schemas/memory-event-schema.d.ts.map +1 -1
  78. package/dist/domain/schemas/memory-event-schema.js +30 -1
  79. package/dist/domain/schemas/memory-event-schema.js.map +1 -1
  80. package/dist/domain/schemas/relation-schema.d.ts +6 -2
  81. package/dist/domain/schemas/relation-schema.d.ts.map +1 -1
  82. package/dist/domain/schemas/relation-schema.js +8 -0
  83. package/dist/domain/schemas/relation-schema.js.map +1 -1
  84. package/dist/domain/schemas/session-checkpoint-schema.d.ts +1 -1
  85. package/dist/domain/type-schema-builder.d.ts +4 -2
  86. package/dist/domain/type-schema-builder.d.ts.map +1 -1
  87. package/dist/domain/type-schema-builder.js +32 -1
  88. package/dist/domain/type-schema-builder.js.map +1 -1
  89. package/package.json +1 -1
  90. package/templates/.wolf/router.log +1 -1
  91. package/templates/base/agents/executor-lead.md +1 -0
  92. package/templates/base/agents/steward.md +1 -1
  93. package/templates/base/agents/worker-implementer.md +1 -0
  94. package/templates/base/agents/worker-researcher.md +1 -0
  95. package/templates/base/agents/worker-reviewer.md +1 -0
  96. package/templates/opencode/plugins/wolf-router.ts +60 -10
@@ -0,0 +1,79 @@
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 { 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
+ /** Волна 2.17 REQ-03/REQ-04 (design §«Механика версий», §Guard): единая
11
+ * версионирующая механика лиц — guard, номер версии, supersede head, журнал;
12
+ * всё под внешним MemoryLock (прецедент tool-librarian.ts:167: вложенные
13
+ * addMemoryObject/supersedeMemoryObject идут с lock: undefined).
14
+ * REQ-06 (design §«Запись мутации Стюарда»): мутация Стюарда (initiator
15
+ * 'steward') атомарно создаёт G17-запись + relation 'mutates' → версия.
16
+ * T-05: 'migrate'/'seed' — служебные пути (вход migrateFaces/посева base-set,
17
+ * design §Guard «посев идёт внутренним путём с initiator: 'seed'»): guard
18
+ * полномочий не применяется, содержание задаёт вызывающий. */
19
+ export type FaceCommand = 'new' | 'restore' | 'breakglass' | 'migrate' | 'seed';
20
+ export type FaceInitiator = 'steward' | 'owner' | 'breakglass' | 'migration' | 'seed';
21
+ /** Поля типа face поверх MemoryObject (декларация — memory-types.ts, T-01). */
22
+ export interface FaceFields {
23
+ owner_skill: string;
24
+ /** '1','2',… — номер назначает эта команда под lock. */
25
+ version: string;
26
+ /** id версии-основы; отсутствует у первой версии (optional, не null). */
27
+ based_on?: string;
28
+ reason: string;
29
+ initiator: FaceInitiator;
30
+ }
31
+ export type FaceObject = MemoryObject & FaceFields;
32
+ export interface CreateFaceVersionDeps {
33
+ store: MemoryStore;
34
+ log: EventLog;
35
+ clock: Clock;
36
+ idGen: IdGenerator;
37
+ index?: SearchIndex;
38
+ lock?: MemoryLock;
39
+ relations?: RelationLog;
40
+ declarations?: readonly MemoryTypeDeclaration[];
41
+ /** Атрибуция только из env (WOLF_ACTOR / WOLF_SESSION), по умолчанию process.env.
42
+ * Параметра-актёра у API нет: подмена инициатора (--created-by-подобная)
43
+ * исключена структурно (design §Guard, F-04). */
44
+ env?: NodeJS.ProcessEnv;
45
+ }
46
+ export interface CreateFaceVersionInput {
47
+ command: FaceCommand;
48
+ ownerSkill: string;
49
+ /** REQ-04 AC2: причина обязательна — без неё операция падает. */
50
+ reason: string;
51
+ /** Тело лица; для new обязательно, restore/breakglass берут из версии-основы. */
52
+ body?: string;
53
+ title?: string;
54
+ tags?: string[];
55
+ /** Основа: id записи или номер версии ('v2'/'2'). Обязателен для restore/breakglass. */
56
+ from?: string;
57
+ /** REQ-06 (G17): обязательны для command='new' (мутация Стюарда); для
58
+ * restore/breakglass шаблон не применяется (ADR-2: только мутации Стюарда). */
59
+ minimalChange?: string;
60
+ boundaries?: string;
61
+ exampleHelps?: string;
62
+ exampleKeep?: string;
63
+ verification?: string;
64
+ rollback?: string;
65
+ /** T-09 (design §«Механика версий», строка 88): id предложения, породившего
66
+ * версию — записывает relation ('proposes', proposal, faceNew). Связь только
67
+ * фиксируется: применение предложения остаётся решением Стюарда (REQ-09). */
68
+ fromProposal?: string;
69
+ }
70
+ export interface CreateFaceVersionResult {
71
+ face: FaceObject;
72
+ /** Прежняя активная версия, superseded этой операцией; null у первой версии. */
73
+ supersededId: string | null;
74
+ /** G17-запись мутации (REQ-06): id note(history); null, если мутация не
75
+ * Стюардом (restore/breakglass). */
76
+ mutationRecordId: string | null;
77
+ }
78
+ export declare function createFaceVersion(deps: CreateFaceVersionDeps, input: CreateFaceVersionInput): Promise<CreateFaceVersionResult>;
79
+ //# 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":"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;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAS5E;;;;;;;;8DAQ8D;AAC9D,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAChF,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM,CAAC;AAEtF,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,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,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,YAAY,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAChD;;qDAEiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;mFAC+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;iFAE6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,gFAAgF;IAChF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;wCACoC;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAgFD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,EAC3B,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CAmLlC"}
@@ -0,0 +1,224 @@
1
+ import { resolveCreatedBy, resolveSessionId } from '../../domain/actor.js';
2
+ import { UserFacingError } from '../../domain/errors.js';
3
+ import { addMemoryObject } from './add-memory-object.js';
4
+ import { supersedeMemoryObject } from './supersede-memory-object.js';
5
+ import { createMutationRecord, missingG17Field } from './create-mutation-record.js';
6
+ import { recordRelation } from './record-relation.js';
7
+ const INITIATOR_BY_COMMAND = {
8
+ new: 'steward',
9
+ restore: 'owner',
10
+ breakglass: 'breakglass',
11
+ migrate: 'migration',
12
+ seed: 'seed',
13
+ };
14
+ function asFace(obj) {
15
+ return obj;
16
+ }
17
+ async function facesOfOwner(store, ownerSkill) {
18
+ return (await store.list({ type: 'face' })).filter((o) => asFace(o).owner_skill === ownerSkill).map(asFace);
19
+ }
20
+ /** Активная (head) версия владельца; null — владельца ещё нет. Дубликаты активных
21
+ * ловит doctor (NFR-02); здесь детерминированно берётся старшая версия. */
22
+ async function activeFace(store, ownerSkill) {
23
+ const active = (await facesOfOwner(store, ownerSkill)).filter((f) => f.status === 'active');
24
+ if (active.length === 0)
25
+ return null;
26
+ return active.sort((a, b) => Number(b.version) - Number(a.version))[0];
27
+ }
28
+ /** Резолв ссылки на основу: mem_-id напрямую, иначе номер версии ('v2'/'2'). */
29
+ async function resolveBase(store, ownerSkill, ref) {
30
+ if (ref.startsWith('mem_')) {
31
+ const obj = await store.get(ref);
32
+ if (!obj || obj.type !== 'face' || asFace(obj).owner_skill !== ownerSkill) {
33
+ throw new UserFacingError(`Face version not found for ${ownerSkill}: ${ref}`);
34
+ }
35
+ return asFace(obj);
36
+ }
37
+ const n = ref.replace(/^v/, '');
38
+ const found = (await facesOfOwner(store, ownerSkill)).filter((f) => f.version === n);
39
+ if (found.length === 0)
40
+ throw new UserFacingError(`Face version not found for ${ownerSkill}: ${ref}`);
41
+ return found.sort((a, b) => Number(b.version) - Number(a.version))[0];
42
+ }
43
+ /** Guard (design §Guard): new — строго agent:steward; restore/breakglass — user:*;
44
+ * breakglass дополнительно отказывает из агент-сессии (WOLF_SESSION=opc-*).
45
+ * migrate/seed — служебные пути (T-05): без проверки полномочий — вход
46
+ * внутренний (migrateFaces / посев base-set), содержание переносится дословно.
47
+ * null — доступ разрешён. */
48
+ function guardFailure(command, actor, sessionId) {
49
+ if (command === 'migrate' || command === 'seed')
50
+ return null;
51
+ if (command === 'new') {
52
+ if (actor !== 'agent:steward') {
53
+ return `Face mutation is steward-only: actor "${actor}" is not agent:steward (attribution is env-only, WOLF_ACTOR)`;
54
+ }
55
+ return null;
56
+ }
57
+ if (!actor.startsWith('user:')) {
58
+ return `face ${command} is owner-only: actor "${actor}" is not user:* (attribution is env-only, WOLF_ACTOR)`;
59
+ }
60
+ if (command === 'breakglass' && sessionId !== null && sessionId.startsWith('opc-')) {
61
+ return 'breakglass is not available from an agent session (WOLF_SESSION=opc-*)';
62
+ }
63
+ return null;
64
+ }
65
+ async function appendDenied(deps, ownerSkill, actor, command) {
66
+ const now = deps.clock.now();
67
+ const event = {
68
+ id: deps.idGen.generateEventId(now),
69
+ type: 'memory.face.denied',
70
+ timestamp: now.toISOString(),
71
+ actor,
72
+ payload: { owner_skill: ownerSkill, actor, command },
73
+ };
74
+ await deps.log.append(event);
75
+ }
76
+ export async function createFaceVersion(deps, input) {
77
+ const env = deps.env ?? process.env;
78
+ const actor = resolveCreatedBy(undefined, env);
79
+ const sessionId = resolveSessionId(env);
80
+ if (!input.ownerSkill || input.ownerSkill.trim() === '') {
81
+ throw new UserFacingError('Face version requires owner_skill');
82
+ }
83
+ if (!input.reason || input.reason.trim() === '') {
84
+ throw new UserFacingError('Face version requires a reason (REQ-04)');
85
+ }
86
+ if ((input.command === 'restore' || input.command === 'breakglass') && !input.from) {
87
+ throw new UserFacingError(`face ${input.command} requires the base version (--from <id|vN>)`);
88
+ }
89
+ const restoreLikeCommand = input.command === 'restore' || input.command === 'breakglass';
90
+ if (!restoreLikeCommand && (input.body === undefined || input.body.trim() === '')) {
91
+ throw new UserFacingError(`face ${input.command} requires a body`);
92
+ }
93
+ const run = async () => {
94
+ const deny = guardFailure(input.command, actor, sessionId);
95
+ if (deny !== null) {
96
+ await appendDenied(deps, input.ownerSkill, actor, input.command);
97
+ throw new UserFacingError(deny);
98
+ }
99
+ // REQ-06 AC2: шаблон G17 неопционален для мутации Стюарда — проверка ДО
100
+ // любых записей: без обязательных полей операция целиком не выполняется.
101
+ const g17 = {
102
+ reason: input.reason,
103
+ minimalChange: input.minimalChange,
104
+ boundaries: input.boundaries,
105
+ exampleHelps: input.exampleHelps,
106
+ exampleKeep: input.exampleKeep,
107
+ verification: input.verification,
108
+ rollback: input.rollback,
109
+ };
110
+ if (input.command === 'new') {
111
+ const missing = missingG17Field(g17);
112
+ if (missing !== null) {
113
+ throw new UserFacingError(`Face mutation requires G17 field "${missing}" (REQ-06: the template is not optional)`);
114
+ }
115
+ }
116
+ // T-09: валидация предложения ДО любых записей — битая ссылка не оставляет
117
+ // половину операции (та же атомарность, что у G17-проверки выше)
118
+ if (input.fromProposal !== undefined) {
119
+ const proposal = await deps.store.get(input.fromProposal);
120
+ if (!proposal) {
121
+ throw new UserFacingError(`Proposal not found: ${input.fromProposal}`);
122
+ }
123
+ if (proposal.facet !== 'proposal') {
124
+ throw new UserFacingError(`Memory object ${input.fromProposal} is not a proposal (facet=proposal required)`);
125
+ }
126
+ }
127
+ // Номер версии и head — строго под lock: параллельные вызовы сериализуются.
128
+ const cur = await activeFace(deps.store, input.ownerSkill);
129
+ const base = input.from ? await resolveBase(deps.store, input.ownerSkill, input.from) : cur;
130
+ const nextVersion = (await facesOfOwner(deps.store, input.ownerSkill)).reduce((m, f) => Math.max(m, Number(f.version) || 0), 0) + 1;
131
+ const restoreLike = input.command === 'restore' || input.command === 'breakglass';
132
+ const source = restoreLike ? base : null;
133
+ const title = restoreLike ? source.title : (input.title ?? `Face: ${input.ownerSkill}`);
134
+ const body = restoreLike ? source.body : input.body;
135
+ const tags = restoreLike ? source.tags : (input.tags ?? []);
136
+ const extra = {
137
+ owner_skill: input.ownerSkill,
138
+ version: String(nextVersion),
139
+ reason: input.reason,
140
+ initiator: INITIATOR_BY_COMMAND[input.command],
141
+ };
142
+ if (base)
143
+ extra.based_on = base.id;
144
+ // lock не передаём: мы уже внутри deps.lock.withLock (FsMemoryLock не реентерабелен)
145
+ const { object } = await addMemoryObject({
146
+ store: deps.store,
147
+ log: deps.log,
148
+ clock: deps.clock,
149
+ idGen: deps.idGen,
150
+ index: deps.index,
151
+ declarations: deps.declarations,
152
+ }, { type: 'face', title, body, tags, createdBy: actor, extra, internalFacePath: true });
153
+ const face = asFace(object);
154
+ let supersededId = null;
155
+ if (cur && cur.id !== face.id) {
156
+ await supersedeMemoryObject({ store: deps.store, log: deps.log, clock: deps.clock, idGen: deps.idGen, index: deps.index }, cur.id, face.id);
157
+ supersededId = cur.id;
158
+ }
159
+ // REQ-06 (design §«Механика версий»): initiator 'steward' → атомарно
160
+ // G17-запись note(history) + relation 'mutates' → версия; та же
161
+ // lock-транзакция (внутренние вызовы без lock).
162
+ let mutationRecordId = null;
163
+ if (INITIATOR_BY_COMMAND[input.command] === 'steward') {
164
+ const note = await createMutationRecord({
165
+ store: deps.store,
166
+ log: deps.log,
167
+ clock: deps.clock,
168
+ idGen: deps.idGen,
169
+ index: deps.index,
170
+ relations: deps.relations,
171
+ }, {
172
+ ownerSkill: input.ownerSkill,
173
+ version: face.version,
174
+ faceId: face.id,
175
+ createdBy: actor,
176
+ reason: g17.reason,
177
+ minimalChange: g17.minimalChange,
178
+ boundaries: g17.boundaries,
179
+ exampleHelps: g17.exampleHelps,
180
+ exampleKeep: g17.exampleKeep,
181
+ verification: g17.verification,
182
+ rollback: g17.rollback,
183
+ });
184
+ mutationRecordId = note.id;
185
+ }
186
+ // T-09 (design §«Механика версий», строка 88): --from-proposal → relation
187
+ // ('proposes', proposal, faceNew); только связь, не применение (REQ-09)
188
+ if (input.fromProposal !== undefined) {
189
+ await recordRelation({ relations: deps.relations, idGen: deps.idGen }, deps.clock.now(), input.fromProposal, 'proposes', face.id, 'system');
190
+ }
191
+ // Design §События журнала: versioned — на КАЖДУЮ версию (включая breakglass,
192
+ // REQ-07 «результат = новая версия»); breakglass дополнительно журналируется
193
+ // own-событием в составе самой операции (REQ-07 AC2). Порядок: versioned, затем breakglass.
194
+ const now = deps.clock.now();
195
+ const versionPayload = {
196
+ owner_skill: input.ownerSkill,
197
+ from: supersededId,
198
+ new: face.id,
199
+ initiator: INITIATOR_BY_COMMAND[input.command],
200
+ reason: input.reason,
201
+ };
202
+ const versioned = {
203
+ id: deps.idGen.generateEventId(now),
204
+ type: 'memory.face.versioned',
205
+ timestamp: now.toISOString(),
206
+ actor,
207
+ payload: versionPayload,
208
+ };
209
+ await deps.log.append(versioned);
210
+ if (input.command === 'breakglass') {
211
+ const breakglass = {
212
+ id: deps.idGen.generateEventId(now),
213
+ type: 'memory.face.breakglass',
214
+ timestamp: now.toISOString(),
215
+ actor,
216
+ payload: versionPayload,
217
+ };
218
+ await deps.log.append(breakglass);
219
+ }
220
+ return { face, supersededId, mutationRecordId };
221
+ };
222
+ return deps.lock ? deps.lock.withLock(run) : run();
223
+ }
224
+ //# 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,47 @@
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 { MemoryTypeDeclaration } from '../../domain/memory-types.js';
8
+ /** Волна 2.17 T-05 (design §«Миграция legacy-playbook → face», REQ-02):
9
+ * идемпотентная физическая миграция legacy-записей лица в контракт face.
10
+ * Кандидат — запись, читаемая как note + facet howto + непустой owner_skill
11
+ * (включая legacy-тип playbook: alias-резолв P211 отдаёт его как note+howto);
12
+ * howto без owner_skill не мигрируется (AC4 — не всякий howto есть лицо).
13
+ *
14
+ * Поэтапность (§Отказов): каждый owner_skill — независимая итерация; падение
15
+ * на N-м не откатывает N-1 (supersede каждой записи уже завершён), ошибка
16
+ * попадает в report.failed, обход продолжается. Внешний lock НЕ держим —
17
+ * каждую версию создаёт createFaceVersion под собственным lock (FsMemoryLock
18
+ * не реентерабелен, прецедент tool-librarian.ts:167). */
19
+ export interface MigrateFacesDeps {
20
+ store: MemoryStore;
21
+ log: EventLog;
22
+ clock: Clock;
23
+ idGen: IdGenerator;
24
+ index?: SearchIndex;
25
+ lock?: MemoryLock;
26
+ declarations?: readonly MemoryTypeDeclaration[];
27
+ env?: NodeJS.ProcessEnv;
28
+ }
29
+ export interface MigrateOutcome {
30
+ ownerSkill: string;
31
+ action: 'migrated' | 'skipped';
32
+ faceId?: string;
33
+ headId?: string;
34
+ reason: string;
35
+ }
36
+ export interface MigrateFacesReport {
37
+ outcomes: MigrateOutcome[];
38
+ /** REQ-02 AC4: howto-записи без owner_skill — не кандидаты (skip с отчётом). */
39
+ skippedHowtoIds: string[];
40
+ /** §Отказов: ошибки по владельцам; уже мигрированные N-1 остаются на месте. */
41
+ failed: {
42
+ ownerSkill: string;
43
+ error: string;
44
+ }[];
45
+ }
46
+ export declare function migrateFaces(deps: MigrateFacesDeps): Promise<MigrateFacesReport>;
47
+ //# sourceMappingURL=migrate-faces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-faces.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/migrate-faces.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;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAKrE;;;;;;;;;;yDAUyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,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,YAAY,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,gFAAgF;IAChF,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAQD,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwDtF"}